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

Feature/profile recover tests #84

Open
wants to merge 7 commits into
base: proto
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/components/UI/SwapStepper.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<div class="swap-stepper">
<template v-for="step in stepsCount">
<div v-show="step === activeStep" :key="step" class="swap-stepper__content">
<div v-show="step === activeStep" :key="step" class="swap-stepper__content" data-test-id="swap-stepper-content">
<slot :name="step" :change-active-step="changeActiveStep"></slot>
</div>
</template>
Expand Down
12 changes: 12 additions & 0 deletions tests/unit/__helpers__/stubComponents.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export function stubComponent(Component, options = {}) {
return {
props: Component.options.props,
model: Component.options.model,
// Do not render any slots/scoped slots except default
// This differs from VTU behavior which renders all slots
template: '<div><slot></slot></div>',
// allows wrapper.find(Component) to work for stub
$_vueTestUtils_original: Component,
...options
}
}
25 changes: 25 additions & 0 deletions tests/unit/__mocks__/profile/Recover.mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
export const DEFAULT_TABLE_MATRIX = Array.from({ length: 24 }, () => {
return {
value: '',
input: true
}
})
export const FULL_TABLE_MATRIX = Array.from({ length: 24 }, () => {
return {
value: 'hello word',
input: false
}
})
export const CHANGE_TABLE_MATRIX = DEFAULT_TABLE_MATRIX.map((tableMAtrix, index) => {
const changeTableMatrix =
index === 1 || index === 2 || index === 4 ? { value: 'hello word', input: false } : { ...tableMAtrix }

return changeTableMatrix
})

export const USER_COLOR_SCHEME = {
background: 'test',
color: 'test',
colorForDarkTheme: 'test',
selectionColor: 'test'
}
7 changes: 7 additions & 0 deletions tests/unit/setup.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,9 @@
import Vue from 'vue'
import UI from '@/components/UI'
import { enableAutoDestroy } from '@vue/test-utils'

process.env.VUE_APP_HOME_URL = 'http://localhost'
process.env.VUE_APP_KEYS_URL = 'http://keys.localhost'

Vue.use(UI)
enableAutoDestroy(global.afterEach)
220 changes: 220 additions & 0 deletions tests/unit/view/profile/Recover.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
import RecoverProfile from '@/views/Profile/Recover.vue'
import SwapStepper from '@/components/UI/SwapStepper.vue'
import { shallowMount } from '@vue/test-utils'
import MnemonicPhraseTable from '@/components/Profile/MnemonicPhraseTable.vue'
import SwapButton from '@/components/UI/SwapButton.vue'
import CreateProfileFormPassword from '@/components/Profile/FormPassword.vue'
import { STEPS_RECOVER_PROFILE, MNEMONIC_PHRASE_WRITE, FORM_PASSWORD } from '@/constants/profile'
import { profileMessageTypes } from '@/constants/messageTypes'
import windowParentPostMessage from '@/windowParentPostMessage'
import { stubComponent } from '../../__helpers__/stubComponents'
import flushPromises from '../../__helpers__/flushPromises'
import {
DEFAULT_TABLE_MATRIX,
CHANGE_TABLE_MATRIX,
FULL_TABLE_MATRIX,
USER_COLOR_SCHEME
} from '../../__mocks__/profile/Recover.mock'

jest.mock('@/windowParentPostMessage')
jest.mock('@/services/profile', () => {
return {
profileService: {
createProfile: jest.fn().mockResolvedValue({
cryptoProfile: {},
shortKey: 'test'
}),
getSeedFromMnemonic: jest.fn().mockResolvedValue({}),
getPublicKey: jest.fn().mockReturnValue(''),
getUserColorScheme: jest.fn().mockReturnValue({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

тут, получается та же структура, что и в USER_COLOR_SCHEME, мб этот объект тогда и возвращать?

background: 'test',
color: 'test',
colorForDarkTheme: 'test',
selectionColor: 'test'
}),
saveProfileByShortKey: jest.fn()
}
}
})

const CreateProfileFormPasswordStub = (isValidPassword = false) => {
return stubComponent(CreateProfileFormPassword, {
render(h) {
return h('div', [this.$scopedSlots.actions?.({ isValidPassword })])
}
})
}

const mockChangeActiveStep = jest.fn()

const SwapStepperStub = stubComponent(SwapStepper, {
render(h) {
return h('div', [
this.$scopedSlots['1']?.({ changeActiveStep: mockChangeActiveStep }),
this.$scopedSlots['2']?.({ changeActiveStep: mockChangeActiveStep })
])
}
})

describe('Recover Profile', () => {
let wrapper

const findMnemonicPhraseTable = () => wrapper.findComponent(MnemonicPhraseTable)
const findCreateProfileFormPassword = () => wrapper.findComponent(CreateProfileFormPassword)
const findSwapStepper = () => wrapper.findComponent(SwapStepper)
const findAllButtonsByText = (text, context = wrapper) => {
return context.findAllComponents(SwapButton).filter(buttonWrapper => buttonWrapper.text().includes(text))
}
const findButtonByText = (text, context = wrapper) => findAllButtonsByText(text, context).at(0)

const goToSeconStep = async () => {
const mnemonicPhraseTable = findMnemonicPhraseTable()
mnemonicPhraseTable.vm.$emit('change', FULL_TABLE_MATRIX)
await wrapper.vm.$nextTick()

const nextButton = findButtonByText('Next')
await nextButton.vm.$emit('click')
}

afterEach(() => {
wrapper.destroy()
})

const createComponent = ({ stubs = {} } = {}) => {
wrapper = shallowMount(RecoverProfile, {
stubs: {
SwapStepper: SwapStepperStub,
CreateProfileFormPassword: CreateProfileFormPasswordStub(),
...stubs
}
})
}

describe('step 1', () => {
it('After creating the Recover profile page, there are component SwapStepper', () => {
createComponent()
expect(findSwapStepper().exists()).toBe(true)
})

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

тут не хватает теста на кнопку Back

it('After creating the Recover profile page, there are component MnemonicPhraseTable', () => {
createComponent()
expect(findMnemonicPhraseTable().exists()).toBe(true)
})

it(`
After creating the Recover profile page,
prop component mnemonicPhraseTable to equal DEFAULT_TABLE_MATRIX`, () => {
createComponent()

const mnemonicPhraseTable = findMnemonicPhraseTable()

expect(mnemonicPhraseTable.props().tableMatrix).toEqual(DEFAULT_TABLE_MATRIX)
})

it(`
after the change event in component mnemonicPhraseTable,
prop table Matrix to equal the modified matrix`, async () => {
createComponent()

const mnemonicPhraseTable = findMnemonicPhraseTable()

mnemonicPhraseTable.vm.$emit('change', CHANGE_TABLE_MATRIX)
await wrapper.vm.$nextTick()

expect(mnemonicPhraseTable.props().tableMatrix).toEqual(CHANGE_TABLE_MATRIX)
})

it('The button to go to the next step is blocked until the mnemonicPhrase is entered', () => {
createComponent()

const backButton = findButtonByText('Next')

expect(backButton.props().disabled).toBe(true)
})

it('The text of the popup hint in the disabled button corresponds to reality', () => {
createComponent()

const nextButton = findButtonByText('Next')

expect(nextButton.props().tooltip).toContain('Complete your secret phrase')
})

it(`
After entering the phrase and clicking on the Next button,
the transition to the next step takes place
`, async () => {
createComponent()

const mnemonicPhraseTable = findMnemonicPhraseTable()
mnemonicPhraseTable.vm.$emit('change', FULL_TABLE_MATRIX)
await wrapper.vm.$nextTick()

const nextButton = findButtonByText('Next')

await nextButton.vm.$emit('click')

expect(mockChangeActiveStep).toBeCalledWith(STEPS_RECOVER_PROFILE[FORM_PASSWORD])
})
})

describe('step 2', () => {
beforeEach(async () => {
createComponent()

await goToSeconStep()
})

it('After going to the second step, there is a component CreateProfileFormPassword', () => {
expect(findCreateProfileFormPassword().exists()).toBe(true)
})

it('After clicking on the Back button, the transition to the previous step takes place', async () => {
const formPassword = wrapper.findComponent(CreateProfileFormPassword)
const backButton = findButtonByText('Back', formPassword)

await backButton.vm.$emit('click')

expect(mockChangeActiveStep).toBeCalledWith(STEPS_RECOVER_PROFILE[MNEMONIC_PHRASE_WRITE])
})

it('disables the button when the password form says the password is invalid', async () => {
createComponent({ stubs: { CreateProfileFormPassword: CreateProfileFormPasswordStub(false) } })
await goToSeconStep()

const recoverButton = findButtonByText('Recover')

expect(recoverButton.props().disabled).toBe(true)
expect(recoverButton.props().tooltip).toBe('Please come up with a password.')
})

it('enables the button when the password form says the password is valid', async () => {
createComponent({ stubs: { CreateProfileFormPassword: CreateProfileFormPasswordStub(true) } })
await goToSeconStep()

const recoverButton = findButtonByText('Recover')

expect(recoverButton.props().disabled).toBe(false)
expect(recoverButton.props().tooltip).toBe(null)
})

it('sends post message with created profile', async () => {
const recoverButton = findButtonByText('Recover')

recoverButton.vm.$emit('click')
await wrapper.vm.$nextTick()
await flushPromises()

expect(windowParentPostMessage).toBeCalledWith(
expect.objectContaining({
message: {
type: profileMessageTypes.PROFILE_RECOVERED,
payload: {
profile: { colorScheme: USER_COLOR_SCHEME, publicKey: 'test' }
}
}
})
)
})
})
})