From 0a3987efe55c618cae36e51ffd315292d2a31407 Mon Sep 17 00:00:00 2001 From: OKendigelyan Date: Tue, 21 Jan 2025 15:39:43 +0000 Subject: [PATCH] Make @umami/state package platform agnostic (#2329) --- .../restoreLedger/RestoreLedger.tsx | 2 +- .../SendFlow/Beacon/useSignWithBeacon.tsx | 2 +- apps/desktop/src/providers/UmamiTheme.tsx | 21 ++++++++---- .../utils/beacon/useHandleBeaconMessage.tsx | 2 +- .../SendFlow/Beacon/useSignWithBeacon.tsx | 2 +- .../useSignWithWalletConnect.tsx | 2 +- .../beacon/useHandleBeaconMessage.tsx | 2 +- apps/web/src/providers/UmamiTheme.tsx | 30 ++++++++--------- apps/web/src/setupTests.ts | 5 +++ packages/data-polling/package.json | 1 + packages/data-polling/src/setupTests.ts | 2 ++ packages/data-polling/src/testUtils.tsx | 7 ++-- packages/state/package.json | 3 -- packages/state/src/hooks/beacon.ts | 23 +++++++++---- .../src/hooks/useAsyncActionHandler.test.ts | 4 +-- .../state/src/hooks/useAsyncActionHandler.ts | 18 +++-------- packages/state/src/setupTests.ts | 6 ++-- packages/state/src/testUtils.tsx | 13 ++++---- packages/utils/src/index.ts | 1 + .../utils/src/providers/ToastProvider.tsx | 27 ++++++++++++++++ packages/utils/src/providers/index.ts | 1 + pnpm-lock.yaml | 32 ++++++++----------- 22 files changed, 119 insertions(+), 87 deletions(-) create mode 100644 packages/utils/src/providers/ToastProvider.tsx create mode 100644 packages/utils/src/providers/index.ts diff --git a/apps/desktop/src/components/Onboarding/restoreLedger/RestoreLedger.tsx b/apps/desktop/src/components/Onboarding/restoreLedger/RestoreLedger.tsx index d99575e4d2..dff0397cf9 100644 --- a/apps/desktop/src/components/Onboarding/restoreLedger/RestoreLedger.tsx +++ b/apps/desktop/src/components/Onboarding/restoreLedger/RestoreLedger.tsx @@ -66,7 +66,7 @@ export const RestoreLedger = ({ toast({ description: "Account successfully created!", status: "success" }); closeModal(); }, LEDGER_TIMEOUT), - error => { + (error: { name: string; message: any }) => { if (error.name === "PublicKeyRetrievalError") { return { description: "Request rejected. Please unlock your Ledger and open the Tezos app", diff --git a/apps/desktop/src/components/SendFlow/Beacon/useSignWithBeacon.tsx b/apps/desktop/src/components/SendFlow/Beacon/useSignWithBeacon.tsx index 1b822a35c3..c90873f4e5 100644 --- a/apps/desktop/src/components/SendFlow/Beacon/useSignWithBeacon.tsx +++ b/apps/desktop/src/components/SendFlow/Beacon/useSignWithBeacon.tsx @@ -38,7 +38,7 @@ export const useSignWithBeacon = ( return openWith(); }, - error => ({ + (error: { message: any }) => ({ description: `Failed to confirm Beacon operation: ${error.message}`, }) ); diff --git a/apps/desktop/src/providers/UmamiTheme.tsx b/apps/desktop/src/providers/UmamiTheme.tsx index 689845f9ae..5ff2053b51 100644 --- a/apps/desktop/src/providers/UmamiTheme.tsx +++ b/apps/desktop/src/providers/UmamiTheme.tsx @@ -1,10 +1,17 @@ -import { ChakraProvider, ColorModeScript } from "@chakra-ui/react"; +import { ChakraProvider, ColorModeScript, useToast } from "@chakra-ui/react"; +import { ToastProvider } from "@umami/utils"; import theme from "../style/theme"; -export const UmamiTheme = (props: any) => ( - - - {props.children} - -); +export const UmamiTheme = (props: any) => { + const toast = useToast(); + + return ( + + + + {props.children} + + + ); +}; diff --git a/apps/desktop/src/utils/beacon/useHandleBeaconMessage.tsx b/apps/desktop/src/utils/beacon/useHandleBeaconMessage.tsx index 510c027efe..6fff403496 100644 --- a/apps/desktop/src/utils/beacon/useHandleBeaconMessage.tsx +++ b/apps/desktop/src/utils/beacon/useHandleBeaconMessage.tsx @@ -139,7 +139,7 @@ export const useHandleBeaconMessage = () => { return openWith(modal, { onClose }); }, - error => ({ + (error: { message: any }) => ({ description: `Error while processing Beacon request: ${error.message}`, }) ); diff --git a/apps/web/src/components/SendFlow/Beacon/useSignWithBeacon.tsx b/apps/web/src/components/SendFlow/Beacon/useSignWithBeacon.tsx index 80ca2bf2ab..a855913cfb 100644 --- a/apps/web/src/components/SendFlow/Beacon/useSignWithBeacon.tsx +++ b/apps/web/src/components/SendFlow/Beacon/useSignWithBeacon.tsx @@ -34,7 +34,7 @@ export const useSignWithBeacon = ({ return openWith(); }, - error => ({ + (error: { message: any }) => ({ description: `Failed to confirm Beacon operation: ${error.message}`, }) ); diff --git a/apps/web/src/components/SendFlow/WalletConnect/useSignWithWalletConnect.tsx b/apps/web/src/components/SendFlow/WalletConnect/useSignWithWalletConnect.tsx index 71ce454142..1d6f55027a 100644 --- a/apps/web/src/components/SendFlow/WalletConnect/useSignWithWalletConnect.tsx +++ b/apps/web/src/components/SendFlow/WalletConnect/useSignWithWalletConnect.tsx @@ -39,7 +39,7 @@ export const useSignWithWalletConnect = ({ await walletKit.respondSessionRequest({ topic: requestId.topic, response }); return openWith(); }, - error => ({ + (error: { message: any }) => ({ description: `Failed to confirm WalletConnect operation: ${error.message}`, }) ); diff --git a/apps/web/src/components/beacon/useHandleBeaconMessage.tsx b/apps/web/src/components/beacon/useHandleBeaconMessage.tsx index 01a0bf5ad0..cde6db8069 100644 --- a/apps/web/src/components/beacon/useHandleBeaconMessage.tsx +++ b/apps/web/src/components/beacon/useHandleBeaconMessage.tsx @@ -165,7 +165,7 @@ export const useHandleBeaconMessage = () => { return openWith(modal, { onClose }); }, - error => ({ + (error: { message: any }) => ({ description: `Error while processing Beacon request: ${error.message}`, }) ); diff --git a/apps/web/src/providers/UmamiTheme.tsx b/apps/web/src/providers/UmamiTheme.tsx index 8c13543b1b..4bbda6bf70 100644 --- a/apps/web/src/providers/UmamiTheme.tsx +++ b/apps/web/src/providers/UmamiTheme.tsx @@ -1,5 +1,6 @@ -import { ChakraProvider, ColorModeScript } from "@chakra-ui/react"; +import { ChakraProvider, ColorModeScript, useToast } from "@chakra-ui/react"; import { Global, css } from "@emotion/react"; +import { ToastProvider } from "@umami/utils"; import { type PropsWithChildren } from "react"; import "focus-visible/dist/focus-visible"; @@ -17,17 +18,16 @@ const GlobalStyles = css` } `; -export const UmamiTheme = ({ children }: PropsWithChildren) => ( - - - - {children} - -); +export const UmamiTheme = ({ children }: PropsWithChildren) => { + const toast = useToast({ render: CustomToast }); + + return ( + + + + + {children} + + + ); +}; diff --git a/apps/web/src/setupTests.ts b/apps/web/src/setupTests.ts index 3d9b9aced9..e148fecdec 100644 --- a/apps/web/src/setupTests.ts +++ b/apps/web/src/setupTests.ts @@ -69,6 +69,11 @@ jest.doMock("@chakra-ui/react", () => ({ useColorMode: () => ({ colorMode: "light", toggleColorMode: jest.fn() }), })); +jest.mock("@umami/utils", () => ({ + ...jest.requireActual("@umami/utils"), + useCustomToast: () => mockToast, +})); + jest.mock("./utils/persistor", () => ({ pause: jest.fn(), })); diff --git a/packages/data-polling/package.json b/packages/data-polling/package.json index 16a145e6b4..753bf1617e 100644 --- a/packages/data-polling/package.json +++ b/packages/data-polling/package.json @@ -73,6 +73,7 @@ "@umami/state": "workspace:^", "@umami/tezos": "workspace:^", "@umami/tzkt": "workspace:^", + "@umami/test-utils": "workspace:^", "date-fns": "^4.1.0", "framer-motion": "^11.15.0", "lodash": "^4.17.21", diff --git a/packages/data-polling/src/setupTests.ts b/packages/data-polling/src/setupTests.ts index d1a0735950..95b3b29202 100644 --- a/packages/data-polling/src/setupTests.ts +++ b/packages/data-polling/src/setupTests.ts @@ -2,12 +2,14 @@ import { webcrypto } from "crypto"; import { TextDecoder, TextEncoder } from "util"; import { mockToast } from "@umami/state"; +import { mockLocalStorage } from "@umami/test-utils"; beforeEach(() => { Object.defineProperties(global, { crypto: { value: webcrypto, writable: true }, TextDecoder: { value: TextDecoder, writable: true }, TextEncoder: { value: TextEncoder, writable: true }, + localStorage: { value: mockLocalStorage(), writable: true }, }); }); diff --git a/packages/data-polling/src/testUtils.tsx b/packages/data-polling/src/testUtils.tsx index ed7c60cb6b..0a4e22d70c 100644 --- a/packages/data-polling/src/testUtils.tsx +++ b/packages/data-polling/src/testUtils.tsx @@ -1,9 +1,8 @@ +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import * as testLib from "@testing-library/react"; +import { type UmamiStore, makeStore } from "@umami/state"; +import { type PropsWithChildren, act } from "react"; import { Provider } from "react-redux"; -import { makeStore, UmamiStore } from "@umami/state"; -import { PropsWithChildren, act } from "react"; - -import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; const customRenderHook = < Result, diff --git a/packages/state/package.json b/packages/state/package.json index 96edb19ef2..15cf98eb6f 100644 --- a/packages/state/package.json +++ b/packages/state/package.json @@ -67,9 +67,6 @@ }, "dependencies": { "@airgap/beacon-wallet": "^4.3.1", - "@chakra-ui/react": "^2.8.2", - "@emotion/react": "^11.14.0", - "@emotion/styled": "^11.14.0", "@reduxjs/toolkit": "^2.5.0", "@reown/walletkit": "^1.0.1", "@tanstack/react-query": "^5.62.11", diff --git a/packages/state/src/hooks/beacon.ts b/packages/state/src/hooks/beacon.ts index 1eb141a6b1..6b4229ee1b 100644 --- a/packages/state/src/hooks/beacon.ts +++ b/packages/state/src/hooks/beacon.ts @@ -4,9 +4,9 @@ import { type NetworkType, Serializer, } from "@airgap/beacon-wallet"; -import { useToast } from "@chakra-ui/react"; import { useQuery } from "@tanstack/react-query"; import { type RawPkh } from "@umami/tezos"; +import { useCustomToast } from "@umami/utils"; import { uniq } from "lodash"; import { useDispatch } from "react-redux"; @@ -102,7 +102,7 @@ export const useRemoveBeaconPeersByAccounts = () => { export const useAddPeer = () => { const { refresh } = useBeaconPeers(); - const toast = useToast(); + const toast = useCustomToast(); return (payload: string) => new Serializer() @@ -111,11 +111,20 @@ export const useAddPeer = () => { .then(peer => WalletClient.addPeer(peer as ExtendedPeerInfo)) .then(() => refresh()) .catch(e => { - toast({ - description: - "Beacon sync code in the clipboard is invalid. Please copy a beacon sync code from the dApp", - status: "error", - }); + const description = + "Beacon sync code in the clipboard is invalid. Please copy a beacon sync code from the dApp"; + const type = "error"; + + toast.show + ? toast.show({ + type, + text1: description, + }) + : toast({ + description, + status: type, + }); + console.error(e); }); }; diff --git a/packages/state/src/hooks/useAsyncActionHandler.test.ts b/packages/state/src/hooks/useAsyncActionHandler.test.ts index ee7038b37e..e712eccc36 100644 --- a/packages/state/src/hooks/useAsyncActionHandler.test.ts +++ b/packages/state/src/hooks/useAsyncActionHandler.test.ts @@ -162,7 +162,7 @@ describe("useAsyncActionHandler", () => { view.result.current.handleAsyncActionUnsafe(() => Promise.reject(new Error("test error"))) ) ).rejects.toThrow("test error"); - expect(mockToast).toHaveBeenCalledTimes(2); + expect(mockToast).toHaveBeenCalledTimes(1); }); it("Unsafe propagates the error and shows the toast once on first handling", async () => { @@ -181,7 +181,7 @@ describe("useAsyncActionHandler", () => { status: "error", isClosable: true, }); - expect(mockToast).toHaveBeenCalledTimes(2); + expect(mockToast).toHaveBeenCalledTimes(1); }); it("Unsafe propagates the error and shows no toast on second handling", async () => { diff --git a/packages/state/src/hooks/useAsyncActionHandler.ts b/packages/state/src/hooks/useAsyncActionHandler.ts index 7b22e9fe02..436ddcf238 100644 --- a/packages/state/src/hooks/useAsyncActionHandler.ts +++ b/packages/state/src/hooks/useAsyncActionHandler.ts @@ -1,10 +1,8 @@ -import { type UseToastOptions, useToast } from "@chakra-ui/react"; -import { getErrorContext } from "@umami/utils"; +import { type ToastOptions, getErrorContext, useCustomToast } from "@umami/utils"; import { useCallback, useRef, useState } from "react"; import { useAppDispatch } from "./useAppDispatch"; import { errorsActions } from "../slices"; -import { mockToast } from "../testUtils"; /** * Hook for gracefully handling async actions. @@ -22,13 +20,13 @@ import { mockToast } from "../testUtils"; export const useAsyncActionHandler = () => { const [isLoading, setIsLoading] = useState(false); const isLoadingRef = useRef(isLoading); - const toast = useToast(); + const toast = useCustomToast(); const dispatch = useAppDispatch(); const handleAsyncActionUnsafe = useCallback( async ( fn: () => Promise, - toastOptions?: UseToastOptions | ((error: any) => UseToastOptions) + toastOptions?: ToastOptions | ((error: any) => ToastOptions) ): Promise => { if (isLoadingRef.current) { return; @@ -53,14 +51,6 @@ export const useAsyncActionHandler = () => { ...(typeof toastOptions === "function" ? toastOptions(error) : toastOptions), }); - // TODO: fix this dirty hack - mockToast({ - description: errorContext.description, - status: "error", - isClosable: true, - ...(typeof toastOptions === "function" ? toastOptions(error) : toastOptions), - }); - dispatch(errorsActions.add(errorContext)); } throw error; @@ -76,7 +66,7 @@ export const useAsyncActionHandler = () => { const handleAsyncAction = useCallback( async ( fn: () => Promise, - toastOptions?: UseToastOptions | ((error: any) => UseToastOptions) + toastOptions?: ToastOptions | ((error: any) => ToastOptions) ): Promise => handleAsyncActionUnsafe(fn, toastOptions).catch(() => {}), [handleAsyncActionUnsafe] ); diff --git a/packages/state/src/setupTests.ts b/packages/state/src/setupTests.ts index 9dfb03ae87..19ef3f9e9c 100644 --- a/packages/state/src/setupTests.ts +++ b/packages/state/src/setupTests.ts @@ -12,9 +12,9 @@ Object.defineProperties(global, { fetch: { value: jest.fn(), writable: true }, }); -jest.mock("@chakra-ui/react", () => ({ - ...jest.requireActual("@chakra-ui/react"), - useToast: () => mockToast, +jest.mock("@umami/utils", () => ({ + ...jest.requireActual("@umami/utils"), + useCustomToast: () => mockToast, })); jest.mock("./beacon/WalletClient", () => ({ diff --git a/packages/state/src/testUtils.tsx b/packages/state/src/testUtils.tsx index 63d63df0b6..d7ec7306c9 100644 --- a/packages/state/src/testUtils.tsx +++ b/packages/state/src/testUtils.tsx @@ -1,9 +1,13 @@ +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import * as testLib from "@testing-library/react"; import { type Account } from "@umami/core"; import { type Multisig } from "@umami/multisig"; +import { type RawPkh } from "@umami/tezos"; +import { type PropsWithChildren, act } from "react"; +import { Provider } from "react-redux"; import { accountsActions, multisigsActions } from "./slices"; -import { makeStore, UmamiStore } from "./store"; -import * as testLib from "@testing-library/react"; +import { type UmamiStore, makeStore } from "./store"; export const addTestAccount = (store: UmamiStore, account: Account | Multisig) => { if (!("type" in account) || account.type === "multisig") { @@ -18,11 +22,6 @@ export const addTestAccounts = (store: UmamiStore, accounts: (Account | Multisig accounts.forEach(account => addTestAccount(store, account)); }; -import { PropsWithChildren, act } from "react"; -import { Provider } from "react-redux"; -import { RawPkh } from "@umami/tezos"; -import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; - const customRenderHook = < Result, Props, diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 38cf1d1381..85ec6c1541 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -1 +1,2 @@ export * from "./ErrorContext"; +export * from "./providers"; diff --git a/packages/utils/src/providers/ToastProvider.tsx b/packages/utils/src/providers/ToastProvider.tsx new file mode 100644 index 0000000000..52e183cbf9 --- /dev/null +++ b/packages/utils/src/providers/ToastProvider.tsx @@ -0,0 +1,27 @@ +import { type PropsWithChildren, createContext, useContext } from "react"; + +// TODO: fix this type when we have a better toast implementation +export type ToastOptions = any; + +export type Toast = { + show?: (options: ToastOptions) => void; + [key: string]: any; +} & ((options: ToastOptions) => void); + +type ToastContextType = { + toast: Toast; +}; + +const ToastContext = createContext(undefined); + +export const useCustomToast = () => { + const toastContext = useContext(ToastContext); + if (!toastContext) { + throw new Error("useCustomToast must be used within a ToastProvider"); + } + return toastContext.toast; +}; + +export const ToastProvider = ({ children, toast }: PropsWithChildren<{ toast: Toast }>) => ( + {children} +); diff --git a/packages/utils/src/providers/index.ts b/packages/utils/src/providers/index.ts new file mode 100644 index 0000000000..bb60e0f4f6 --- /dev/null +++ b/packages/utils/src/providers/index.ts @@ -0,0 +1 @@ +export * from "./ToastProvider"; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f2779c2097..4609e69382 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -754,7 +754,7 @@ importers: version: 0.75.4(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0)) '@react-native/eslint-config': specifier: 0.76.5 - version: 0.76.5(eslint@8.57.0)(jest@29.7.0(@types/node@22.10.3)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.7.36(@swc/helpers@0.5.13))(@types/node@22.10.3)(typescript@5.7.2)))(prettier@3.4.2)(typescript@5.7.2) + version: 0.76.5(eslint@8.57.0)(jest@29.7.0(babel-plugin-macros@3.1.0))(prettier@3.4.2)(typescript@5.7.2) '@react-native/gradle-plugin': specifier: ^0.75.4 version: 0.75.4 @@ -769,7 +769,7 @@ importers: version: 5.4.3(react-native@0.75.4(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(encoding@0.1.13)(react@18.3.1)(typescript@5.7.2))(react-test-renderer@18.3.1(react@18.3.1))(react@18.3.1) '@testing-library/react-native': specifier: ^12.9.0 - version: 12.9.0(jest@29.7.0(@types/node@22.10.3)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.7.36(@swc/helpers@0.5.13))(@types/node@22.10.3)(typescript@5.7.2)))(react-native@0.75.4(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(encoding@0.1.13)(react@18.3.1)(typescript@5.7.2))(react-test-renderer@18.3.1(react@18.3.1))(react@18.3.1) + version: 12.9.0(jest@29.7.0(babel-plugin-macros@3.1.0))(react-native@0.75.4(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(encoding@0.1.13)(react@18.3.1)(typescript@5.7.2))(react-test-renderer@18.3.1(react@18.3.1))(react@18.3.1) '@types/react': specifier: ^18.3.12 version: 18.3.12 @@ -1112,7 +1112,7 @@ importers: version: 2.5.2 jest-transformer-svg: specifier: ^2.0.2 - version: 2.0.2(jest@29.7.0(@types/node@22.10.3)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.7.36(@swc/helpers@0.5.13))(@types/node@22.10.3)(typescript@5.7.2)))(react@18.3.1) + version: 2.0.2(jest@29.7.0(@types/node@22.10.3)(babel-plugin-macros@3.1.0))(react@18.3.1) madge: specifier: ^8.0.0 version: 8.0.0(typescript@5.7.2) @@ -1470,6 +1470,9 @@ importers: '@umami/state': specifier: workspace:^ version: link:../state + '@umami/test-utils': + specifier: workspace:^ + version: link:../test-utils '@umami/tezos': specifier: workspace:^ version: link:../tezos @@ -1596,7 +1599,7 @@ importers: version: 2.31.0(@typescript-eslint/parser@8.19.0(eslint@8.57.0)(typescript@5.7.2))(eslint-import-resolver-typescript@3.7.0)(eslint@8.57.0) eslint-plugin-jest: specifier: ^28.10.0 - version: 28.10.0(@typescript-eslint/eslint-plugin@8.19.0(@typescript-eslint/parser@8.19.0(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0)(jest@29.7.0(@types/node@22.10.3)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.7.36(@swc/helpers@0.5.13))(@types/node@22.10.3)(typescript@5.7.2)))(typescript@5.7.2) + version: 28.10.0(@typescript-eslint/eslint-plugin@8.19.0(@typescript-eslint/parser@8.19.0(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0)(jest@29.7.0(babel-plugin-macros@3.1.0))(typescript@5.7.2) eslint-plugin-jest-dom: specifier: ^5.5.0 version: 5.5.0(@testing-library/dom@10.4.0)(eslint@8.57.0) @@ -1785,15 +1788,6 @@ importers: '@airgap/beacon-wallet': specifier: ^4.3.1 version: 4.3.1 - '@chakra-ui/react': - specifier: ^2.8.2 - version: 2.8.2(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(framer-motion@11.15.0(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@emotion/react': - specifier: ^11.14.0 - version: 11.14.0(@types/react@18.3.12)(react@18.3.1) - '@emotion/styled': - specifier: ^11.14.0 - version: 11.14.0(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1) '@reduxjs/toolkit': specifier: ^2.5.0 version: 2.5.0(react-redux@9.2.0(@types/react@18.3.12)(react@18.3.1)(redux@5.0.1))(react@18.3.1) @@ -16658,7 +16652,7 @@ snapshots: - supports-color - utf-8-validate - '@react-native/eslint-config@0.76.5(eslint@8.57.0)(jest@29.7.0(@types/node@22.10.3)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.7.36(@swc/helpers@0.5.13))(@types/node@22.10.3)(typescript@5.7.2)))(prettier@3.4.2)(typescript@5.7.2)': + '@react-native/eslint-config@0.76.5(eslint@8.57.0)(jest@29.7.0(babel-plugin-macros@3.1.0))(prettier@3.4.2)(typescript@5.7.2)': dependencies: '@babel/core': 7.26.0 '@babel/eslint-parser': 7.25.8(@babel/core@7.26.0)(eslint@8.57.0) @@ -16669,7 +16663,7 @@ snapshots: eslint-config-prettier: 8.10.0(eslint@8.57.0) eslint-plugin-eslint-comments: 3.2.0(eslint@8.57.0) eslint-plugin-ft-flow: 2.0.3(@babel/eslint-parser@7.25.8(@babel/core@7.26.0)(eslint@8.57.0))(eslint@8.57.0) - eslint-plugin-jest: 27.9.0(@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0)(jest@29.7.0(@types/node@22.10.3)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.7.36(@swc/helpers@0.5.13))(@types/node@22.10.3)(typescript@5.7.2)))(typescript@5.7.2) + eslint-plugin-jest: 27.9.0(@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0)(jest@29.7.0(babel-plugin-macros@3.1.0))(typescript@5.7.2) eslint-plugin-react: 7.37.2(eslint@8.57.0) eslint-plugin-react-hooks: 4.6.2(eslint@8.57.0) eslint-plugin-react-native: 4.1.0(eslint@8.57.0) @@ -18501,7 +18495,7 @@ snapshots: react-test-renderer: 18.3.1(react@18.3.1) redent: 3.0.0 - '@testing-library/react-native@12.9.0(jest@29.7.0(@types/node@22.10.3)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.7.36(@swc/helpers@0.5.13))(@types/node@22.10.3)(typescript@5.7.2)))(react-native@0.75.4(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(encoding@0.1.13)(react@18.3.1)(typescript@5.7.2))(react-test-renderer@18.3.1(react@18.3.1))(react@18.3.1)': + '@testing-library/react-native@12.9.0(jest@29.7.0(babel-plugin-macros@3.1.0))(react-native@0.75.4(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(encoding@0.1.13)(react@18.3.1)(typescript@5.7.2))(react-test-renderer@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: jest-matcher-utils: 29.7.0 pretty-format: 29.7.0 @@ -21797,7 +21791,7 @@ snapshots: optionalDependencies: '@testing-library/dom': 10.4.0 - eslint-plugin-jest@27.9.0(@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0)(jest@29.7.0(@types/node@22.10.3)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.7.36(@swc/helpers@0.5.13))(@types/node@22.10.3)(typescript@5.7.2)))(typescript@5.7.2): + eslint-plugin-jest@27.9.0(@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0)(jest@29.7.0(babel-plugin-macros@3.1.0))(typescript@5.7.2): dependencies: '@typescript-eslint/utils': 7.18.0(eslint@8.57.0)(typescript@5.7.2) eslint: 8.57.0 @@ -21808,7 +21802,7 @@ snapshots: - supports-color - typescript - eslint-plugin-jest@28.10.0(@typescript-eslint/eslint-plugin@8.19.0(@typescript-eslint/parser@8.19.0(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0)(jest@29.7.0(@types/node@22.10.3)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.7.36(@swc/helpers@0.5.13))(@types/node@22.10.3)(typescript@5.7.2)))(typescript@5.7.2): + eslint-plugin-jest@28.10.0(@typescript-eslint/eslint-plugin@8.19.0(@typescript-eslint/parser@8.19.0(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0)(jest@29.7.0(babel-plugin-macros@3.1.0))(typescript@5.7.2): dependencies: '@typescript-eslint/utils': 7.18.0(eslint@8.57.0)(typescript@5.7.2) eslint: 8.57.0 @@ -23469,7 +23463,7 @@ snapshots: transitivePeerDependencies: - supports-color - jest-transformer-svg@2.0.2(jest@29.7.0(@types/node@22.10.3)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.7.36(@swc/helpers@0.5.13))(@types/node@22.10.3)(typescript@5.7.2)))(react@18.3.1): + jest-transformer-svg@2.0.2(jest@29.7.0(@types/node@22.10.3)(babel-plugin-macros@3.1.0))(react@18.3.1): dependencies: jest: 29.7.0(@types/node@22.10.3)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.7.36(@swc/helpers@0.5.13))(@types/node@22.10.3)(typescript@5.7.2)) react: 18.3.1