Skip to content

Commit

Permalink
update interaction test
Browse files Browse the repository at this point in the history
  • Loading branch information
eshark9312 committed Nov 22, 2023
1 parent 06d5006 commit e6a1e66
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 64 deletions.
128 changes: 81 additions & 47 deletions packages/ui/src/app/App.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,17 @@ type Args = {
onTransfer: jest.Mock
onSubscribeEmail: jest.Mock
onConfirmEmail: jest.Mock
onUpdateMembership: CallableFunction
onAddStakingAccount: jest.Mock
onConfirmStakingAccount: jest.Mock
batchTx: jest.Mock
}

type Story = StoryObj<FC<Args>>

const alice = member('alice')
const bob = member('bob')
const charlie = member('charlie')
const dave = member('dave')

const NEW_MEMBER_DATA = {
id: alice.id, // we set this to alice's ID so that after member is created, member with same ID can be found in MembershipContext
Expand All @@ -72,9 +75,11 @@ export default {
argTypes: {
onBuyMembership: { action: 'BuyMembership' },
onTransfer: { action: 'BalanceTransfer' },
onUpdateMembership: { action: 'UpdateMembership' },
onSubscribeEmail: { action: 'SubscribeEmail' },
onConfirmEmail: { action: 'ConfirmEmail' },
onAddStakingAccount: { action: 'AddStakingAccount' },
onConfirmStakingAccount: { action: 'ConfirmStakingAccount' },
batchTx: { action: 'BatchTx' },
},

args: {
Expand All @@ -95,13 +100,16 @@ export default {

mocks: ({ args, parameters }: StoryContext<Args>): MocksParameters => {
const account = (member: Membership) => ({
balances: member !== charlie ? (args.hasFunds ? parameters.totalBalance : 0) : 0,
balances: member !== dave ? (args.hasFunds ? parameters.totalBalance : 0) : 0,
...(args.hasMemberships ? { member } : { account: { name: member.handle, address: member.controllerAccount } }),
})
return {
accounts: {
active: args.isLoggedIn ? 'alice' : undefined,
list: args.hasMemberships || args.hasAccounts ? [account(alice), account(bob), account(charlie)] : [],
list:
args.hasMemberships || args.hasAccounts
? [account(alice), account(bob), account(charlie), account(dave)]
: [],
hasWallet: args.hasWallet,
},

Expand All @@ -128,11 +136,24 @@ export default {
onSend: args.onBuyMembership,
failure: parameters.txFailure,
},
updateProfile: {
event: 'MembershipUpdated',
addStakingAccountCandidate: {
event: 'StakingAccountAdded',
data: [NEW_MEMBER_DATA.id],
onSend: args.onUpdateMembership,
failure: parameters.updateTxFailure,
onSend: args.onAddStakingAccount,
failure: parameters.addStakingAccountTxFailure,
},
confirmStakingAccount: {
event: 'StakingAccountConfirmed',
data: [NEW_MEMBER_DATA.id],
onSend: args.onConfirmStakingAccount,
failure: parameters.confirmStakingAccountTxFailure,
},
},
utility: {
batch: {
event: 'TxBatch',
onSend: args.batchTx,
failure: parameters.batchTxFailure,
},
},
},
Expand Down Expand Up @@ -511,8 +532,11 @@ const fillMembershipFormWithValidatorAcc = async (modal: Container) => {
await fillMembershipForm(modal)
const validatorChechButton = modal.getAllByText('Yes')[1]
await userEvent.click(validatorChechButton)
expect(await modal.findByText('Validator account'))
await selectFromDropdown(modal, 'Validator account', 'alice')
expect(await modal.findByText(/^If your validator account/))
await selectFromDropdown(modal, /^If your validator account/, 'charlie')
// await selectFromDropdown(modal, /^If your validator account/, 'dave')
const addButton = document.getElementsByClassName('add-button')[0]
await userEvent.click(addButton)
}

export const BuyMembershipWithValidatorAccountHappyAndBindHappy: Story = {
Expand Down Expand Up @@ -547,14 +571,24 @@ export const BuyMembershipWithValidatorAccountHappyAndBindHappy: Story = {
await userEvent.click(getButtonByText(modal, 'Create membership'))
})

await step('Bind validator account with membership', async () => {
expect(await modal.findByText('You are intending to bond your validator account with your membership'))
await step('Add validator account', async () => {
expect(await modal.findByText('You are intending to bond your validator account with your membership.'))
expect(modal.getByText('Transaction fee:')?.nextSibling?.textContent).toBe('5')
expect(modal.getByRole('heading', { name: 'bob' }))
expect(modal.getByRole('heading', { name: 'charlie' }))

await userEvent.click(getButtonByText(modal, 'Sign and Bond'))
})

await step('Confirm validator account', async () => {
expect(
await modal.findByText('You are intending to confirm your validator account to be bound with your membership')
)
expect(modal.getByText('Transaction fee:')?.nextSibling?.textContent).toBe('5')
expect(modal.getByRole('heading', { name: 'bob' }))

await userEvent.click(getButtonByText(modal, 'Sign and Confirm'))
})

await step('Confirm', async () => {
expect(await modal.findByText('Success'))
expect(modal.getByText(NEW_MEMBER_DATA.handle))
Expand All @@ -571,16 +605,13 @@ export const BuyMembershipWithValidatorAccountHappyAndBindHappy: Story = {
referrerId: undefined,
})

expect(args.onUpdateMembership).toHaveBeenCalledWith(NEW_MEMBER_DATA.id, NEW_MEMBER_DATA.handle, {
validatorAccount: alice.controllerAccount,
})
expect(args.onAddStakingAccount).toHaveBeenCalledWith(NEW_MEMBER_DATA.id)

const viewProfileButton = getButtonByText(modal, 'View my profile')
expect(viewProfileButton).toBeEnabled()
userEvent.click(viewProfileButton)
expect(args.batchTx).toHaveBeenCalledTimes(1)

expect(modal.getByText('Profile'))
expect(modal.getByText(NEW_MEMBER_DATA.handle))
const doneButton = getButtonByText(modal, 'Done')
expect(doneButton).toBeEnabled()
userEvent.click(doneButton)
})
},
}
Expand Down Expand Up @@ -627,11 +658,11 @@ export const BuyMembershipTxWithValidatorAccountFailure: Story = {
},
}

export const BuyMembershipWithValidatorAccountHappyAndBindNotEnoughFunds: Story = {
export const BuyMembershipHappyAddValidatorAccFailure: Story = {
args: { hasMemberships: false, isLoggedIn: false },
parameters: { totalBalance: 25 },
parameters: { addStakingAccountTxFailure: 'Some error message' },

play: async ({ args, canvasElement, step }) => {
play: async ({ canvasElement, step }) => {
const screen = within(canvasElement)
const modal = withinModal(canvasElement)

Expand Down Expand Up @@ -660,33 +691,22 @@ export const BuyMembershipWithValidatorAccountHappyAndBindNotEnoughFunds: Story
await userEvent.click(getButtonByText(modal, 'Create membership'))
})

await step('Not enough funds for update tx', async () => {
expect(await modal.findByText('You are intending to bond your validator account with your membership'))
await selectFromDropdown(modal, 'Sending from account', 'charlie')
expect(modal.getByText('Insufficient funds to cover the membership creation.'))
expect(getButtonByText(modal, 'Sign and Bond')).toBeDisabled()
})
await step('Add Validator Account Tx Failure', async () => {
expect(await modal.findByText('You are intending to bond your validator account with your membership.'))
expect(modal.getByText('Transaction fee:')?.nextSibling?.textContent).toBe('5')
expect(modal.getByRole('heading', { name: 'charlie' }))

await step('Confirm', async () => {
expect(args.onBuyMembership).toHaveBeenCalledWith({
rootAccount: alice.controllerAccount,
controllerAccount: bob.controllerAccount,
handle: NEW_MEMBER_DATA.handle,
metadata: metadataToBytes(MembershipMetadata, {
name: NEW_MEMBER_DATA.metadata.name,
about: NEW_MEMBER_DATA.metadata.about,
avatarUri: NEW_MEMBER_DATA.metadata.avatar.avatarUri,
}),
invitingMemberId: undefined,
referrerId: undefined,
})
await userEvent.click(getButtonByText(modal, 'Sign and Bond'))

expect(await modal.findByText('Failure'))
expect(await modal.findByText('Some error message'))
})
},
}

export const BuyMembershipWithValidatorAccountHappyAndBindTxFailure: Story = {
export const BuyMembershipAddValidatorAccHappyConfirmTxFailure: Story = {
args: { hasMemberships: false, isLoggedIn: false },
parameters: { updateTxFailure: 'Some error message' },
parameters: { batchTxFailure: 'Some error message' },

play: async ({ canvasElement, step }) => {
const screen = within(canvasElement)
Expand Down Expand Up @@ -717,9 +737,23 @@ export const BuyMembershipWithValidatorAccountHappyAndBindTxFailure: Story = {
await userEvent.click(getButtonByText(modal, 'Create membership'))
})

await step('Bind validator account Tx failure', async () => {
expect(await modal.findByText('You are intending to bond your validator account with your membership'))
await step('Add validator account', async () => {
expect(await modal.findByText('You are intending to bond your validator account with your membership.'))
expect(modal.getByText('Transaction fee:')?.nextSibling?.textContent).toBe('5')
expect(modal.getByRole('heading', { name: 'charlie' }))

await userEvent.click(getButtonByText(modal, 'Sign and Bond'))
})

await step('Confirm validator account', async () => {
expect(
await modal.findByText('You are intending to confirm your validator account to be bound with your membership')
)
expect(modal.getByText('Transaction fee:')?.nextSibling?.textContent).toBe('5')
expect(modal.getByRole('heading', { name: 'bob' }))

await userEvent.click(getButtonByText(modal, 'Sign and Confirm'))

expect(await modal.findByText('Failure'))
expect(await modal.findByText('Some error message'))
})
Expand Down
3 changes: 2 additions & 1 deletion packages/ui/src/common/components/Modal/Modals.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@ export const Row = styled.div`
height: auto;
`

export const RowInline = styled.div<{ gap?: number }>`
export const RowInline = styled.div<{ gap?: number; top?: number }>`
display: flex;
flex-direction: row;
width: 100%;
height: auto;
align-items: center;
gap: ${({ gap }) => gap ?? 16}px;
margin-top: ${({ top }) => top ?? 0}px;
`

export const AccountRow = styled.div`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export const AddStakingAccCandidateModal = ({ onClose, formData, transaction, in
}}
>
<ModalBody>
<TextMedium>You are intending to bond your validator account with your membership</TextMedium>
<TextMedium>You are intending to bond your validator account with your membership.</TextMedium>
<TextMedium>
Fees of <TokenValue value={paymentInfo?.partialFee.toBn()} /> will be applied to the transaction.
</TextMedium>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import HCaptcha from '@hcaptcha/react-hcaptcha'
import { BalanceOf } from '@polkadot/types/interfaces/runtime'
import React, { useEffect, useState } from 'react'
import { FormProvider, useForm } from 'react-hook-form'
import styled from 'styled-components'
import * as Yup from 'yup'

import { SelectAccount, SelectedAccount } from '@/accounts/components/SelectAccount'
Expand Down Expand Up @@ -265,15 +266,24 @@ export const BuyMembershipForm = ({

{type === 'general' && (
<>
<Row>
<InlineToggleWrap>
<Label>I am a validator: </Label>
<ToggleCheckbox trueLabel="Yes" falseLabel="No" name="isValidator" />
</InlineToggleWrap>
</Row>
<RowInline top={16}>
<Label>I am a validator: </Label>
<ToggleCheckbox trueLabel="Yes" falseLabel="No" name="isValidator" />
</RowInline>
{isValidator && (
<>
<Row>
<SelectValidatorAccountWrapper>
<RowInline gap={4}>
<Label noMargin>Add validator controller account or validator stash account</Label>
<Tooltip tooltipText="This is the status which indicates the selected account is actually a validator account.">
<TooltipDefault />
</Tooltip>
<TextSmall dark>*</TextSmall>
</RowInline>
<TextMedium dark>
If your validator account is not in your signer wallet, paste the account address to the field
below:
</TextMedium>
<RowInline>
<InputComponent id="select-validatorAccount" inputSize="l">
<SelectAccount id="select-validatorAccount" name="validatorAccountCandidate" />
Expand All @@ -283,11 +293,12 @@ export const BuyMembershipForm = ({
size="large"
onClick={addValidatorAccount}
disabled={!validatorAccountCandidate}
className="add-button"
>
<PlusIcon />
</ButtonPrimary>
</RowInline>
</Row>
</SelectValidatorAccountWrapper>

{validatorAccounts.map((account, index) => (
<Row>
Expand Down Expand Up @@ -397,3 +408,10 @@ export const BuyMembershipFormModal = ({ onClose, onSubmit, membershipPrice }: B
</ScrolledModal>
)
}

const SelectValidatorAccountWrapper = styled.div`
margin-top: -4px;
display: flex;
flex-direction: column;
gap: 8px;
`
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,7 @@ export const BuyMembershipModal = () => {
state.matches('addStakingAccCandidateTx') &&
api &&
state.context.memberId &&
state.context.form.validatorAccounts &&
state.context.bindingValidtorAccStep
state.context.form.validatorAccounts
) {
const transaction = api.tx.members.addStakingAccountCandidate(state.context.memberId.toString())
const service = state.children.transaction
Expand All @@ -68,7 +67,7 @@ export const BuyMembershipModal = () => {
onClose={hideModal}
formData={state.context.form}
transaction={transaction}
initialSigner={state.context.form.validatorAccounts[state.context.bindingValidtorAccStep]}
initialSigner={state.context.form.validatorAccounts[state.context.bindingValidtorAccStep ?? 0]}
service={service}
/>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export const ConfirmStakingAccModal = ({ onClose, formData, transaction, initial
}}
>
<ModalBody>
<TextMedium>You are intending to bond your validator account with your membership</TextMedium>
<TextMedium>You are intending to confirm your validator account to be bound with your membership</TextMedium>
<TextMedium>
Fees of <TokenValue value={paymentInfo?.partialFee.toBn()} /> will be applied to the transaction.
</TextMedium>
Expand All @@ -84,7 +84,7 @@ export const ConfirmStakingAccModal = ({ onClose, formData, transaction, initial
transactionFee={paymentInfo?.partialFee.toBn()}
next={{
disabled: signDisabled,
label: 'Sign and Bond',
label: 'Sign and Confirm',
onClick: sign,
}}
></ModalTransactionFooter>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ export type BuyMembershipEvent =
| { type: 'ERROR' }

const isSelfTransition = (context: BuyMembershipContext) =>
!!context.form?.validatorAccounts &&
(!context.bindingValidtorAccStep || context.form.validatorAccounts.length > context.bindingValidtorAccStep)
context.form?.validatorAccounts &&
context.form?.validatorAccounts.length > 1 &&
(!context.bindingValidtorAccStep || context.form.validatorAccounts.length - 1 > context.bindingValidtorAccStep)

export const buyMembershipMachine = createMachine<BuyMembershipContext, BuyMembershipEvent, BuyMembershipState>({
initial: 'prepare',
Expand Down

0 comments on commit e6a1e66

Please sign in to comment.