-
Notifications
You must be signed in to change notification settings - Fork 448
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: transaction approval screen showing odd half loading state (#1218)
Fixes #1201 - Fixes loading state only being partially applied to TxApprove components - Adds unit tests for TxApprove (as a dumb component) ## Before <img width="348" alt="Screenshot 2024-04-08 at 20 27 43" src="https://github.com/FuelLabs/fuels-wallet/assets/114662397/6bbcdbbd-c631-415f-9151-6d70fa182a35"> ## After https://github.com/FuelLabs/fuels-wallet/assets/3487334/60518df0-3b84-4d4c-881b-cc26dfc9b081
- Loading branch information
1 parent
8f94aee
commit 616f091
Showing
3 changed files
with
178 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"fuels-wallet": patch | ||
--- | ||
|
||
Fixes Approve Transaction screen staying in a partially loading state after approving a transaction |
167 changes: 167 additions & 0 deletions
167
packages/app/src/systems/Transaction/pages/TxApprove/TxApprove.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
import { fireEvent, render, screen } from '@testing-library/react'; | ||
import { TransactionStatus } from 'fuels'; | ||
|
||
import { TxRequestStatus } from '~/systems/DApp/machines/transactionRequestMachine'; | ||
import { TxApprove } from './TxApprove'; | ||
|
||
const mockNavigate = jest.fn(); | ||
|
||
jest.mock('~/systems/DApp', () => ({ | ||
useTransactionRequest: jest.fn(), | ||
})); | ||
jest.mock('~/systems/Asset', () => ({ | ||
useAssets: jest.fn(), | ||
})); | ||
jest.mock('react-router-dom', () => ({ | ||
...jest.requireActual('react-router-dom'), // use actual for all non-hook parts | ||
useNavigate: () => ({ navigate: mockNavigate }), | ||
})); | ||
jest.mock('~/systems/Store', () => ({ | ||
store: { | ||
refreshNetworks: jest.fn(), | ||
refreshAccounts: jest.fn(), | ||
refreshBalance: jest.fn(), | ||
}, | ||
StoreProvider: ({ children }: { children: React.ReactNode }) => ( | ||
<>{children}</> | ||
), | ||
})); | ||
|
||
import { useAssets } from '~/systems/Asset'; | ||
import { useTransactionRequest } from '~/systems/DApp'; | ||
|
||
const mockUseTransactionRequest = useTransactionRequest as jest.Mock; | ||
const mockUseAssets = useAssets as jest.Mock; | ||
|
||
const mockTxResult = { | ||
id: 'tx_123', | ||
status: TransactionStatus.success, | ||
type: 'transfer', | ||
}; | ||
|
||
describe('TxApprove', () => { | ||
afterEach(() => { | ||
jest.clearAllMocks(); | ||
}); | ||
|
||
const setup = ( | ||
transactionRequestOverrides = {}, | ||
assetsOverrides = {}, | ||
mockStatus?: { status: TxRequestStatus; result: boolean } | ||
) => { | ||
const mockCustomStatus = mockStatus?.status ?? 'never'; | ||
mockUseTransactionRequest.mockReturnValue({ | ||
isLoading: false, | ||
showActions: true, | ||
status: jest.fn().mockImplementation((status) => { | ||
switch (status) { | ||
case mockCustomStatus: | ||
if (!mockStatus?.status) { | ||
throw new Error('Invalid mock status'); | ||
} | ||
return mockStatus?.result ?? false; | ||
case 'sending': | ||
return false; | ||
case 'success': | ||
return false; | ||
case 'failed': | ||
return false; | ||
case 'idle': | ||
return true; | ||
default: | ||
return false; | ||
} | ||
}), | ||
txResult: mockTxResult, | ||
approveStatus: jest.fn().mockReturnValue(TransactionStatus.success), | ||
handlers: { | ||
closeDialog: jest.fn(), | ||
approve: jest.fn(), | ||
tryAgain: jest.fn(), | ||
}, | ||
shouldShowLoader: false, | ||
shouldShowTx: true, | ||
title: 'Transaction Approval', | ||
providerUrl: 'https://example.com', | ||
...transactionRequestOverrides, | ||
}); | ||
|
||
mockUseAssets.mockReturnValue({ | ||
assets: [], | ||
isLoading: false, | ||
...assetsOverrides, | ||
}); | ||
|
||
render(<TxApprove />); | ||
}; | ||
|
||
it('calls the approve handler when approve button is clicked', () => { | ||
setup(); | ||
const approveButton = screen.getByText(/approve/i); | ||
fireEvent.click(approveButton); | ||
expect(mockUseTransactionRequest().handlers.approve).toHaveBeenCalled(); | ||
}); | ||
|
||
it('displays a loading indicator when assets are loading', () => { | ||
setup( | ||
{}, | ||
{ isLoading: true }, | ||
{ status: TxRequestStatus.idle, result: true } | ||
); | ||
expect(screen.getByText(/loading/i)).toBeDefined(); | ||
}); | ||
|
||
it('displays a loading indicator when status is sending', () => { | ||
setup({}, {}, { status: TxRequestStatus.sending, result: true }); | ||
expect(screen.getByText(/loading/i)).toBeDefined(); | ||
}); | ||
|
||
it('displays a loading indicator when the transaction is being processed', () => { | ||
setup({}, {}, { status: TxRequestStatus.loading, result: true }); | ||
expect(screen.getByText(/loading/i)).toBeDefined(); | ||
}); | ||
|
||
it('displays success when a transaction was completed', () => { | ||
setup({}, {}, { status: TxRequestStatus.success, result: true }); | ||
expect(screen.getByText(/success/i)).toBeDefined(); | ||
}); | ||
|
||
it('displays an error message when the transaction fails', () => { | ||
setup( | ||
{ approveStatus: jest.fn().mockReturnValue(TransactionStatus.failure) }, | ||
{}, | ||
{ status: TxRequestStatus.failed, result: true } | ||
); | ||
expect(screen.getByText(/failure/i)).toBeDefined(); | ||
}); | ||
|
||
it('does not show the approve button show actions is false', () => { | ||
setup({ showActions: false }); | ||
expect(screen.queryByText(/approve/i)).toBeNull(); | ||
}); | ||
|
||
it('shows the try again button when the transaction has failed', () => { | ||
setup( | ||
{ txResult: { ...mockTxResult, status: TransactionStatus.failure } }, | ||
{}, | ||
{ status: TxRequestStatus.failed, result: true } | ||
); | ||
expect(screen.getByText(/try again/i)).toBeDefined(); | ||
}); | ||
|
||
it('calls the try again handler when try again button is clicked', () => { | ||
setup( | ||
{ txResult: { ...mockTxResult, status: TransactionStatus.failure } }, | ||
{}, | ||
{ status: TxRequestStatus.failed, result: true } | ||
); | ||
fireEvent.click(screen.getByText(/try again/i)); | ||
expect(mockUseTransactionRequest().handlers.tryAgain).toHaveBeenCalled(); | ||
}); | ||
|
||
it('calls the close dialog handler when back button is clicked', () => { | ||
setup(); | ||
fireEvent.click(screen.getByText(/back/i)); | ||
expect(mockUseTransactionRequest().handlers.closeDialog).toHaveBeenCalled(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters