@0xsequence/marketplace-sdk 0.8.2 → 0.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/dist/{builder-types-Wrqq6YoW.d.ts → builder-types-BY6eD6vD.d.ts} +1 -1
- package/dist/{chunk-IZ44XPBH.js → chunk-25CAMYCG.js} +2 -2
- package/dist/{chunk-LDHGFXPJ.js → chunk-44YGZVBS.js} +2 -2
- package/dist/{chunk-BNAUZXPV.js → chunk-ALICO7NG.js} +3 -3
- package/dist/chunk-ALICO7NG.js.map +1 -0
- package/dist/{chunk-3II5GLHE.js → chunk-HGKWWZWY.js} +2 -2
- package/dist/{chunk-S2UFNIYX.js → chunk-HRL2TMXU.js} +12 -9
- package/dist/chunk-HRL2TMXU.js.map +1 -0
- package/dist/{chunk-XOHAZXBZ.js → chunk-VBRJ2OPM.js} +14 -6
- package/dist/chunk-VBRJ2OPM.js.map +1 -0
- package/dist/{chunk-F6CUGMI4.js → chunk-VF3LWBQB.js} +378 -263
- package/dist/chunk-VF3LWBQB.js.map +1 -0
- package/dist/{chunk-GBQVYNCD.js → chunk-XUNDLCEH.js} +3 -3
- package/dist/{chunk-4DFOSZTE.js → chunk-ZSCZLHKX.js} +195 -3
- package/dist/chunk-ZSCZLHKX.js.map +1 -0
- package/dist/{create-config-B58hoCDv.d.ts → create-config-qDML4ZNn.d.ts} +1 -1
- package/dist/{index-PhhCRKUH.d.ts → index-DtWR0b_l.d.ts} +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +7 -9
- package/dist/{lowestListing-CuLxIWxy.d.ts → lowestListing-W7P4EkC3.d.ts} +34 -11
- package/dist/{marketplace.gen-De2-sxiG.d.ts → marketplace.gen-DS-MmGEB.d.ts} +35 -4
- package/dist/react/_internal/api/index.d.ts +2 -2
- package/dist/react/_internal/api/index.js +1 -1
- package/dist/react/_internal/databeat/index.d.ts +1 -1
- package/dist/react/_internal/databeat/index.js +8 -8
- package/dist/react/_internal/index.d.ts +5 -5
- package/dist/react/_internal/index.js +2 -2
- package/dist/react/_internal/wagmi/index.d.ts +3 -3
- package/dist/react/_internal/wagmi/index.js +2 -2
- package/dist/react/hooks/index.d.ts +72 -49
- package/dist/react/hooks/index.js +9 -7
- package/dist/react/hooks/options/index.d.ts +3 -3
- package/dist/react/hooks/options/index.js +4 -4
- package/dist/react/index.d.ts +8 -8
- package/dist/react/index.js +12 -10
- package/dist/react/queries/index.d.ts +2 -2
- package/dist/react/queries/index.js +7 -3
- package/dist/react/ssr/index.d.ts +2 -2
- package/dist/react/ssr/index.js +3 -3
- package/dist/react/ui/components/collectible-card/index.d.ts +1 -1
- package/dist/react/ui/components/collectible-card/index.js +10 -10
- package/dist/react/ui/icons/index.js +3 -3
- package/dist/react/ui/index.d.ts +1 -1
- package/dist/react/ui/index.js +10 -10
- package/dist/react/ui/modals/_internal/components/actionModal/index.js +8 -8
- package/dist/{services-BdzIAR9w.d.ts → services-BOX67E7W.d.ts} +1 -1
- package/dist/types/index.d.ts +3 -3
- package/dist/types/index.js +2 -4
- package/dist/{types-CmHOStH3.d.ts → types-CJLhc2VZ.d.ts} +2 -2
- package/dist/utils/abi/index.js +5 -5
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.js +7 -7
- package/package.json +1 -1
- package/src/react/_internal/api/__mocks__/marketplace.msw.ts +35 -18
- package/src/react/_internal/api/marketplace.gen.ts +39 -6
- package/src/react/_internal/api/zod-schema.ts +7 -18
- package/src/react/hooks/__tests__/useCancelTransactionSteps.test.tsx +4 -9
- package/src/react/hooks/__tests__/useGenerateCancelTransaction.test.tsx +5 -4
- package/src/react/hooks/__tests__/useGenerateListingTransaction.test.tsx +14 -2
- package/src/react/hooks/__tests__/useGenerateOfferTransaction.test.tsx +115 -57
- package/src/react/hooks/__tests__/useGenerateSellTransaction.test.tsx +10 -3
- package/src/react/hooks/__tests__/useInventory.test.tsx +294 -0
- package/src/react/hooks/index.ts +1 -0
- package/src/react/hooks/useAutoSelectFeeOption.tsx +10 -3
- package/src/react/hooks/useCancelOrder.tsx +1 -0
- package/src/react/hooks/useCancelTransactionSteps.tsx +20 -6
- package/src/react/hooks/useGenerateOfferTransaction.tsx +11 -1
- package/src/react/hooks/useInventory.tsx +15 -0
- package/src/react/hooks/util/optimisticCancelUpdates.ts +115 -0
- package/src/react/queries/index.ts +1 -0
- package/src/react/queries/inventory.ts +303 -0
- package/src/react/queries/listBalances.ts +1 -8
- package/src/react/queries/listCollectibles.ts +12 -3
- package/src/react/ui/modals/CreateListingModal/__tests__/Modal.test.tsx +74 -104
- package/src/react/ui/modals/CreateListingModal/hooks/useTransactionSteps.tsx +2 -2
- package/src/react/ui/modals/MakeOfferModal/__tests__/Modal.test.tsx +108 -78
- package/src/react/ui/modals/MakeOfferModal/hooks/useTransactionSteps.tsx +2 -2
- package/src/react/ui/modals/SellModal/hooks/useTransactionSteps.tsx +2 -2
- package/src/react/ui/modals/_internal/components/actionModal/ActionModal.test.tsx +286 -0
- package/src/react/ui/modals/_internal/components/actionModal/ActionModal.tsx +16 -4
- package/src/react/ui/modals/_internal/components/currencyOptionsSelect/__tests__/index.test.tsx +35 -132
- package/src/react/ui/modals/_internal/components/floorPriceText/__tests__/FloorPriceText.test.tsx +199 -0
- package/src/react/ui/modals/_internal/components/priceInput/__tests__/PriceInput.test.tsx +55 -0
- package/src/react/ui/modals/_internal/components/priceInput/index.tsx +1 -1
- package/src/react/ui/modals/_internal/components/switchChainModal/index.tsx +2 -2
- package/src/types/api-types.ts +0 -1
- package/test/const.ts +24 -0
- package/test/test-utils.tsx +74 -26
- package/.changeset/flat-parks-clean.md +0 -8
- package/.changeset/seven-doors-taste.md +0 -5
- package/dist/chunk-4DFOSZTE.js.map +0 -1
- package/dist/chunk-BNAUZXPV.js.map +0 -1
- package/dist/chunk-F6CUGMI4.js.map +0 -1
- package/dist/chunk-S2UFNIYX.js.map +0 -1
- package/dist/chunk-XOHAZXBZ.js.map +0 -1
- package/src/react/ui/modals/_internal/components/priceInput/__tests__/index.test.tsx +0 -164
- /package/dist/{chunk-IZ44XPBH.js.map → chunk-25CAMYCG.js.map} +0 -0
- /package/dist/{chunk-LDHGFXPJ.js.map → chunk-44YGZVBS.js.map} +0 -0
- /package/dist/{chunk-3II5GLHE.js.map → chunk-HGKWWZWY.js.map} +0 -0
- /package/dist/{chunk-GBQVYNCD.js.map → chunk-XUNDLCEH.js.map} +0 -0
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import { fireEvent, render, screen, waitFor } from '@test';
|
|
2
|
+
import { type Address, custom, zeroAddress } from 'viem';
|
|
3
|
+
import { mainnet, polygon } from 'viem/chains';
|
|
4
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
5
|
+
import { WalletKind } from '../../../../../_internal';
|
|
6
|
+
import * as walletModule from '../../../../../_internal/wallet/useWallet';
|
|
7
|
+
import { ActionModal } from './ActionModal';
|
|
8
|
+
|
|
9
|
+
const mockShowSwitchChainModal = vi.fn();
|
|
10
|
+
vi.mock('../switchChainModal', () => ({
|
|
11
|
+
useSwitchChainModal: () => ({
|
|
12
|
+
show: mockShowSwitchChainModal,
|
|
13
|
+
close: vi.fn(),
|
|
14
|
+
isSwitching$: { get: () => false },
|
|
15
|
+
}),
|
|
16
|
+
}));
|
|
17
|
+
|
|
18
|
+
describe('ActionModal', () => {
|
|
19
|
+
const mockOnClose = vi.fn();
|
|
20
|
+
const mockOnClick = vi.fn();
|
|
21
|
+
|
|
22
|
+
const defaultProps = {
|
|
23
|
+
isOpen: true,
|
|
24
|
+
onClose: mockOnClose,
|
|
25
|
+
title: 'Test Modal',
|
|
26
|
+
children: <div>Modal Content</div>,
|
|
27
|
+
ctas: [
|
|
28
|
+
{
|
|
29
|
+
label: 'Test Button',
|
|
30
|
+
onClick: mockOnClick,
|
|
31
|
+
testid: 'test-button',
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
chainId: polygon.id,
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
beforeEach(() => {
|
|
38
|
+
vi.clearAllMocks();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
describe('Loading states', () => {
|
|
42
|
+
it('should show a loading spinner when modalLoading prop is true', async () => {
|
|
43
|
+
render(<ActionModal {...defaultProps} modalLoading={true} />);
|
|
44
|
+
|
|
45
|
+
expect(screen.getByTestId('spinner')).toBeInTheDocument();
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('should show a loading spinner when isLoading from useWallet is true', async () => {
|
|
49
|
+
vi.spyOn(walletModule, 'useWallet').mockReturnValue({
|
|
50
|
+
wallet: null,
|
|
51
|
+
isLoading: true,
|
|
52
|
+
isError: false,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
render(<ActionModal {...defaultProps} />);
|
|
56
|
+
|
|
57
|
+
expect(screen.getByTestId('spinner')).toBeInTheDocument();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('should show error message when useWallet returns an error', () => {
|
|
61
|
+
vi.spyOn(walletModule, 'useWallet').mockReturnValue({
|
|
62
|
+
wallet: null,
|
|
63
|
+
isLoading: false,
|
|
64
|
+
isError: true,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
render(<ActionModal {...defaultProps} />);
|
|
68
|
+
|
|
69
|
+
expect(screen.getByTestId('error-loading-text')).toBeInTheDocument();
|
|
70
|
+
expect(screen.getByText('Error loading modal')).toBeInTheDocument();
|
|
71
|
+
expect(screen.queryByText('Modal Content')).not.toBeInTheDocument();
|
|
72
|
+
expect(screen.queryByTestId('test-button')).not.toBeInTheDocument();
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('should show modal content if loading states is false and no error', async () => {
|
|
76
|
+
vi.spyOn(walletModule, 'useWallet').mockReturnValue({
|
|
77
|
+
wallet: null,
|
|
78
|
+
isLoading: false,
|
|
79
|
+
isError: false,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
render(<ActionModal {...defaultProps} modalLoading={false} />);
|
|
83
|
+
|
|
84
|
+
expect(screen.getByText('Modal Content')).toBeInTheDocument();
|
|
85
|
+
expect(screen.getByTestId('test-button')).toBeInTheDocument();
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
describe('Chain switching', () => {
|
|
90
|
+
it('should automatically switch chain for Sequence WaaS wallets', async () => {
|
|
91
|
+
const switchChainMock = vi.fn();
|
|
92
|
+
|
|
93
|
+
vi.spyOn(walletModule, 'useWallet').mockReturnValue({
|
|
94
|
+
wallet: {
|
|
95
|
+
address: () => Promise.resolve(zeroAddress as Address),
|
|
96
|
+
getChainId: vi.fn().mockResolvedValue(mainnet.id),
|
|
97
|
+
switchChain: switchChainMock,
|
|
98
|
+
transport: custom({ request: vi.fn() }),
|
|
99
|
+
walletKind: WalletKind.sequence,
|
|
100
|
+
isWaaS: true,
|
|
101
|
+
handleConfirmTransactionStep: vi.fn(),
|
|
102
|
+
handleSendTransactionStep: vi.fn(),
|
|
103
|
+
handleSignMessageStep: vi.fn(),
|
|
104
|
+
hasTokenApproval: vi.fn(),
|
|
105
|
+
},
|
|
106
|
+
isLoading: false,
|
|
107
|
+
isError: false,
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
render(<ActionModal {...defaultProps} />);
|
|
111
|
+
|
|
112
|
+
expect(switchChainMock).toHaveBeenCalledWith(polygon.id);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('should show switch chain modal when CTA is clicked with chain mismatch', async () => {
|
|
116
|
+
mockShowSwitchChainModal.mockClear();
|
|
117
|
+
|
|
118
|
+
vi.spyOn(walletModule, 'useWallet').mockReturnValue({
|
|
119
|
+
wallet: {
|
|
120
|
+
address: () => Promise.resolve(zeroAddress as Address),
|
|
121
|
+
getChainId: vi.fn().mockResolvedValue(mainnet.id), // different from defaultProps.chainId
|
|
122
|
+
switchChain: vi.fn(),
|
|
123
|
+
transport: custom({ request: vi.fn() }),
|
|
124
|
+
walletKind: WalletKind.sequence,
|
|
125
|
+
isWaaS: false,
|
|
126
|
+
handleConfirmTransactionStep: vi.fn(),
|
|
127
|
+
handleSendTransactionStep: vi.fn(),
|
|
128
|
+
handleSignMessageStep: vi.fn(),
|
|
129
|
+
hasTokenApproval: vi.fn(),
|
|
130
|
+
},
|
|
131
|
+
isLoading: false,
|
|
132
|
+
isError: false,
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
render(<ActionModal {...defaultProps} />);
|
|
136
|
+
|
|
137
|
+
const button = screen.getByTestId('test-button');
|
|
138
|
+
fireEvent.click(button);
|
|
139
|
+
|
|
140
|
+
await waitFor(() => {
|
|
141
|
+
expect(mockShowSwitchChainModal).toHaveBeenCalledWith({
|
|
142
|
+
chainIdToSwitchTo: polygon.id,
|
|
143
|
+
onSuccess: expect.any(Function),
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('should directly execute callback when chain already matches', async () => {
|
|
149
|
+
mockOnClick.mockClear();
|
|
150
|
+
|
|
151
|
+
vi.spyOn(walletModule, 'useWallet').mockReturnValue({
|
|
152
|
+
wallet: {
|
|
153
|
+
address: () => Promise.resolve(zeroAddress as Address),
|
|
154
|
+
getChainId: vi.fn().mockResolvedValue(polygon.id), // Same as defaultProps.chainId
|
|
155
|
+
switchChain: vi.fn(),
|
|
156
|
+
transport: custom({ request: vi.fn() }),
|
|
157
|
+
walletKind: WalletKind.sequence,
|
|
158
|
+
isWaaS: false,
|
|
159
|
+
handleConfirmTransactionStep: vi.fn(),
|
|
160
|
+
handleSendTransactionStep: vi.fn(),
|
|
161
|
+
handleSignMessageStep: vi.fn(),
|
|
162
|
+
hasTokenApproval: vi.fn(),
|
|
163
|
+
},
|
|
164
|
+
isLoading: false,
|
|
165
|
+
isError: false,
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
render(<ActionModal {...defaultProps} />);
|
|
169
|
+
|
|
170
|
+
const button = screen.getByTestId('test-button');
|
|
171
|
+
fireEvent.click(button);
|
|
172
|
+
|
|
173
|
+
await waitFor(() => {
|
|
174
|
+
expect(mockOnClick).toHaveBeenCalled();
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
describe('CTA buttons', () => {
|
|
180
|
+
it('should call onClick when CTA button is clicked', async () => {
|
|
181
|
+
const onClick = vi.fn();
|
|
182
|
+
render(
|
|
183
|
+
<ActionModal
|
|
184
|
+
{...defaultProps}
|
|
185
|
+
ctas={[{ label: 'Click Me', onClick, testid: 'cta-button' }]}
|
|
186
|
+
/>,
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
const button = screen.getByTestId('cta-button');
|
|
190
|
+
fireEvent.click(button);
|
|
191
|
+
|
|
192
|
+
await waitFor(() => {
|
|
193
|
+
expect(onClick).toHaveBeenCalled();
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it('should disable the button when disabled prop is true', () => {
|
|
198
|
+
render(
|
|
199
|
+
<ActionModal
|
|
200
|
+
{...defaultProps}
|
|
201
|
+
ctas={[
|
|
202
|
+
{
|
|
203
|
+
label: 'Disabled Button',
|
|
204
|
+
onClick: mockOnClick,
|
|
205
|
+
disabled: true,
|
|
206
|
+
testid: 'disabled-button',
|
|
207
|
+
},
|
|
208
|
+
]}
|
|
209
|
+
/>,
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
const button = screen.getByTestId('disabled-button');
|
|
213
|
+
expect(button).toBeDisabled();
|
|
214
|
+
|
|
215
|
+
fireEvent.click(button);
|
|
216
|
+
expect(mockOnClick).not.toHaveBeenCalled();
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
it('should show spinner when pending prop is true', () => {
|
|
220
|
+
render(
|
|
221
|
+
<ActionModal
|
|
222
|
+
{...defaultProps}
|
|
223
|
+
ctas={[
|
|
224
|
+
{
|
|
225
|
+
label: 'Loading Button',
|
|
226
|
+
onClick: mockOnClick,
|
|
227
|
+
pending: true,
|
|
228
|
+
testid: 'pending-button',
|
|
229
|
+
},
|
|
230
|
+
]}
|
|
231
|
+
/>,
|
|
232
|
+
);
|
|
233
|
+
|
|
234
|
+
expect(screen.getByTestId('pending-button')).toBeInTheDocument();
|
|
235
|
+
expect(screen.getByTestId('pending-button-spinner')).toBeInTheDocument(); // wrapper of spinner has data-testid of {testid}-spinner
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
it('should not render hidden buttons', () => {
|
|
239
|
+
render(
|
|
240
|
+
<ActionModal
|
|
241
|
+
{...defaultProps}
|
|
242
|
+
ctas={[
|
|
243
|
+
{
|
|
244
|
+
label: 'Visible Button',
|
|
245
|
+
onClick: vi.fn(),
|
|
246
|
+
testid: 'visible-button',
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
label: 'Hidden Button',
|
|
250
|
+
onClick: vi.fn(),
|
|
251
|
+
hidden: true,
|
|
252
|
+
testid: 'hidden-button',
|
|
253
|
+
},
|
|
254
|
+
]}
|
|
255
|
+
/>,
|
|
256
|
+
);
|
|
257
|
+
|
|
258
|
+
expect(screen.getByTestId('visible-button')).toBeInTheDocument();
|
|
259
|
+
expect(screen.queryByTestId('hidden-button')).not.toBeInTheDocument();
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
it('should render multiple CTA buttons', () => {
|
|
263
|
+
render(
|
|
264
|
+
<ActionModal
|
|
265
|
+
{...defaultProps}
|
|
266
|
+
ctas={[
|
|
267
|
+
{
|
|
268
|
+
label: 'Primary CTA',
|
|
269
|
+
onClick: vi.fn(),
|
|
270
|
+
testid: 'primary-cta',
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
label: 'Secondary CTA',
|
|
274
|
+
onClick: vi.fn(),
|
|
275
|
+
variant: 'secondary',
|
|
276
|
+
testid: 'secondary-cta',
|
|
277
|
+
},
|
|
278
|
+
]}
|
|
279
|
+
/>,
|
|
280
|
+
);
|
|
281
|
+
|
|
282
|
+
expect(screen.getByTestId('primary-cta')).toBeInTheDocument();
|
|
283
|
+
expect(screen.getByTestId('secondary-cta')).toBeInTheDocument();
|
|
284
|
+
});
|
|
285
|
+
});
|
|
286
|
+
});
|
|
@@ -52,7 +52,7 @@ export const ActionModal = observer(
|
|
|
52
52
|
const chainMismatch = walletChainId !== Number(chainId);
|
|
53
53
|
if (chainMismatch) {
|
|
54
54
|
showSwitchChainModal({
|
|
55
|
-
chainIdToSwitchTo:
|
|
55
|
+
chainIdToSwitchTo: chainId,
|
|
56
56
|
onSuccess,
|
|
57
57
|
});
|
|
58
58
|
} else {
|
|
@@ -84,13 +84,21 @@ export const ActionModal = observer(
|
|
|
84
84
|
{modalLoading || isLoading || isError ? (
|
|
85
85
|
<div
|
|
86
86
|
className={`flex ${spinnerContainerClassname} w-full items-center justify-center`}
|
|
87
|
+
data-testid="error-loading-wrapper"
|
|
87
88
|
>
|
|
88
89
|
{isError && (
|
|
89
|
-
<Text
|
|
90
|
+
<Text
|
|
91
|
+
data-testid="error-loading-text"
|
|
92
|
+
className="text-center font-body text-error100 text-small"
|
|
93
|
+
>
|
|
90
94
|
Error loading modal
|
|
91
95
|
</Text>
|
|
92
96
|
)}
|
|
93
|
-
{isLoading
|
|
97
|
+
{(isLoading || modalLoading) && (
|
|
98
|
+
<div data-testid="spinner">
|
|
99
|
+
<Spinner size="lg" />
|
|
100
|
+
</div>
|
|
101
|
+
)}
|
|
94
102
|
</div>
|
|
95
103
|
) : (
|
|
96
104
|
children
|
|
@@ -118,7 +126,11 @@ export const ActionModal = observer(
|
|
|
118
126
|
data-testid={cta.testid}
|
|
119
127
|
label={
|
|
120
128
|
<div className="flex items-center justify-center gap-2">
|
|
121
|
-
{cta.pending &&
|
|
129
|
+
{cta.pending && (
|
|
130
|
+
<div data-testid={`${cta.testid}-spinner`}>
|
|
131
|
+
<Spinner size="sm" />
|
|
132
|
+
</div>
|
|
133
|
+
)}
|
|
122
134
|
|
|
123
135
|
{cta.label}
|
|
124
136
|
</div>
|
package/src/react/ui/modals/_internal/components/currencyOptionsSelect/__tests__/index.test.tsx
CHANGED
|
@@ -1,151 +1,54 @@
|
|
|
1
1
|
import { observable } from '@legendapp/state';
|
|
2
2
|
import type { UseQueryResult } from '@tanstack/react-query';
|
|
3
3
|
import { render } from '@test';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { TEST_CURRENCIES, TEST_CURRENCY } from '@test/const';
|
|
5
|
+
import { screen } from '@testing-library/react';
|
|
6
|
+
import { zeroAddress } from 'viem';
|
|
7
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
6
8
|
import CurrencyOptionsSelect from '..';
|
|
7
9
|
import type { Currency } from '../../../../../../_internal';
|
|
8
|
-
import
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
10
|
+
import * as hooks from '../../../../../../hooks';
|
|
11
|
+
|
|
12
|
+
const defaultProps = {
|
|
13
|
+
collectionAddress: zeroAddress,
|
|
14
|
+
chainId: 1,
|
|
15
|
+
selectedCurrency$: observable<Currency | null | undefined>(TEST_CURRENCY),
|
|
16
|
+
secondCurrencyAsDefault: false,
|
|
17
|
+
includeNativeCurrency: false,
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
describe('CurrencyOptionsSelect', () => {
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
vi.restoreAllMocks();
|
|
18
23
|
});
|
|
19
24
|
|
|
20
25
|
it('should render loading skeleton when currencies are loading', () => {
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
it('should set first currency as default when currencies load', async () => {
|
|
27
|
-
vi.mocked(useCurrencies).mockReturnValue({
|
|
28
|
-
data: mockCurrencies,
|
|
29
|
-
isLoading: false,
|
|
30
|
-
} as UseQueryResult<Currency[], Error>);
|
|
31
|
-
|
|
32
|
-
const props = createDefaultProps();
|
|
33
|
-
render(<CurrencyOptionsSelect {...props} />);
|
|
34
|
-
|
|
35
|
-
await waitFor(() => {
|
|
36
|
-
const selectedCurrency = props.selectedCurrency$.get();
|
|
37
|
-
expect(selectedCurrency).toBeDefined();
|
|
38
|
-
expect(selectedCurrency?.contractAddress).toBe(
|
|
39
|
-
mockCurrencies[0].contractAddress,
|
|
40
|
-
);
|
|
41
|
-
expect(selectedCurrency?.symbol).toBe(mockCurrencies[0].symbol);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
expect(screen.getByText(mockCurrencies[0].symbol)).toBeInTheDocument();
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('should set second currency as default when secondCurrencyAsDefault is true', async () => {
|
|
48
|
-
vi.mocked(useCurrencies).mockReturnValue({
|
|
49
|
-
data: mockCurrencies,
|
|
50
|
-
isLoading: false,
|
|
51
|
-
} as UseQueryResult<Currency[], Error>);
|
|
52
|
-
|
|
53
|
-
const props = createDefaultProps();
|
|
54
|
-
render(<CurrencyOptionsSelect {...props} secondCurrencyAsDefault={true} />);
|
|
55
|
-
|
|
56
|
-
await waitFor(() => {
|
|
57
|
-
const selectedCurrency = props.selectedCurrency$.get();
|
|
58
|
-
expect(selectedCurrency).toBeDefined();
|
|
59
|
-
expect(selectedCurrency?.contractAddress).toBe(
|
|
60
|
-
mockCurrencies[1].contractAddress,
|
|
61
|
-
);
|
|
62
|
-
expect(selectedCurrency?.symbol).toBe(mockCurrencies[1].symbol);
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
expect(screen.getByText(mockCurrencies[1].symbol)).toBeInTheDocument();
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it('should update selected currency when changed programmatically', async () => {
|
|
69
|
-
vi.mocked(useCurrencies).mockReturnValue({
|
|
70
|
-
data: mockCurrencies,
|
|
71
|
-
isLoading: false,
|
|
26
|
+
const useCurrenciesSpy = vi.spyOn(hooks, 'useCurrencies');
|
|
27
|
+
useCurrenciesSpy.mockReturnValue({
|
|
28
|
+
isLoading: true,
|
|
29
|
+
data: undefined,
|
|
30
|
+
error: null,
|
|
72
31
|
} as UseQueryResult<Currency[], Error>);
|
|
73
32
|
|
|
74
|
-
|
|
75
|
-
render(<CurrencyOptionsSelect {...props} />);
|
|
76
|
-
|
|
77
|
-
// Wait for initial currency to be set
|
|
78
|
-
await waitFor(() => {
|
|
79
|
-
expect(props.selectedCurrency$.get()).toBeDefined();
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
// Programmatically change the selected currency
|
|
83
|
-
props.selectedCurrency$.set(mockCurrencies[1]);
|
|
33
|
+
render(<CurrencyOptionsSelect {...defaultProps} />);
|
|
84
34
|
|
|
85
|
-
|
|
86
|
-
expect(
|
|
87
|
-
|
|
88
|
-
);
|
|
89
|
-
expect(props.selectedCurrency$.get()?.symbol).toBe(
|
|
90
|
-
mockCurrencies[1].symbol,
|
|
91
|
-
);
|
|
35
|
+
const skeleton = document.querySelector('.h-7.w-20.rounded-2xl');
|
|
36
|
+
expect(skeleton).toBeInTheDocument();
|
|
37
|
+
expect(skeleton).toHaveClass('animate-skeleton');
|
|
92
38
|
});
|
|
93
39
|
|
|
94
|
-
it('should
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
// Initial load with currencies
|
|
98
|
-
useCurrenciesMock.mockReturnValue({
|
|
99
|
-
data: mockCurrencies,
|
|
40
|
+
it('should set first currency as default when currencies load', async () => {
|
|
41
|
+
const useCurrenciesSpy = vi.spyOn(hooks, 'useCurrencies');
|
|
42
|
+
useCurrenciesSpy.mockReturnValue({
|
|
100
43
|
isLoading: false,
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
const props = createDefaultProps();
|
|
104
|
-
render(<CurrencyOptionsSelect {...props} />);
|
|
105
|
-
|
|
106
|
-
// Wait for initial currency to be set
|
|
107
|
-
await waitFor(() => {
|
|
108
|
-
expect(props.selectedCurrency$.get()).toBeDefined();
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
// Programmatically set the second currency
|
|
112
|
-
props.selectedCurrency$.set(mockCurrencies[1]);
|
|
113
|
-
|
|
114
|
-
// Verify second currency is selected
|
|
115
|
-
expect(props.selectedCurrency$.get()?.contractAddress).toBe(
|
|
116
|
-
mockCurrencies[1].contractAddress,
|
|
117
|
-
);
|
|
118
|
-
|
|
119
|
-
// Simulate reload by setting loading state
|
|
120
|
-
useCurrenciesMock.mockReturnValue({
|
|
121
|
-
data: undefined,
|
|
122
|
-
isLoading: true,
|
|
44
|
+
data: TEST_CURRENCIES,
|
|
123
45
|
error: null,
|
|
124
|
-
} as
|
|
125
|
-
|
|
126
|
-
// Verify the selected currency remains the same during loading
|
|
127
|
-
expect(props.selectedCurrency$.get()?.contractAddress).toBe(
|
|
128
|
-
mockCurrencies[1].contractAddress,
|
|
129
|
-
);
|
|
130
|
-
expect(props.selectedCurrency$.get()?.symbol).toBe(
|
|
131
|
-
mockCurrencies[1].symbol,
|
|
132
|
-
);
|
|
46
|
+
} as UseQueryResult<Currency[], Error>);
|
|
133
47
|
|
|
134
|
-
|
|
135
|
-
useCurrenciesMock.mockReturnValue({
|
|
136
|
-
data: mockCurrencies,
|
|
137
|
-
isLoading: false,
|
|
138
|
-
error: null,
|
|
139
|
-
} as unknown as UseQueryResult<Currency[], Error>);
|
|
48
|
+
render(<CurrencyOptionsSelect {...defaultProps} />);
|
|
140
49
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
mockCurrencies[1].contractAddress,
|
|
145
|
-
);
|
|
146
|
-
expect(props.selectedCurrency$.get()?.symbol).toBe(
|
|
147
|
-
mockCurrencies[1].symbol,
|
|
148
|
-
);
|
|
149
|
-
});
|
|
50
|
+
const trigger = screen.getByTestId('currency-select-trigger');
|
|
51
|
+
expect(trigger).toBeInTheDocument();
|
|
52
|
+
expect(trigger).toHaveTextContent(TEST_CURRENCY.symbol);
|
|
150
53
|
});
|
|
151
54
|
});
|