Files
pezkuwi-extension/packages/extension-ui/src/Popup/Export.spec.tsx
T
Satoshi Qazi Muhammed 9d769676e4 Move to @pezkuwi/dev 0.86 (eslint 10 toolchain)
- @pezkuwi/dev, dev-test, dev-ts ^0.86.3 in the root and in every
  workspace package (they still asked for 0.84.3)
- tsconfig.base target ES2022, the @pezkuwi/dev default; it carries
  the ErrorOptions type for `cause`
- rethrown errors carry the original as `cause`; rejections are
  normalised to Error
- page/messaging: the typed subscriber is called directly, not as
  `Function`
- chrome mock: constant results through Promise.resolve
- useLedger: drop a construction every branch below repeated
- InputWithLabel: onKeyDown instead of the deprecated onKeyPress
- Account: toggleActions + 1 instead of a pre-increment of a parameter
- optional chains where a guard tested the same value
- specs: mount<React.Component> so the wrappers are not `any`-typed
- AccountsStore.set keeps its async override of KeyringStore.set:
  BaseStore.set handles its own failure, so it never rejects
- extension-chains keeps its ChainProperties assertion: the package's
  own build does not load the type augmentation
- the existing React Compiler findings (37, react-hooks rules only)
  are recorded in eslint-suppressions.json; a new one fails lint
2026-10-09 16:32:46 +04:00

108 lines
4.1 KiB
TypeScript

// Copyright 2019-2026 @pezkuwi/extension-ui authors & contributors
// SPDX-License-Identifier: Apache-2.0
import '@pezkuwi/extension-mocks/chrome';
import type { ReactWrapper } from 'enzyme';
import type * as _ from '@pezkuwi/dev-test/globals.d.ts';
import type { KeyringPair$Json } from '@pezkuwi/keyring/types';
import Adapter from '@wojtekmaj/enzyme-adapter-react-17';
import enzyme from 'enzyme';
import React from 'react';
import { act } from 'react-dom/test-utils';
import { MemoryRouter, Route } from 'react-router';
import { Button } from '../components/index.js';
import * as messaging from '../messaging.js';
import { flushAllPromises } from '../testHelpers.js';
import Export from './Export.js';
const { configure, mount } = enzyme;
// // NOTE Required for spyOn when using @swc/jest
// // https://github.com/swc-project/swc/issues/3843
// jest.mock('../messaging', (): Record<string, unknown> => ({
// __esModule: true,
// ...jest.requireActual('../messaging')
// }));
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
configure({ adapter: new Adapter() });
describe('Export component', () => {
let wrapper: ReactWrapper;
const VALID_ADDRESS = 'HjoBp62cvsWDA3vtNMWxz6c9q13ReEHi9UGHK7JbZweH5g5';
const enterPassword = (password = 'any password'): void => {
wrapper.find('[data-export-password] input').simulate('change', { target: { value: password } });
};
beforeEach(() => {
jest.spyOn(messaging, 'exportAccount').mockImplementation(() => Promise.resolve({ exportedJson: { meta: { name: 'account_name' } } as unknown as KeyringPair$Json }));
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
wrapper = mount(
<MemoryRouter initialEntries={ [`/account/export/${VALID_ADDRESS}`] }>
<Route path='/account/export/:address'><Export /></Route>
</MemoryRouter>
);
});
it('creates export message on button press', async () => {
enterPassword('passw0rd');
wrapper.find('[data-export-button] button').simulate('click');
await act(flushAllPromises);
expect(messaging.exportAccount).toHaveBeenCalledWith(VALID_ADDRESS, 'passw0rd');
});
it('button is disabled before any password is typed', () => {
expect(wrapper.find(Button).prop('isDisabled')).toBe(true);
});
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');
});
enterPassword();
wrapper.find('[data-export-button] button').simulate('click');
await act(flushAllPromises);
wrapper.update();
// the first message is "You are exporting your account. Keep it safe and don't share it with anyone."
expect(wrapper.find('.warning-message').at(1).text()).toBe('Unable to decode using the supplied passphrase');
expect(wrapper.find(Button).prop('isDisabled')).toBe(true);
expect(wrapper.find('InputWithLabel').first().prop('isError')).toBe(true);
});
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');
});
enterPassword();
wrapper.find('[data-export-button] button').simulate('click');
await act(flushAllPromises);
wrapper.update();
enterPassword();
// the first message is "You are exporting your account. Keep it safe and don't share it with anyone."
expect(wrapper.find('.warning-message')).toHaveLength(1);
expect(wrapper.find(Button).prop('isDisabled')).toBe(false);
expect(wrapper.find('InputWithLabel').first().prop('isError')).toBe(false);
});
it('button is enabled after password is typed', async () => {
enterPassword();
await act(flushAllPromises);
expect(wrapper.find(Button).prop('isDisabled')).toBe(false);
});
});