thirdweb 5.103.0 → 5.103.1
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/dist/cjs/cli/bin.js +2 -2
- package/dist/cjs/cli/bin.js.map +1 -1
- package/dist/cjs/react/core/hooks/useTransactionDetails.js +1 -1
- package/dist/cjs/react/core/hooks/useTransactionDetails.js.map +1 -1
- package/dist/cjs/react/core/hooks/wallets/useSendToken.js +17 -2
- package/dist/cjs/react/core/hooks/wallets/useSendToken.js.map +1 -1
- package/dist/cjs/react/web/ui/Bridge/CheckoutWidget.js +0 -11
- package/dist/cjs/react/web/ui/Bridge/CheckoutWidget.js.map +1 -1
- package/dist/cjs/react/web/ui/Bridge/TransactionWidget.js +0 -17
- package/dist/cjs/react/web/ui/Bridge/TransactionWidget.js.map +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/cli/bin.js +2 -2
- package/dist/esm/cli/bin.js.map +1 -1
- package/dist/esm/react/core/hooks/useTransactionDetails.js +1 -1
- package/dist/esm/react/core/hooks/useTransactionDetails.js.map +1 -1
- package/dist/esm/react/core/hooks/wallets/useSendToken.js +17 -2
- package/dist/esm/react/core/hooks/wallets/useSendToken.js.map +1 -1
- package/dist/esm/react/web/ui/Bridge/CheckoutWidget.js +0 -11
- package/dist/esm/react/web/ui/Bridge/CheckoutWidget.js.map +1 -1
- package/dist/esm/react/web/ui/Bridge/TransactionWidget.js +0 -17
- package/dist/esm/react/web/ui/Bridge/TransactionWidget.js.map +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/types/react/core/hooks/wallets/useSendToken.d.ts.map +1 -1
- package/dist/types/react/web/ui/Bridge/CheckoutWidget.d.ts +0 -11
- package/dist/types/react/web/ui/Bridge/CheckoutWidget.d.ts.map +1 -1
- package/dist/types/react/web/ui/Bridge/TransactionWidget.d.ts +0 -17
- package/dist/types/react/web/ui/Bridge/TransactionWidget.d.ts.map +1 -1
- package/dist/types/version.d.ts +1 -1
- package/dist/types/wallets/utils/getWalletBalance.d.ts +1 -1
- package/dist/types/wallets/utils/getWalletBalance.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/bridge/Status.test.ts +1 -1
- package/src/cli/bin.ts +2 -2
- package/src/react/core/hooks/useTransactionDetails.ts +1 -1
- package/src/react/core/hooks/wallets/useSendToken.ts +17 -3
- package/src/react/core/machines/paymentMachine.test.ts +0 -172
- package/src/react/web/adapters/adapters.test.ts +0 -8
- package/src/react/web/ui/Bridge/CheckoutWidget.tsx +0 -11
- package/src/react/web/ui/Bridge/TransactionWidget.tsx +0 -17
- package/src/version.ts +1 -1
- package/src/wallets/utils/getWalletBalance.ts +1 -1
- package/src/react/core/hooks/useBridgeError.test.ts +0 -172
- package/src/react/core/hooks/usePaymentMethods.test.ts +0 -336
@@ -3,12 +3,14 @@ import type { ThirdwebClient } from "../../../../client/client.js";
|
|
3
3
|
import { getContract } from "../../../../contract/contract.js";
|
4
4
|
import { resolveAddress } from "../../../../extensions/ens/resolve-address.js";
|
5
5
|
import { transfer } from "../../../../extensions/erc20/write/transfer.js";
|
6
|
+
import { estimateGas } from "../../../../transaction/actions/estimate-gas.js";
|
6
7
|
import { sendTransaction } from "../../../../transaction/actions/send-transaction.js";
|
7
8
|
import { waitForReceipt } from "../../../../transaction/actions/wait-for-tx-receipt.js";
|
8
9
|
import { prepareTransaction } from "../../../../transaction/prepare-transaction.js";
|
9
10
|
import { isAddress } from "../../../../utils/address.js";
|
10
11
|
import { isValidENSName } from "../../../../utils/ens/isValidENSName.js";
|
11
12
|
import { toWei } from "../../../../utils/units.js";
|
13
|
+
import { getWalletBalance } from "../../../../wallets/utils/getWalletBalance.js";
|
12
14
|
import { invalidateWalletBalance } from "../../providers/invalidateWalletBalance.js";
|
13
15
|
import { useActiveWallet } from "./useActiveWallet.js";
|
14
16
|
|
@@ -85,13 +87,24 @@ export function useSendToken(client: ThirdwebClient) {
|
|
85
87
|
to,
|
86
88
|
value: toWei(amount),
|
87
89
|
});
|
90
|
+
const gasEstimate = await estimateGas({
|
91
|
+
transaction: sendNativeTokenTx,
|
92
|
+
account,
|
93
|
+
});
|
94
|
+
const balance = await getWalletBalance({
|
95
|
+
address: account.address,
|
96
|
+
chain: activeChain,
|
97
|
+
client,
|
98
|
+
});
|
99
|
+
if (toWei(amount) + gasEstimate > balance.value) {
|
100
|
+
throw new Error("Insufficient balance for transfer amount and gas");
|
101
|
+
}
|
88
102
|
|
89
|
-
return sendTransaction({
|
103
|
+
return await sendTransaction({
|
90
104
|
transaction: sendNativeTokenTx,
|
91
105
|
account,
|
92
106
|
});
|
93
107
|
}
|
94
|
-
|
95
108
|
// erc20 token transfer
|
96
109
|
else {
|
97
110
|
const contract = getContract({
|
@@ -106,7 +119,7 @@ export function useSendToken(client: ThirdwebClient) {
|
|
106
119
|
to,
|
107
120
|
});
|
108
121
|
|
109
|
-
return sendTransaction({
|
122
|
+
return await sendTransaction({
|
110
123
|
transaction: tx,
|
111
124
|
account,
|
112
125
|
});
|
@@ -121,6 +134,7 @@ export function useSendToken(client: ThirdwebClient) {
|
|
121
134
|
transactionHash: data.transactionHash,
|
122
135
|
client,
|
123
136
|
chain: data.chain,
|
137
|
+
maxBlocksWaitTime: 10_000,
|
124
138
|
});
|
125
139
|
}
|
126
140
|
invalidateWalletBalance(queryClient);
|
@@ -124,114 +124,6 @@ describe("PaymentMachine", () => {
|
|
124
124
|
expect(state.context.adapters).toBe(adapters);
|
125
125
|
});
|
126
126
|
|
127
|
-
it("should transition through happy path with wallet payment method", () => {
|
128
|
-
const { result } = renderHook(() =>
|
129
|
-
usePaymentMachine(adapters, "fund_wallet"),
|
130
|
-
);
|
131
|
-
|
132
|
-
// Confirm destination
|
133
|
-
act(() => {
|
134
|
-
const [, send] = result.current;
|
135
|
-
send({
|
136
|
-
type: "DESTINATION_CONFIRMED",
|
137
|
-
destinationToken: testTokenForPayment,
|
138
|
-
destinationAmount: "100",
|
139
|
-
receiverAddress: "0xa3841994009B4fEabb01ebcC62062F9E56F701CD",
|
140
|
-
});
|
141
|
-
});
|
142
|
-
|
143
|
-
let [state] = result.current;
|
144
|
-
expect(state.value).toBe("methodSelection");
|
145
|
-
expect(state.context.destinationToken).toEqual(testTokenForPayment);
|
146
|
-
expect(state.context.destinationAmount).toBe("100");
|
147
|
-
expect(state.context.receiverAddress).toBe(
|
148
|
-
"0xa3841994009B4fEabb01ebcC62062F9E56F701CD",
|
149
|
-
);
|
150
|
-
|
151
|
-
// Select wallet payment method
|
152
|
-
const walletPaymentMethod: PaymentMethod = {
|
153
|
-
type: "wallet",
|
154
|
-
originToken: testUSDCToken,
|
155
|
-
payerWallet: TEST_IN_APP_WALLET_A,
|
156
|
-
balance: 1000000000000000000n,
|
157
|
-
};
|
158
|
-
|
159
|
-
act(() => {
|
160
|
-
const [, send] = result.current;
|
161
|
-
send({
|
162
|
-
type: "PAYMENT_METHOD_SELECTED",
|
163
|
-
paymentMethod: walletPaymentMethod,
|
164
|
-
});
|
165
|
-
});
|
166
|
-
|
167
|
-
[state] = result.current;
|
168
|
-
expect(state.value).toBe("quote");
|
169
|
-
expect(state.context.selectedPaymentMethod).toEqual(walletPaymentMethod);
|
170
|
-
|
171
|
-
// Receive quote
|
172
|
-
act(() => {
|
173
|
-
const [, send] = result.current;
|
174
|
-
send({
|
175
|
-
type: "QUOTE_RECEIVED",
|
176
|
-
preparedQuote: mockBuyQuote,
|
177
|
-
});
|
178
|
-
});
|
179
|
-
|
180
|
-
[state] = result.current;
|
181
|
-
expect(state.value).toBe("preview");
|
182
|
-
expect(state.context.preparedQuote).toBe(mockBuyQuote);
|
183
|
-
|
184
|
-
// Confirm route
|
185
|
-
act(() => {
|
186
|
-
const [, send] = result.current;
|
187
|
-
send({
|
188
|
-
type: "ROUTE_CONFIRMED",
|
189
|
-
});
|
190
|
-
});
|
191
|
-
|
192
|
-
[state] = result.current;
|
193
|
-
expect(state.value).toBe("execute");
|
194
|
-
expect(state.context.selectedPaymentMethod).toBe(walletPaymentMethod);
|
195
|
-
|
196
|
-
// Complete execution
|
197
|
-
act(() => {
|
198
|
-
const [, send] = result.current;
|
199
|
-
send({
|
200
|
-
type: "EXECUTION_COMPLETE",
|
201
|
-
completedStatuses: [
|
202
|
-
{
|
203
|
-
type: "buy",
|
204
|
-
status: "COMPLETED",
|
205
|
-
paymentId: "test-payment-id",
|
206
|
-
originAmount: 1000000000000000000n,
|
207
|
-
destinationAmount: 100000000n,
|
208
|
-
originChainId: 1,
|
209
|
-
destinationChainId: 137,
|
210
|
-
originTokenAddress: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
211
|
-
destinationTokenAddress:
|
212
|
-
"0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
|
213
|
-
originToken: testETHToken,
|
214
|
-
destinationToken: testUSDCToken,
|
215
|
-
sender: "0xa3841994009B4fEabb01ebcC62062F9E56F701CD",
|
216
|
-
receiver: "0xa3841994009B4fEabb01ebcC62062F9E56F701CD",
|
217
|
-
transactions: [
|
218
|
-
{
|
219
|
-
chainId: 1,
|
220
|
-
transactionHash: "0xtest123",
|
221
|
-
},
|
222
|
-
],
|
223
|
-
},
|
224
|
-
],
|
225
|
-
});
|
226
|
-
});
|
227
|
-
|
228
|
-
[state] = result.current;
|
229
|
-
expect(state.value).toBe("success");
|
230
|
-
expect(state.context.completedStatuses).toBeDefined();
|
231
|
-
expect(state.context.completedStatuses).toHaveLength(1);
|
232
|
-
expect(state.context.completedStatuses?.[0]?.status).toBe("COMPLETED");
|
233
|
-
});
|
234
|
-
|
235
127
|
it("should handle errors and allow retry", () => {
|
236
128
|
const { result } = renderHook(() =>
|
237
129
|
usePaymentMachine(adapters, "fund_wallet"),
|
@@ -517,70 +409,6 @@ describe("PaymentMachine", () => {
|
|
517
409
|
expect(state.value).toBe("init");
|
518
410
|
});
|
519
411
|
|
520
|
-
it("should clear prepared quote when payment method changes", () => {
|
521
|
-
const { result } = renderHook(() =>
|
522
|
-
usePaymentMachine(adapters, "fund_wallet"),
|
523
|
-
);
|
524
|
-
|
525
|
-
// Go to methodSelection
|
526
|
-
act(() => {
|
527
|
-
const [, send] = result.current;
|
528
|
-
send({
|
529
|
-
type: "DESTINATION_CONFIRMED",
|
530
|
-
destinationToken: testTokenForPayment,
|
531
|
-
destinationAmount: "100",
|
532
|
-
receiverAddress: "0xa3841994009B4fEabb01ebcC62062F9E56F701CD",
|
533
|
-
});
|
534
|
-
});
|
535
|
-
|
536
|
-
// Select first payment method and get quote
|
537
|
-
act(() => {
|
538
|
-
const [, send] = result.current;
|
539
|
-
send({
|
540
|
-
type: "PAYMENT_METHOD_SELECTED",
|
541
|
-
paymentMethod: {
|
542
|
-
type: "fiat",
|
543
|
-
currency: "USD",
|
544
|
-
payerWallet: TEST_IN_APP_WALLET_A,
|
545
|
-
onramp: "stripe",
|
546
|
-
},
|
547
|
-
});
|
548
|
-
});
|
549
|
-
|
550
|
-
act(() => {
|
551
|
-
const [, send] = result.current;
|
552
|
-
send({
|
553
|
-
type: "QUOTE_RECEIVED",
|
554
|
-
preparedQuote: mockBuyQuote,
|
555
|
-
});
|
556
|
-
});
|
557
|
-
|
558
|
-
let [state] = result.current;
|
559
|
-
expect(state.context.preparedQuote).toBe(mockBuyQuote);
|
560
|
-
|
561
|
-
// Go back and select different payment method
|
562
|
-
act(() => {
|
563
|
-
const [, send] = result.current;
|
564
|
-
send({ type: "BACK" });
|
565
|
-
});
|
566
|
-
|
567
|
-
act(() => {
|
568
|
-
const [, send] = result.current;
|
569
|
-
send({
|
570
|
-
type: "PAYMENT_METHOD_SELECTED",
|
571
|
-
paymentMethod: {
|
572
|
-
type: "wallet",
|
573
|
-
payerWallet: TEST_IN_APP_WALLET_A,
|
574
|
-
originToken: testUSDCToken,
|
575
|
-
balance: 1000000000000000000n,
|
576
|
-
},
|
577
|
-
});
|
578
|
-
});
|
579
|
-
|
580
|
-
[state] = result.current;
|
581
|
-
expect(state.context.preparedQuote).toBeUndefined(); // Should be cleared
|
582
|
-
});
|
583
|
-
|
584
412
|
it("should handle post-buy-transaction state flow", () => {
|
585
413
|
const { result } = renderHook(() =>
|
586
414
|
usePaymentMachine(adapters, "fund_wallet"),
|
@@ -27,12 +27,4 @@ describe("WebWindowAdapter", () => {
|
|
27
27
|
"noopener,noreferrer",
|
28
28
|
);
|
29
29
|
});
|
30
|
-
|
31
|
-
it("should throw error when popup is blocked", async () => {
|
32
|
-
mockOpen.mockReturnValue(null);
|
33
|
-
|
34
|
-
await expect(windowAdapter.open("https://example.com")).rejects.toThrow(
|
35
|
-
"Failed to open URL - popup may be blocked",
|
36
|
-
);
|
37
|
-
});
|
38
30
|
});
|
@@ -198,17 +198,6 @@ type UIOptionsResult =
|
|
198
198
|
* />
|
199
199
|
* ```
|
200
200
|
*
|
201
|
-
* ### Enable/Disable payment methods
|
202
|
-
*
|
203
|
-
* You can use `disableOnramps` to prevent the use of onramps in the widget.
|
204
|
-
*
|
205
|
-
* ```tsx
|
206
|
-
* <CheckoutWidget
|
207
|
-
* client={client}
|
208
|
-
* disableOnramps
|
209
|
-
* />
|
210
|
-
* ```
|
211
|
-
*
|
212
201
|
* ### Customize the UI
|
213
202
|
*
|
214
203
|
* You can customize the UI of the `CheckoutWidget` component by passing a custom theme object to the `theme` prop.
|
@@ -201,23 +201,6 @@ type UIOptionsResult =
|
|
201
201
|
* />
|
202
202
|
* ```
|
203
203
|
*
|
204
|
-
* ### Enable/Disable payment methods
|
205
|
-
*
|
206
|
-
* You can use `disableOnramps` to prevent the use of onramps in the widget.
|
207
|
-
*
|
208
|
-
* ```tsx
|
209
|
-
* <TransactionWidget
|
210
|
-
* client={client}
|
211
|
-
* transaction={prepareTransaction({
|
212
|
-
* to: "0x...",
|
213
|
-
* chain: ethereum,
|
214
|
-
* client: client,
|
215
|
-
* value: toUnits("0.001", 18),
|
216
|
-
* })}
|
217
|
-
* disableOnramps
|
218
|
-
* />
|
219
|
-
* ```
|
220
|
-
*
|
221
204
|
* ### Customize the UI
|
222
205
|
*
|
223
206
|
* You can customize the UI of the `TransactionWidget` component by passing a custom theme object to the `theme` prop.
|
package/src/version.ts
CHANGED
@@ -1 +1 @@
|
|
1
|
-
export const version = "5.103.
|
1
|
+
export const version = "5.103.1";
|
@@ -41,7 +41,7 @@ export type GetWalletBalanceResult = GetBalanceResult;
|
|
41
41
|
*/
|
42
42
|
export async function getWalletBalance(
|
43
43
|
options: GetWalletBalanceOptions,
|
44
|
-
): Promise<
|
44
|
+
): Promise<GetBalanceResult> {
|
45
45
|
const { address, client, chain, tokenAddress } = options;
|
46
46
|
// erc20 case
|
47
47
|
if (tokenAddress) {
|
@@ -1,172 +0,0 @@
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
2
|
-
import { ApiError } from "../../../bridge/types/Errors.js";
|
3
|
-
import { useBridgeError } from "./useBridgeError.js";
|
4
|
-
|
5
|
-
describe("useBridgeError", () => {
|
6
|
-
it("should handle null error", () => {
|
7
|
-
const result = useBridgeError({ error: null });
|
8
|
-
|
9
|
-
expect(result).toEqual({
|
10
|
-
mappedError: null,
|
11
|
-
isRetryable: false,
|
12
|
-
userMessage: "",
|
13
|
-
errorCode: null,
|
14
|
-
statusCode: null,
|
15
|
-
isClientError: false,
|
16
|
-
isServerError: false,
|
17
|
-
});
|
18
|
-
});
|
19
|
-
|
20
|
-
it("should handle undefined error", () => {
|
21
|
-
const result = useBridgeError({ error: undefined });
|
22
|
-
|
23
|
-
expect(result).toEqual({
|
24
|
-
mappedError: null,
|
25
|
-
isRetryable: false,
|
26
|
-
userMessage: "",
|
27
|
-
errorCode: null,
|
28
|
-
statusCode: null,
|
29
|
-
isClientError: false,
|
30
|
-
isServerError: false,
|
31
|
-
});
|
32
|
-
});
|
33
|
-
|
34
|
-
it("should process ApiError correctly", () => {
|
35
|
-
const apiError = new ApiError({
|
36
|
-
code: "INVALID_INPUT",
|
37
|
-
message: "Invalid parameters provided",
|
38
|
-
statusCode: 400,
|
39
|
-
});
|
40
|
-
|
41
|
-
const result = useBridgeError({ error: apiError });
|
42
|
-
|
43
|
-
expect(result.mappedError).toBeInstanceOf(ApiError);
|
44
|
-
expect(result.errorCode).toBe("INVALID_INPUT");
|
45
|
-
expect(result.statusCode).toBe(400);
|
46
|
-
expect(result.isClientError).toBe(true);
|
47
|
-
expect(result.isServerError).toBe(false);
|
48
|
-
expect(result.isRetryable).toBe(false); // INVALID_INPUT is not retryable
|
49
|
-
expect(result.userMessage).toBe(
|
50
|
-
"Invalid input provided. Please check your parameters and try again.",
|
51
|
-
);
|
52
|
-
});
|
53
|
-
|
54
|
-
it("should convert generic Error to ApiError", () => {
|
55
|
-
const genericError = new Error("Network connection failed");
|
56
|
-
|
57
|
-
const result = useBridgeError({ error: genericError });
|
58
|
-
|
59
|
-
expect(result.mappedError).toBeInstanceOf(ApiError);
|
60
|
-
expect(result.errorCode).toBe("UNKNOWN_ERROR");
|
61
|
-
expect(result.statusCode).toBe(500);
|
62
|
-
expect(result.isClientError).toBe(false);
|
63
|
-
expect(result.isServerError).toBe(true);
|
64
|
-
expect(result.isRetryable).toBe(true);
|
65
|
-
expect(result.userMessage).toBe(
|
66
|
-
"An unexpected error occurred. Please try again.",
|
67
|
-
);
|
68
|
-
});
|
69
|
-
|
70
|
-
it("should identify server errors correctly", () => {
|
71
|
-
const serverError = new ApiError({
|
72
|
-
code: "INTERNAL_SERVER_ERROR",
|
73
|
-
message: "Server error",
|
74
|
-
statusCode: 500,
|
75
|
-
});
|
76
|
-
|
77
|
-
const result = useBridgeError({ error: serverError });
|
78
|
-
|
79
|
-
expect(result.statusCode).toBe(500);
|
80
|
-
expect(result.isClientError).toBe(false);
|
81
|
-
expect(result.isServerError).toBe(true);
|
82
|
-
expect(result.isRetryable).toBe(true); // INTERNAL_SERVER_ERROR is retryable
|
83
|
-
expect(result.userMessage).toBe(
|
84
|
-
"A temporary error occurred. Please try again in a moment.",
|
85
|
-
);
|
86
|
-
});
|
87
|
-
|
88
|
-
it("should provide user-friendly messages for known error codes", () => {
|
89
|
-
// Test INVALID_INPUT
|
90
|
-
const invalidInputError = new ApiError({
|
91
|
-
code: "INVALID_INPUT",
|
92
|
-
message: "Technical error message",
|
93
|
-
statusCode: 400,
|
94
|
-
});
|
95
|
-
const invalidInputResult = useBridgeError({ error: invalidInputError });
|
96
|
-
expect(invalidInputResult.userMessage).toBe(
|
97
|
-
"Invalid input provided. Please check your parameters and try again.",
|
98
|
-
);
|
99
|
-
|
100
|
-
// Test INTERNAL_SERVER_ERROR
|
101
|
-
const serverError = new ApiError({
|
102
|
-
code: "INTERNAL_SERVER_ERROR",
|
103
|
-
message: "Technical error message",
|
104
|
-
statusCode: 500,
|
105
|
-
});
|
106
|
-
const serverResult = useBridgeError({ error: serverError });
|
107
|
-
expect(serverResult.userMessage).toBe(
|
108
|
-
"A temporary error occurred. Please try again in a moment.",
|
109
|
-
);
|
110
|
-
});
|
111
|
-
|
112
|
-
it("should use original error message for unknown error codes", () => {
|
113
|
-
const unknownError = new ApiError({
|
114
|
-
code: "UNKNOWN_ERROR",
|
115
|
-
message: "Custom error message",
|
116
|
-
statusCode: 418,
|
117
|
-
});
|
118
|
-
|
119
|
-
const result = useBridgeError({ error: unknownError });
|
120
|
-
|
121
|
-
expect(result.userMessage).toBe(
|
122
|
-
"An unexpected error occurred. Please try again.",
|
123
|
-
);
|
124
|
-
expect(result.errorCode).toBe("UNKNOWN_ERROR");
|
125
|
-
});
|
126
|
-
|
127
|
-
it("should detect client vs server errors correctly", () => {
|
128
|
-
// Client error (4xx)
|
129
|
-
const clientError = new ApiError({
|
130
|
-
code: "INVALID_INPUT",
|
131
|
-
message: "Bad request",
|
132
|
-
statusCode: 400,
|
133
|
-
});
|
134
|
-
|
135
|
-
const clientResult = useBridgeError({ error: clientError });
|
136
|
-
expect(clientResult.isClientError).toBe(true);
|
137
|
-
expect(clientResult.isServerError).toBe(false);
|
138
|
-
|
139
|
-
// Server error (5xx)
|
140
|
-
const serverError = new ApiError({
|
141
|
-
code: "INTERNAL_SERVER_ERROR",
|
142
|
-
message: "Internal error",
|
143
|
-
statusCode: 503,
|
144
|
-
});
|
145
|
-
|
146
|
-
const serverResult = useBridgeError({ error: serverError });
|
147
|
-
expect(serverResult.isClientError).toBe(false);
|
148
|
-
expect(serverResult.isServerError).toBe(true);
|
149
|
-
|
150
|
-
// No status code
|
151
|
-
const noStatusError = new ApiError({
|
152
|
-
code: "UNKNOWN_ERROR",
|
153
|
-
message: "Unknown error",
|
154
|
-
statusCode: 500,
|
155
|
-
});
|
156
|
-
|
157
|
-
const noStatusResult = useBridgeError({ error: noStatusError });
|
158
|
-
expect(noStatusResult.isClientError).toBe(false);
|
159
|
-
expect(noStatusResult.isServerError).toBe(true); // 500 is a server error
|
160
|
-
});
|
161
|
-
|
162
|
-
it("should handle Error without message", () => {
|
163
|
-
const errorWithoutMessage = new Error();
|
164
|
-
|
165
|
-
const result = useBridgeError({ error: errorWithoutMessage });
|
166
|
-
|
167
|
-
expect(result.userMessage).toBe(
|
168
|
-
"An unexpected error occurred. Please try again.",
|
169
|
-
);
|
170
|
-
expect(result.errorCode).toBe("UNKNOWN_ERROR");
|
171
|
-
});
|
172
|
-
});
|