diff --git a/packages/ui/cypress/fixtures/watchAccounts/watchMultisigs.ts b/packages/ui/cypress/fixtures/watchAccounts/watchMultisigs.ts
new file mode 100644
index 00000000..c5693ad4
--- /dev/null
+++ b/packages/ui/cypress/fixtures/watchAccounts/watchMultisigs.ts
@@ -0,0 +1,18 @@
+import { watchSignatories } from './watchSignatories'
+
+export const watchMultisigs = {
+ 'multisig-with-pure': {
+ name: 'Multisig With Pure',
+ address: '5Fa3UUF3S6SVdXZtPrCw2tGUqxJiRJLxEGfujozfZ4xFeAKn',
+ pureAddress: '5EfdqwwuyjjtEa4UhdjbZJu3UxHEHbzh8LMRvE13xTD7z6Wd',
+ threshold: 2,
+ signatories: [watchSignatories[0].address, watchSignatories[1].address]
+ },
+
+ 'multisig-without-pure': {
+ name: 'Multisig No Pure',
+ address: '5GysXAKXrGjNvpQruKWH3RwxtYrJqqWLN1A15gUMht6EXmzC',
+ threshold: 2,
+ signatories: [watchSignatories[2].address, watchSignatories[3].address]
+ }
+}
diff --git a/packages/ui/cypress/fixtures/watchAccounts/watchSignatories.ts b/packages/ui/cypress/fixtures/watchAccounts/watchSignatories.ts
new file mode 100644
index 00000000..69f56b21
--- /dev/null
+++ b/packages/ui/cypress/fixtures/watchAccounts/watchSignatories.ts
@@ -0,0 +1,29 @@
+export const watchSignatories = [
+ // signatories of multisig-with-pure
+ {
+ address: '5GGjPYsz8B8mxAzNScFNDPkZ1g97VWFCPCMexPSkPnibPBez',
+ name: 'Pure Signatory 1',
+ type: 'sr25519',
+ mnemonic: 'citizen heavy warrior cattle enter chef label split differ seek turtle gorilla'
+ },
+ {
+ address: '5EkbU3anZKYP98aXF5MvmCUxvwvM4kxp7osc2Xhj1wHYL6ym',
+ name: 'Pure Signatory 2',
+ type: 'sr25519',
+ mnemonic: 'script spoon elder spawn kite burst theme property hip fatal flight amount'
+ },
+
+ // signatories of multisig-without-pure
+ {
+ address: '5HfzjVSWj6mxBnqgJhPfUTpkAJKro9BKToxXB3nozbu2MTpV',
+ name: 'No Pure Signatory 1',
+ type: 'sr25519',
+ mnemonic: 'spring banana desert horse ecology resist tag matrix burden heart stereo fix'
+ },
+ {
+ address: '5Df1JyC6KSbjSp3pQEn85PCnvTtknGiN7JyE7bSZ9zqNL76E',
+ name: 'No Pure Signatory 2',
+ type: 'sr25519',
+ mnemonic: 'mutual pluck punch boy gym key brush dune master aunt track dynamic'
+ }
+]
diff --git a/packages/ui/cypress/support/page-objects/components/accountDisplay.ts b/packages/ui/cypress/support/page-objects/components/accountDisplay.ts
new file mode 100644
index 00000000..a9810b08
--- /dev/null
+++ b/packages/ui/cypress/support/page-objects/components/accountDisplay.ts
@@ -0,0 +1,7 @@
+export const accountDisplay = {
+ identicon: () => cy.get('[data-cy=icon-identicon]'),
+ pureBadge: () => cy.get('[data-cy=badge-pure]'),
+ multisigBadge: () => cy.get('[data-cy=badge-multi]'),
+ nameLabel: () => cy.get('[data-cy=label-account-name]'),
+ addressLabel: () => cy.get('[data-cy=label-account-address]')
+}
diff --git a/packages/ui/cypress/support/page-objects/modals/editNamesModal.ts b/packages/ui/cypress/support/page-objects/modals/editNamesModal.ts
new file mode 100644
index 00000000..04c4d362
--- /dev/null
+++ b/packages/ui/cypress/support/page-objects/modals/editNamesModal.ts
@@ -0,0 +1,7 @@
+export const editNamesModal = {
+ body: () => cy.get('[data-cy=modal-edit-names]'),
+ inputEditPureName: () => cy.get('[data-cy=input-edit-pure-name]'),
+ inputEditMultisigName: () => cy.get('[data-cy=input-edit-multisig-name]'),
+ inputEditSignatoryName: () => cy.get('[data-cy=input-edit-signatory-name]'),
+ saveButton: () => cy.get('[data-cy=button-save-edited-names]')
+}
diff --git a/packages/ui/cypress/support/page-objects/multisigPage.ts b/packages/ui/cypress/support/page-objects/multisigPage.ts
index ec018975..189461bf 100644
--- a/packages/ui/cypress/support/page-objects/multisigPage.ts
+++ b/packages/ui/cypress/support/page-objects/multisigPage.ts
@@ -1,3 +1,9 @@
export const multisigPage = {
- newTransactionButton: () => cy.get('[data-cy="button-new-transaction"]')
+ // header elements
+ accountHeader: () => cy.get('[data-cy=header-account]'),
+ seeOverviewButton: () => cy.get('[data-cy=button-see-overview]'),
+ newTransactionButton: () => cy.get('[data-cy=button-new-transaction]'),
+ optionsMenuButton: () => cy.get('[data-cy=button-options-menu]'),
+ editNamesMenuOption: () => cy.get('[data-cy=menu-option-edit-names]'),
+ subscanMenuOption: () => cy.get('[data-cy=menu-option-subscan]')
}
diff --git a/packages/ui/cypress/support/page-objects/notifications.ts b/packages/ui/cypress/support/page-objects/notifications.ts
index 6494ce4b..dd7c7bdb 100644
--- a/packages/ui/cypress/support/page-objects/notifications.ts
+++ b/packages/ui/cypress/support/page-objects/notifications.ts
@@ -1,6 +1,6 @@
export const notifications = {
- successNotificationIcon: () => cy.get('[data-cy="notification-icon-success"]'),
- errorNotificationIcon: () => cy.get('[data-cy="notification-icon-error"]'),
- loadingNotificationIcon: () => cy.get('[data-cy="notification-icon-loading"]'),
- notificationWrapper: () => cy.get('[data-cy="notification-wrapper"]')
+ successNotificationIcon: () => cy.get('[data-cy=notification-icon-success]'),
+ errorNotificationIcon: () => cy.get('[data-cy=notification-icon-error]'),
+ loadingNotificationIcon: () => cy.get('[data-cy=notification-icon-loading]'),
+ notificationWrapper: () => cy.get('[data-cy=notification-wrapper]')
}
diff --git a/packages/ui/cypress/support/page-objects/sendTxModal.ts b/packages/ui/cypress/support/page-objects/sendTxModal.ts
index 185ab428..c8d222a5 100644
--- a/packages/ui/cypress/support/page-objects/sendTxModal.ts
+++ b/packages/ui/cypress/support/page-objects/sendTxModal.ts
@@ -1,6 +1,6 @@
export const sendTxModal = {
- sendTxTitle: () => cy.get('[data-cy="title-send-tx"]'),
- fieldTo: () => cy.get('[data-cy="field-to"]'),
- fieldAmount: () => cy.get('[data-cy="field-amount"]'),
- buttonSend: () => cy.get('[data-cy="button-send"]')
+ sendTxTitle: () => cy.get('[data-cy=title-send-tx]'),
+ fieldTo: () => cy.get('[data-cy=field-to]'),
+ fieldAmount: () => cy.get('[data-cy=field-amount]'),
+ buttonSend: () => cy.get('[data-cy=button-send]')
}
diff --git a/packages/ui/cypress/support/page-objects/settingsPage.ts b/packages/ui/cypress/support/page-objects/settingsPage.ts
index fe15e109..6b7254a9 100644
--- a/packages/ui/cypress/support/page-objects/settingsPage.ts
+++ b/packages/ui/cypress/support/page-objects/settingsPage.ts
@@ -3,9 +3,6 @@ export const settingsPage = {
accountNameInput: () => cy.get('[data-cy=input-account-name]'),
addButton: () => cy.get('[data-cy=button-add-watched-account]'),
accountContainer: () => cy.get('[data-cy=container-account-details]', { timeout: 20000 }),
- accountIcon: () => cy.get('[data-cy=icon-identicon]'),
- accountNameLabel: () => cy.get('[data-cy=label-account-name]'),
- accountAddressLabel: () => cy.get('[data-cy=label-account-address]'),
accountDeleteButton: () => cy.get('[data-cy=button-delete-watched-account]'),
errorLabel: () => cy.get('[data-cy=label-watch-account-error]')
}
diff --git a/packages/ui/cypress/support/page-objects/topMenuItems.ts b/packages/ui/cypress/support/page-objects/topMenuItems.ts
index 57d88179..04cc6b72 100644
--- a/packages/ui/cypress/support/page-objects/topMenuItems.ts
+++ b/packages/ui/cypress/support/page-objects/topMenuItems.ts
@@ -1,4 +1,10 @@
export const topMenuItems = {
- connectButton: () => cy.get('[data-cy="button-menu-connect"]'),
- multiproxySelector: () => cy.get('[data-cy="select-multiproxy"]')
+ homeButton: () => cy.get('[data-cy=button-navigate-home]'),
+ newMultisigButton: () => cy.get('[data-cy=button-new-multisig]'),
+ settingsButton: () => cy.get('[data-cy=button-navigate-settings]'),
+ overviewButton: () => cy.get('[data-cy=button-navigate-overview]'),
+ aboutButton: () => cy.get('[data-cy=button-navigate-about]'),
+ connectButton: () => cy.get('[data-cy=button-menu-connect]'),
+ multiproxySelector: () => cy.get('[data-cy=select-multiproxy]', { timeout: 20000 }),
+ multiproxySelectorOption: () => cy.get('[data-cy=select-multiproxy-option]')
}
diff --git a/packages/ui/cypress/tests/watched-accounts.cy.ts b/packages/ui/cypress/tests/watched-accounts.cy.ts
index 4c68958b..9de966d6 100644
--- a/packages/ui/cypress/tests/watched-accounts.cy.ts
+++ b/packages/ui/cypress/tests/watched-accounts.cy.ts
@@ -1,7 +1,12 @@
import { addresses } from '../fixtures/accounts'
+import { accountDisplay } from '../support/page-objects/components/accountDisplay'
import { landingPageUrl, settingsPageWatchAccountUrl } from '../fixtures/landingData'
import { landingPage } from '../support/page-objects/landingPage'
import { settingsPage } from '../support/page-objects/settingsPage'
+import { topMenuItems } from '../support/page-objects/topMenuItems'
+import { watchMultisigs } from '../fixtures/watchAccounts/watchMultisigs'
+import { multisigPage } from '../support/page-objects/multisigPage'
+import { editNamesModal } from '../support/page-objects/modals/editNamesModal'
const addWatchAccount = (address: string, name?: string) => {
settingsPage.accountAddressInput().type(`${address}{enter}`, { delay: 20 })
@@ -19,9 +24,9 @@ describe('Watched Accounts', () => {
landingPage.watchAccountButton().click()
addWatchAccount(addresses.Alice, 'Alice')
settingsPage.accountContainer().within(() => {
- settingsPage.accountIcon().should('be.visible')
- settingsPage.accountAddressLabel().should('be.visible')
- settingsPage.accountNameLabel().should('be.visible')
+ accountDisplay.identicon().should('be.visible')
+ accountDisplay.addressLabel().should('be.visible')
+ accountDisplay.nameLabel().should('be.visible')
settingsPage.accountDeleteButton().should('be.visible')
})
})
@@ -33,8 +38,8 @@ describe('Watched Accounts', () => {
// now remove it
settingsPage.accountContainer().within(() => {
settingsPage.accountDeleteButton().click()
- settingsPage.accountIcon().should('not.exist')
- settingsPage.accountAddressLabel().should('not.exist')
+ accountDisplay.identicon().should('not.exist')
+ accountDisplay.addressLabel().should('not.exist')
})
settingsPage.accountContainer().should('have.length', 0)
})
@@ -58,4 +63,127 @@ describe('Watched Accounts', () => {
settingsPage.accountContainer().should('have.length', 0)
settingsPage.addButton().should('be.disabled')
})
+
+ it('can see the expected account details displayed for a watched multisig', () => {
+ cy.visit(settingsPageWatchAccountUrl)
+ addWatchAccount(
+ watchMultisigs['multisig-without-pure'].address,
+ watchMultisigs['multisig-without-pure'].name
+ )
+ // ensure the multisig name is displayed in the settings account container
+ settingsPage.accountContainer().within(() => {
+ accountDisplay.identicon().should('be.visible')
+ accountDisplay
+ .nameLabel()
+ .should('be.visible')
+ .should('have.text', watchMultisigs['multisig-without-pure'].name)
+ })
+ // ensure the name is included in the selectable drop-down option
+ topMenuItems.multiproxySelector().should('be.visible').first().click()
+ topMenuItems.multiproxySelectorOption().within(() => {
+ accountDisplay.identicon().should('be.visible')
+ accountDisplay.multisigBadge().should('be.visible')
+ accountDisplay.pureBadge().should('not.exist')
+ accountDisplay.nameLabel().should('have.text', watchMultisigs['multisig-without-pure'].name)
+ })
+ // ensure the name is displayed in the home page header
+ topMenuItems.homeButton().click()
+ multisigPage.accountHeader().within(() => {
+ accountDisplay.identicon().should('be.visible')
+ accountDisplay.multisigBadge().should('be.visible')
+ accountDisplay.pureBadge().should('not.exist')
+ accountDisplay.nameLabel().should('have.text', watchMultisigs['multisig-without-pure'].name)
+ })
+ })
+
+ it('can see the expected account details displayed for a watched pure', () => {
+ cy.visit(settingsPageWatchAccountUrl)
+ addWatchAccount(
+ watchMultisigs['multisig-with-pure'].pureAddress,
+ watchMultisigs['multisig-with-pure'].name
+ )
+ // ensure the multisig name is displayed in the settings account container
+ settingsPage.accountContainer().within(() => {
+ accountDisplay.identicon().should('be.visible')
+ accountDisplay
+ .nameLabel()
+ .should('be.visible')
+ .should('have.text', watchMultisigs['multisig-with-pure'].name)
+ })
+ // ensure the name is included in the selectable drop-down option
+ topMenuItems.multiproxySelector().should('be.visible').first().click()
+ topMenuItems.multiproxySelectorOption().within(() => {
+ accountDisplay.identicon().should('be.visible')
+ accountDisplay.pureBadge().should('be.visible')
+ accountDisplay.multisigBadge().should('not.exist')
+ accountDisplay.nameLabel().should('have.text', watchMultisigs['multisig-with-pure'].name)
+ })
+ // navigate to the multisig page and ensure the name is included in the home page header
+ topMenuItems.homeButton().click()
+ multisigPage.accountHeader().within(() => {
+ accountDisplay.identicon().should('be.visible')
+ accountDisplay.pureBadge().should('be.visible')
+ accountDisplay.multisigBadge().should('not.exist')
+ accountDisplay.nameLabel().should('have.text', watchMultisigs['multisig-with-pure'].name)
+ })
+ })
+
+ it('can edit the name of a watched pure', () => {
+ cy.visit(settingsPageWatchAccountUrl)
+ addWatchAccount(
+ watchMultisigs['multisig-with-pure'].pureAddress,
+ watchMultisigs['multisig-with-pure'].name
+ )
+ // navigate to the home page and edit the name
+ topMenuItems.homeButton().click()
+ multisigPage.optionsMenuButton().click()
+ multisigPage.editNamesMenuOption().click()
+ editNamesModal.body().should('be.visible')
+ cy.clock()
+ editNamesModal.inputEditPureName().type(`{selectall}{del}${`Edited Name Test`}`)
+ // name edition is debounced by 300ms
+ cy.tick(300)
+ editNamesModal.saveButton().should('be.enabled').click()
+ // ensure the edited name is now displayed in the home page header
+ multisigPage.accountHeader().within(() => {
+ accountDisplay.nameLabel().should('have.text', 'Edited Name Test')
+ })
+ // navigate to settings and ensure the edited name is displayed
+ cy.visit(settingsPageWatchAccountUrl)
+ settingsPage.accountContainer().within(() => {
+ accountDisplay.nameLabel().should('have.text', 'Edited Name Test')
+ })
+ })
+
+ it('can open the correct subscan link for a watched pure', () => {
+ cy.visit(settingsPageWatchAccountUrl)
+ addWatchAccount(
+ watchMultisigs['multisig-with-pure'].pureAddress,
+ watchMultisigs['multisig-with-pure'].name
+ )
+ topMenuItems.homeButton().click()
+ multisigPage.optionsMenuButton().click()
+ multisigPage.subscanMenuOption().should('be.visible')
+ // stub window.open to prevent opening a new tab
+ cy.window().then((win) => {
+ cy.stub(win, 'open').as('open')
+ })
+ multisigPage.subscanMenuOption().click()
+ // ensure the correct subscan url is opened
+ cy.get('@open').should(
+ 'have.been.calledOnceWith',
+ `https://rococo.subscan.io/account/${watchMultisigs['multisig-with-pure'].pureAddress}`
+ )
+ })
+
+ it('can not see the "New Transaction" button when only a watched account', () => {
+ cy.visit(settingsPageWatchAccountUrl)
+ addWatchAccount(
+ watchMultisigs['multisig-with-pure'].pureAddress,
+ watchMultisigs['multisig-with-pure'].name
+ )
+ topMenuItems.homeButton().click()
+ multisigPage.accountHeader().should('be.visible')
+ multisigPage.newTransactionButton().should('not.exist')
+ })
})
diff --git a/packages/ui/src/components/AccountEditName.tsx b/packages/ui/src/components/AccountEditName.tsx
index 300c52f9..f0e9484f 100644
--- a/packages/ui/src/components/AccountEditName.tsx
+++ b/packages/ui/src/components/AccountEditName.tsx
@@ -15,9 +15,10 @@ interface Props {
className?: string
address: string
onNameChange: (args: OnChangeArgs) => void
+ testId?: string
}
-const AccountEditName = ({ address, onNameChange, className }: Props) => {
+const AccountEditName = ({ address, onNameChange, className, testId }: Props) => {
const { getNamesWithExtension } = useAccountNames()
const { ownAddressList } = useAccounts()
const [name, setName] = useState(getNamesWithExtension(address) || '')
@@ -66,6 +67,7 @@ const AccountEditName = ({ address, onNameChange, className }: Props) => {
onChange={onChange}
disabled={isExtensionAccount}
value={name}
+ data-cy={`input-edit-${testId}-name`}
// onKeyDown={handleSpecialKeys}
/>
diff --git a/packages/ui/src/components/Header/Header.tsx b/packages/ui/src/components/Header/Header.tsx
index ccaff8ce..96520193 100644
--- a/packages/ui/src/components/Header/Header.tsx
+++ b/packages/ui/src/components/Header/Header.tsx
@@ -42,6 +42,7 @@ const Header = ({ handleDrawerOpen }: Props) => {
{name}
diff --git a/packages/ui/src/components/IdenticonBadge.tsx b/packages/ui/src/components/IdenticonBadge.tsx
index b7ddbf19..85d2fe09 100644
--- a/packages/ui/src/components/IdenticonBadge.tsx
+++ b/packages/ui/src/components/IdenticonBadge.tsx
@@ -44,6 +44,7 @@ export const IdenticonBadge = ({
color="primary"
badgeContent={badge}
anchorOrigin={{ horizontal: 'left', vertical: 'top' }}
+ data-cy={`badge-${badge}`}
>
diff --git a/packages/ui/src/components/OptionsMenu.tsx b/packages/ui/src/components/OptionsMenu.tsx
index 4d581714..8ee663ca 100644
--- a/packages/ui/src/components/OptionsMenu.tsx
+++ b/packages/ui/src/components/OptionsMenu.tsx
@@ -49,6 +49,7 @@ const OptionsMenu = ({ className, options, menuButtonBorder }: Props) => {
aria-expanded={open ? 'true' : undefined}
aria-haspopup="true"
onClick={handleMenuClick}
+ data-cy="button-options-menu"
>
@@ -74,6 +75,7 @@ const OptionsMenu = ({ className, options, menuButtonBorder }: Props) => {
className="menuEntry"
key={option.text}
onClick={() => handleClick(option.onClick)}
+ data-cy={`menu-option-${option.text.toLowerCase().replace(/ /g, '-')}`}
>
{option.icon}
{option.text}
diff --git a/packages/ui/src/components/modals/EditNames.tsx b/packages/ui/src/components/modals/EditNames.tsx
index fdc33448..f9bb3bd9 100644
--- a/packages/ui/src/components/modals/EditNames.tsx
+++ b/packages/ui/src/components/modals/EditNames.tsx
@@ -52,6 +52,7 @@ const EditNames = ({ onClose, className }: Props) => {
maxWidth={'sm'}
open
className={className}
+ data-cy="modal-edit-names"
>
Edit names
@@ -68,6 +69,7 @@ const EditNames = ({ onClose, className }: Props) => {
className="accountEdition"
address={selectedMultiProxy.proxy || ''}
onNameChange={onNameChange}
+ testId="pure"
/>
>
)}
@@ -87,6 +89,7 @@ const EditNames = ({ onClose, className }: Props) => {
className="accountEdition"
address={address}
onNameChange={onNameChange}
+ testId="multisig"
/>
))}
@@ -101,6 +104,7 @@ const EditNames = ({ onClose, className }: Props) => {
className="accountEdition"
address={signatory}
onNameChange={onNameChange}
+ testId="signatory"
/>
))}
@@ -112,6 +116,7 @@ const EditNames = ({ onClose, className }: Props) => {
diff --git a/packages/ui/src/components/select/MultiProxySelection.tsx b/packages/ui/src/components/select/MultiProxySelection.tsx
index 65631fef..b4ba0403 100644
--- a/packages/ui/src/components/select/MultiProxySelection.tsx
+++ b/packages/ui/src/components/select/MultiProxySelection.tsx
@@ -88,10 +88,12 @@ const MultiProxySelection = ({ className }: Props) => {
key={displayAddress}
component="li"
{...props}
+ data-cy="select-multiproxy-option"
>
)
diff --git a/packages/ui/src/pages/Home/HeaderView.tsx b/packages/ui/src/pages/Home/HeaderView.tsx
index bdd1ce6e..0c9a9800 100644
--- a/packages/ui/src/pages/Home/HeaderView.tsx
+++ b/packages/ui/src/pages/Home/HeaderView.tsx
@@ -19,11 +19,12 @@ const HeaderView = () => {
}, [selectedHasProxy, selectedMultiProxy])
return (
-
+
navigate('/overview')}
variant="link"
+ data-cy="button-see-overview"
>
See overview
@@ -38,7 +39,7 @@ const HeaderView = () => {
Balance
-
+