import React from 'react'; import configureMockStore from 'redux-mock-store'; import { fireEvent, waitFor } from '@testing-library/react'; import thunk from 'redux-thunk'; import { renderWithProvider } from '../../../test/lib/render-helpers'; import mockState from '../../../test/data/mock-state.json'; import { MetaMetricsContext } from '../../contexts/metametrics'; import { MetaMetricsEventCategory, MetaMetricsEventKeyType, MetaMetricsEventName, } from '../../../shared/constants/metametrics'; import { Modal } from '../../components/app/modals'; import configureStore from '../../store/store'; import RevealSeedPage from './reveal-seed'; const mockRequestRevealSeedWords = jest.fn(); const mockShowModal = jest.fn(); jest.mock('../../store/actions.ts', () => ({ ...jest.requireActual('../../store/actions.ts'), requestRevealSeedWords: () => mockRequestRevealSeedWords, })); const mockStateWithModal = { ...mockState, appState: { ...mockState.appState, modal: { open: true, modalState: { name: 'HOLD_TO_REVEAL_SRP', props: { onLongPressed: jest.fn(), }, }, }, }, }; describe('Reveal Seed Page', () => { const mockStore = configureMockStore([thunk])(mockStateWithModal); afterEach(() => { jest.clearAllMocks(); }); it('should match snapshot', () => { const { container } = renderWithProvider(, mockStore); expect(container).toMatchSnapshot(); }); it('form submit', async () => { mockRequestRevealSeedWords.mockResolvedValueOnce('test srp'); const { queryByTestId, queryByText } = renderWithProvider( , mockStore, ); fireEvent.change(queryByTestId('input-password'), { target: { value: 'password' }, }); fireEvent.click(queryByText('Next')); await waitFor(() => { expect(mockRequestRevealSeedWords).toHaveBeenCalled(); }); }); it('shows hold to reveal', async () => { mockRequestRevealSeedWords.mockResolvedValueOnce('test srp'); const { queryByTestId, queryByText } = renderWithProvider( , mockStore, ); fireEvent.change(queryByTestId('input-password'), { target: { value: 'password' }, }); fireEvent.click(queryByText('Next')); await waitFor(() => { expect(mockRequestRevealSeedWords).toHaveBeenCalled(); }); }); it('does not show modal on bad password', async () => { mockRequestRevealSeedWords.mockRejectedValueOnce('incorrect password'); const { queryByTestId, queryByText } = renderWithProvider( , mockStore, ); fireEvent.change(queryByTestId('input-password'), { target: { value: 'bad password' }, }); fireEvent.click(queryByText('Next')); await waitFor(() => { expect(mockShowModal).not.toHaveBeenCalled(); }); }); it('should show srp after hold to reveal', async () => { // need to use actual store because redux-mock-store does not execute actions const store = configureStore(mockState); mockRequestRevealSeedWords.mockResolvedValueOnce('test srp'); const { queryByTestId, queryByText } = renderWithProvider(
, store, ); const nextButton = queryByText('Next'); fireEvent.change(queryByTestId('input-password'), { target: { value: 'password' }, }); fireEvent.click(nextButton); await waitFor(() => { expect(mockRequestRevealSeedWords).toHaveBeenCalled(); expect(queryByText('Keep your SRP safe')).toBeInTheDocument(); }); }); it('emits events when correct password is entered', async () => { const store = configureStore(mockState); mockRequestRevealSeedWords .mockRejectedValueOnce('incorrect password') .mockResolvedValueOnce('test srp'); const mockTrackEvent = jest.fn(); const { queryByTestId, queryByText, getByText, queryByLabelText } = renderWithProvider( , store, ); fireEvent.change(queryByTestId('input-password'), { target: { value: 'bad-password' }, }); fireEvent.click(queryByText('Next')); await waitFor(() => { expect(mockRequestRevealSeedWords).toHaveBeenCalled(); expect(mockTrackEvent).toHaveBeenNthCalledWith(1, { category: MetaMetricsEventCategory.Keys, event: MetaMetricsEventName.KeyExportRequested, properties: { key_type: MetaMetricsEventKeyType.Srp, }, }); expect(mockTrackEvent).toHaveBeenNthCalledWith(2, { category: MetaMetricsEventCategory.Keys, event: MetaMetricsEventName.SrpRevealNextClicked, properties: { key_type: MetaMetricsEventKeyType.Srp, }, }); expect(mockTrackEvent).toHaveBeenLastCalledWith({ category: MetaMetricsEventCategory.Keys, event: MetaMetricsEventName.KeyExportFailed, properties: { key_type: MetaMetricsEventKeyType.Srp, reason: undefined, }, }); }); mockTrackEvent.mockClear(); fireEvent.change(queryByTestId('input-password'), { target: { value: 'password' }, }); fireEvent.click(queryByText('Next')); await waitFor(() => { expect(mockTrackEvent).toHaveBeenNthCalledWith(1, { category: MetaMetricsEventCategory.Keys, event: MetaMetricsEventName.KeyExportRequested, properties: { key_type: MetaMetricsEventKeyType.Srp, }, }); expect(mockTrackEvent).toHaveBeenNthCalledWith(2, { category: MetaMetricsEventCategory.Keys, event: MetaMetricsEventName.SrpRevealNextClicked, properties: { key_type: MetaMetricsEventKeyType.Srp, }, }); expect(mockTrackEvent).toHaveBeenLastCalledWith({ category: MetaMetricsEventCategory.Keys, event: MetaMetricsEventName.KeyExportRevealed, properties: { key_type: MetaMetricsEventKeyType.Srp, }, }); expect(queryByText('Keep your SRP safe')).toBeInTheDocument(); }); const holdButton = getByText('Hold to reveal SRP'); const circleLocked = queryByLabelText('hold to reveal circle locked'); fireEvent.pointerDown(holdButton); fireEvent.transitionEnd(circleLocked); const circleUnlocked = queryByLabelText('hold to reveal circle unlocked'); fireEvent.animationEnd(circleUnlocked); await waitFor(() => { expect(holdButton.firstChild).toHaveClass( 'hold-to-reveal-button__icon-container', ); // tests that the mock srp is now shown. expect(getByText('test srp')).toBeInTheDocument(); expect(mockTrackEvent).toHaveBeenLastCalledWith({ category: MetaMetricsEventCategory.Keys, event: MetaMetricsEventName.SrpViewSrpText, properties: { key_type: MetaMetricsEventKeyType.Srp, }, }); }); mockTrackEvent.mockClear(); // completed hold click const qrTab = getByText('QR'); const textTab = getByText('Text'); fireEvent.click(qrTab); await waitFor(() => { expect(mockTrackEvent).toHaveBeenLastCalledWith({ category: MetaMetricsEventCategory.Keys, event: MetaMetricsEventName.SrpViewsSrpQR, properties: { key_type: MetaMetricsEventKeyType.Srp, }, }); }); fireEvent.click(textTab); await waitFor(() => { expect(mockTrackEvent).toHaveBeenLastCalledWith({ category: MetaMetricsEventCategory.Keys, event: MetaMetricsEventName.SrpViewSrpText, properties: { key_type: MetaMetricsEventKeyType.Srp, }, }); }); mockTrackEvent.mockClear(); const copyButton = getByText('Copy to clipboard'); fireEvent.click(copyButton); await waitFor(() => { expect(mockTrackEvent).toHaveBeenNthCalledWith(1, { category: MetaMetricsEventCategory.Keys, event: MetaMetricsEventName.KeyExportCopied, properties: { key_type: MetaMetricsEventKeyType.Srp, copy_method: 'clipboard', }, }); expect(mockTrackEvent).toHaveBeenNthCalledWith(2, { category: MetaMetricsEventCategory.Keys, event: MetaMetricsEventName.SrpCopiedToClipboard, properties: { key_type: MetaMetricsEventKeyType.Srp, copy_method: 'clipboard', }, }); }); const doneButton = getByText('Close'); fireEvent.click(doneButton); await waitFor(() => { expect(mockTrackEvent).toHaveBeenLastCalledWith({ category: MetaMetricsEventCategory.Keys, event: MetaMetricsEventName.SrpRevealCloseClicked, properties: { key_type: MetaMetricsEventKeyType.Srp, }, }); }); }); it('should emit event when cancel is clicked', async () => { mockRequestRevealSeedWords .mockRejectedValueOnce('incorrect password') .mockResolvedValueOnce('test srp'); const mockTrackEvent = jest.fn(); const { queryByText } = renderWithProvider( , mockStore, ); const cancelButton = queryByText('Cancel'); fireEvent.click(cancelButton); await waitFor(() => { expect(mockTrackEvent).toHaveBeenNthCalledWith(1, { category: MetaMetricsEventCategory.Keys, event: MetaMetricsEventName.KeyExportCanceled, properties: { key_type: MetaMetricsEventKeyType.Srp, }, }); expect(mockTrackEvent).toHaveBeenNthCalledWith(2, { category: MetaMetricsEventCategory.Keys, event: MetaMetricsEventName.SrpRevealCancelled, properties: { key_type: MetaMetricsEventKeyType.Srp, }, }); }); }); });