Skip to content

Commit ba5d459

Browse files
authored
feat: adds skeleton loader for quote fetching (#27174)
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Adds a skeleton loader during quote fetching in the swaps experience. <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: improves quote loading UI ## **Related issues** Fixes: null ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk UI/test-only change that adds deterministic `testID`s and a small unit test for the quote details loading skeleton; no business logic or data flow changes. > > **Overview** > Adds a dedicated `QuoteDetailsCardSkeleton` loading state with per-row `testID`s and re-exports it from `QuoteDetailsCard/index.ts`. > > Updates `QuoteDetailsCard.test.tsx` to cover the skeleton, asserting the `QUOTE_DETAILS_SKELETON` container renders and contains **four** loading rows. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 4309445. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent 94d5408 commit ba5d459

3 files changed

Lines changed: 21 additions & 0 deletions

File tree

app/components/UI/Bridge/components/QuoteDetailsCard/QuoteDetailsCard.test.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import '../../_mocks_/initialState';
33
import { fireEvent, waitFor } from '@testing-library/react-native';
44
import { renderScreen } from '../../../../../util/test/renderWithProvider';
55
import QuoteDetailsCard from './QuoteDetailsCard';
6+
import QuoteDetailsCardSkeleton from './QuoteDetailsCardSkeleton';
67
import { strings } from '../../../../../../locales/i18n';
78
import Routes from '../../../../../constants/navigation/Routes';
89
import mockQuotes from '../../_mocks_/mock-quotes-sol-sol.json';
@@ -11,6 +12,7 @@ import { createBridgeTestState } from '../../testUtils';
1112
import { useBridgeQuoteData } from '../../hooks/useBridgeQuoteData';
1213
import { MetaMetricsSwapsEventSource } from '@metamask/bridge-controller';
1314
import { PriceImpactModalType } from '../PriceImpactModal/constants';
15+
import { BridgeViewSelectorsIDs } from '../../Views/BridgeView/BridgeView.testIds';
1416

1517
jest.mock(
1618
'../../../../../animations/rewards_icon_animations.riv',
@@ -273,11 +275,28 @@ const QuoteDetailsCardTestScreen = () => (
273275
/>
274276
);
275277

278+
const QuoteDetailsCardSkeletonTestScreen = () => <QuoteDetailsCardSkeleton />;
279+
276280
describe('QuoteDetailsCard', () => {
277281
beforeEach(() => {
278282
jest.clearAllMocks();
279283
});
280284

285+
it('renders a four-row loading skeleton', () => {
286+
const { getByTestId, getAllByTestId } = renderScreen(
287+
QuoteDetailsCardSkeletonTestScreen,
288+
{
289+
name: Routes.BRIDGE.ROOT,
290+
},
291+
{ state: testState },
292+
);
293+
294+
expect(
295+
getByTestId(BridgeViewSelectorsIDs.QUOTE_DETAILS_SKELETON),
296+
).toBeDefined();
297+
expect(getAllByTestId('quote-details-card-loading-row')).toHaveLength(4);
298+
});
299+
281300
it('renders initial state', () => {
282301
const { toJSON } = renderScreen(
283302
QuoteDetailsCardTestScreen,

app/components/UI/Bridge/components/QuoteDetailsCard/QuoteDetailsCardSkeleton.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const QuoteDetailsCardSkeleton = () => (
2323
{ROWS.map(([left, right], i) => (
2424
<Box
2525
key={i}
26+
testID="quote-details-card-loading-row"
2627
flexDirection={BoxFlexDirection.Row}
2728
justifyContent={BoxJustifyContent.Between}
2829
alignItems={BoxAlignItems.Center}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export { default } from './QuoteDetailsCard';
2+
export { default as QuoteDetailsCardSkeleton } from './QuoteDetailsCardSkeleton';

0 commit comments

Comments
 (0)