diff --git a/jest.config.js b/jest.config.js index 9b169b11..7c500910 100644 --- a/jest.config.js +++ b/jest.config.js @@ -4,7 +4,6 @@ const config = require('@polkadot/dev/config/jest.cjs'); module.exports = Object.assign({}, config, { - browser: true, moduleNameMapper: { '@polkadot/extension-(base|chains|dapp|inject|ui)(.*)$': '/packages/extension-$1/src/$2', // eslint-disable-next-line sort-keys diff --git a/packages/extension-ui/src/Popup/Accounts/Account.test.tsx b/packages/extension-ui/src/Popup/Accounts/Account.test.tsx index a803392b..712bfe2d 100644 --- a/packages/extension-ui/src/Popup/Accounts/Account.test.tsx +++ b/packages/extension-ui/src/Popup/Accounts/Account.test.tsx @@ -6,15 +6,20 @@ import '../../../../../__mocks__/chrome'; import Adapter from '@wojtekmaj/enzyme-adapter-react-17'; import { configure, mount, ReactWrapper } from 'enzyme'; import React from 'react'; +import { act } from 'react-dom/test-utils'; import { MemoryRouter } from 'react-router'; import { ThemeProvider } from 'styled-components'; import { Theme, themes } from '../../components'; +import * as messaging from '../../messaging'; +import { flushAllPromises } from '../../testHelpers'; import Account from './Account'; // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-call configure({ adapter: new Adapter() }); +jest.spyOn(messaging, 'getAllMetatdata').mockResolvedValue([]); + describe('Account component', () => { let wrapper: ReactWrapper; const VALID_ADDRESS = 'HjoBp62cvsWDA3vtNMWxz6c9q13ReEHi9UGHK7JbZweH5g5'; @@ -29,9 +34,10 @@ describe('Account component', () => { ); - it('shows Export option if account is not external', () => { + it('shows Export option if account is not external', async () => { wrapper = mountAccountComponent({ isExternal: false, type: 'ed25519' }); wrapper.find('.settings').first().simulate('click'); + await act(flushAllPromises); expect(wrapper.find('a.menuItem').length).toBe(4); expect(wrapper.find('a.menuItem').at(0).text()).toBe('Rename'); @@ -41,9 +47,10 @@ describe('Account component', () => { expect(wrapper.find('.genesisSelection').exists()).toBe(true); }); - it('does not show Export option if account is external', () => { + it('does not show Export option if account is external', async () => { wrapper = mountAccountComponent({ isExternal: true, type: 'ed25519' }); wrapper.find('.settings').first().simulate('click'); + await act(flushAllPromises); expect(wrapper.find('a.menuItem').length).toBe(2); expect(wrapper.find('a.menuItem').at(0).text()).toBe('Rename'); @@ -51,9 +58,10 @@ describe('Account component', () => { expect(wrapper.find('.genesisSelection').exists()).toBe(true); }); - it('does not show Derive option if account is of ethereum type', () => { + it('does not show Derive option if account is of ethereum type', async () => { wrapper = mountAccountComponent({ isExternal: false, type: 'ethereum' }); wrapper.find('.settings').first().simulate('click'); + await act(flushAllPromises); expect(wrapper.find('a.menuItem').length).toBe(3); expect(wrapper.find('a.menuItem').at(0).text()).toBe('Rename'); @@ -62,9 +70,10 @@ describe('Account component', () => { expect(wrapper.find('.genesisSelection').exists()).toBe(true); }); - it('does not show genesis hash selection dropsown if account is hardware', () => { + it('does not show genesis hash selection dropsown if account is hardware', async () => { wrapper = mountAccountComponent({ isExternal: true, isHardware: true }); wrapper.find('.settings').first().simulate('click'); + await act(flushAllPromises); expect(wrapper.find('a.menuItem').length).toBe(2); expect(wrapper.find('a.menuItem').at(0).text()).toBe('Rename'); diff --git a/packages/extension-ui/src/Popup/Derive/Derive.test.tsx b/packages/extension-ui/src/Popup/Derive/Derive.test.tsx index 14e25787..e2dda7c2 100644 --- a/packages/extension-ui/src/Popup/Derive/Derive.test.tsx +++ b/packages/extension-ui/src/Popup/Derive/Derive.test.tsx @@ -89,6 +89,8 @@ describe('Derive', () => { // eslint-disable-next-line @typescript-eslint/require-await jest.spyOn(messaging, 'validateAccount').mockImplementation(async (_, pass: string) => pass === parentPassword); + // silencing the following expected console.error + console.error = jest.fn(); // eslint-disable-next-line @typescript-eslint/require-await jest.spyOn(messaging, 'validateDerivationPath').mockImplementation(async (_, path) => { if (path === '//') { diff --git a/packages/extension-ui/src/Popup/Export.test.tsx b/packages/extension-ui/src/Popup/Export.test.tsx index feccfe26..03ae49b5 100644 --- a/packages/extension-ui/src/Popup/Export.test.tsx +++ b/packages/extension-ui/src/Popup/Export.test.tsx @@ -52,6 +52,8 @@ describe('Export component', () => { }); it('shows an error if the password is wrong', async () => { + // silencing the following expected console.error + console.error = jest.fn(); // eslint-disable-next-line @typescript-eslint/require-await jest.spyOn(messaging, 'exportAccount').mockImplementation(async () => { throw new Error('Unable to decode using the supplied passphrase'); @@ -68,6 +70,8 @@ describe('Export component', () => { }); it('shows no error when typing again after a wrong password', async () => { + // silencing the following expected console.error + console.error = jest.fn(); // eslint-disable-next-line @typescript-eslint/require-await jest.spyOn(messaging, 'exportAccount').mockImplementation(async () => { throw new Error('Unable to decode using the supplied passphrase'); diff --git a/packages/extension-ui/src/Popup/ImportSeed/ImportSeed.test.tsx b/packages/extension-ui/src/Popup/ImportSeed/ImportSeed.test.tsx index c5b8b17a..f07f1b28 100644 --- a/packages/extension-ui/src/Popup/ImportSeed/ImportSeed.test.tsx +++ b/packages/extension-ui/src/Popup/ImportSeed/ImportSeed.test.tsx @@ -26,6 +26,8 @@ const account = { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-call configure({ adapter: new Adapter() }); +jest.spyOn(messaging, 'getAllMetatdata').mockResolvedValue([]); + const typeSeed = async (wrapper: ReactWrapper, value: string) => { wrapper.find('textarea').first().simulate('change', { target: { value } }); await act(flushAllPromises); @@ -86,7 +88,9 @@ describe('ImportSeed', () => { }); it('shows an error when incorrect seed is typed and next step button is enabled', async () => { - // eslint-disable-next-line @typescript-eslint/require-await + // silencing the following expected console.error + console.error = jest.fn(); + // eslint-disable-next-line @typescript-eslint/require-await jest.spyOn(messaging, 'validateSeed').mockImplementation(async () => { throw new Error('Some test error message'); }); @@ -124,6 +128,9 @@ describe('ImportSeed', () => { it('shows an error when derivation path is incorrect and next step button is disabled', async () => { const wrongPath = 'wrong'; const suri = `${account.seed}${wrongPath}`; + + // silencing the following expected console.error + console.error = jest.fn(); // eslint-disable-next-line @typescript-eslint/require-await const validateCall = jest.spyOn(messaging, 'validateSeed').mockImplementation(async () => { throw new Error('Some test error message'); diff --git a/packages/extension-ui/src/Popup/Signing/Signing.test.tsx b/packages/extension-ui/src/Popup/Signing/Signing.test.tsx index b24b727a..04e549e3 100644 --- a/packages/extension-ui/src/Popup/Signing/Signing.test.tsx +++ b/packages/extension-ui/src/Popup/Signing/Signing.test.tsx @@ -153,31 +153,40 @@ describe('Signing requests', () => { expect(wrapper.find(Request).prop('signId')).toBe(signRequests[0].id); }); - it('only the right arrow should be active on first screen', () => { + it('only the right arrow should be active on first screen', async () => { expect(wrapper.find('FontAwesomeIcon.arrowLeft')).toHaveLength(1); expect(wrapper.find('FontAwesomeIcon.arrowLeft.active')).toHaveLength(0); expect(wrapper.find('FontAwesomeIcon.arrowRight.active')).toHaveLength(1); wrapper.find('FontAwesomeIcon.arrowLeft').simulate('click'); + await act(flushAllPromises); + expect(wrapper.find(TransactionIndex).text()).toBe('1/2'); }); - it('should display second request after clicking right arrow', () => { + it('should display second request after clicking right arrow', async () => { wrapper.find('FontAwesomeIcon.arrowRight').simulate('click'); + await act(flushAllPromises); + expect(wrapper.find(TransactionIndex).text()).toBe('2/2'); expect(wrapper.find(Request).prop('signId')).toBe(signRequests[1].id); }); - it('only the left should be active on second screen', () => { + it('only the left should be active on second screen', async () => { wrapper.find('FontAwesomeIcon.arrowRight').simulate('click'); + await act(flushAllPromises); + expect(wrapper.find('FontAwesomeIcon.arrowLeft.active')).toHaveLength(1); expect(wrapper.find('FontAwesomeIcon.arrowRight')).toHaveLength(1); expect(wrapper.find('FontAwesomeIcon.arrowRight.active')).toHaveLength(0); expect(wrapper.find(TransactionIndex).text()).toBe('2/2'); }); - it('should display previous request after the left arrow has been clicked', () => { + it('should display previous request after the left arrow has been clicked', async () => { wrapper.find('FontAwesomeIcon.arrowRight').simulate('click'); + await act(flushAllPromises); wrapper.find('FontAwesomeIcon.arrowLeft').simulate('click'); + await act(flushAllPromises); + expect(wrapper.find(TransactionIndex).text()).toBe('1/2'); expect(wrapper.find(Request).prop('signId')).toBe(signRequests[0].id); }); @@ -245,8 +254,10 @@ describe('Signing requests', () => { ]); }); - it('correctly displays request 2', () => { + it('correctly displays request 2', async () => { wrapper.find('FontAwesomeIcon.arrowRight').simulate('click'); + await act(flushAllPromises); + expect(wrapper.find(Address).find('.fullAddress').text()).toBe(signRequests[1].account.address); expect(wrapper.find(Extrinsic).find('td.data').map((el): string => el.text())).toEqual([ 'https://polkadot.js.org/apps', @@ -264,48 +275,66 @@ describe('Signing requests', () => { }); describe('Submitting', () => { - it('passes request id to cancel call', () => { + it('passes request id to cancel call', async () => { wrapper.find('.cancelButton').find('a').simulate('click'); + await act(flushAllPromises); + expect(messaging.cancelSignRequest).toBeCalledWith(signRequests[0].id); }); it('passes request id and password to approve call', async () => { wrapper.find(Input).simulate('change', { target: { value: 'hunter1' } }); + await act(flushAllPromises); + wrapper.find(Button).find('button').simulate('click'); await act(flushAllPromises); wrapper.update(); + expect(messaging.approveSignPassword).toBeCalledWith(signRequests[0].id, false, 'hunter1'); }); it('asks the background to cache the password when the relevant checkbox is checked', async () => { check(wrapper.find('input[type="checkbox"]')); + await act(flushAllPromises); + wrapper.find(Input).simulate('change', { target: { value: 'hunter1' } }); + await act(flushAllPromises); + wrapper.find(Button).find('button').simulate('click'); await act(flushAllPromises); wrapper.update(); + expect(messaging.approveSignPassword).toBeCalledWith(signRequests[0].id, true, 'hunter1'); }); it('shows an error when the password is wrong', async () => { + // silencing the following expected console.error + console.error = jest.fn(); // eslint-disable-next-line @typescript-eslint/require-await jest.spyOn(messaging, 'approveSignPassword').mockImplementation(async () => { throw new Error('Unable to decode using the supplied passphrase'); }); - await act(flushAllPromises); - wrapper.update(); + wrapper.find(Input).simulate('change', { target: { value: 'anything' } }); + await act(flushAllPromises); + wrapper.find(Button).find('button').simulate('click'); await act(flushAllPromises); wrapper.update(); + expect(wrapper.find('.warning-message').first().text()).toBe('Unable to decode using the supplied passphrase'); }); - it('when last request has been removed/cancelled, shows the previous one', () => { + it('when last request has been removed/cancelled, shows the previous one', async () => { wrapper.find('FontAwesomeIcon.arrowRight').simulate('click'); + await act(flushAllPromises); + act(() => { emitter.emit('request', [signRequests[0]]); }); + await act(flushAllPromises); wrapper.update(); + expect(wrapper.find(TransactionIndex)).toHaveLength(0); expect(wrapper.find(Request).prop('signId')).toBe(signRequests[0].id); });