diff --git a/.eslintignore b/.eslintignore
index c2c9d0994..5b1e11ac7 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -1,4 +1,5 @@
node_modules
dist
*.js
-scripts
\ No newline at end of file
+scripts
+vitest.config.ts
\ No newline at end of file
diff --git a/package.json b/package.json
index 905268c6c..a62ffa09e 100644
--- a/package.json
+++ b/package.json
@@ -76,6 +76,11 @@
"@typescript-eslint/parser": "^5.59.7",
"@vercel/routing-utils": "^3.1.0",
"@vitest/coverage-v8": "^2.0.5",
+ "@testing-library/react": "^16.0.0",
+ "@testing-library/dom": "^10.1.0",
+ "@testing-library/react-hooks": "^8.0.1",
+ "happy-dom": "^14.12.0",
+ "react-test-renderer": "^18.3.1",
"buffer": "^5.5.0",
"chalk": "^5.2.0",
"command-line-args": "^5.2.1",
diff --git a/vitest.config.ts b/vitest.config.ts
index 0da549d7b..19ebacfe1 100644
--- a/vitest.config.ts
+++ b/vitest.config.ts
@@ -1,8 +1,8 @@
-///
-import { defineConfig } from 'vite';
+import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
+ environment: 'happy-dom',
watch: false,
},
});
diff --git a/wallets/react/package.json b/wallets/react/package.json
index fd6d30a3f..e4451eda8 100644
--- a/wallets/react/package.json
+++ b/wallets/react/package.json
@@ -6,9 +6,11 @@
"source": "./src/index.ts",
"main": "./dist/index.js",
"exports": {
- ".": "./dist/index.js"
+ ".": {
+ "types": "./dist/index.d.ts",
+ "default": "./dist/index.js"
+ }
},
- "typings": "dist/index.d.ts",
"files": [
"dist",
"src"
@@ -18,7 +20,9 @@
"ts-check": "tsc --declaration --emitDeclarationOnly -p ./tsconfig.json",
"clean": "rimraf dist",
"format": "prettier --write '{.,src}/**/*.{ts,tsx}'",
- "lint": "eslint \"**/*.{ts,tsx}\" --ignore-path ../../.eslintignore"
+ "lint": "eslint \"**/*.{ts,tsx}\" --ignore-path ../../.eslintignore",
+ "test": "vitest",
+ "coverage": "vitest run --coverage"
},
"peerDependencies": {
"@types/react": "^17.0.0 || ^18.0.0",
@@ -30,7 +34,11 @@
"@rango-dev/wallets-shared": "^0.37.1-next.1",
"rango-types": "^0.1.69"
},
+ "devDependencies": {
+ "@types/react": "^18.0.25",
+ "@types/react-dom": "^18.0.25"
+ },
"publishConfig": {
"access": "public"
}
-}
\ No newline at end of file
+}
diff --git a/wallets/react/src/test-utils/env.ts b/wallets/react/src/test-utils/env.ts
new file mode 100644
index 000000000..53c44f8b6
--- /dev/null
+++ b/wallets/react/src/test-utils/env.ts
@@ -0,0 +1,10 @@
+const TEST_ENVIRONMENT_AGENT = 'HappyDOM/0.0.0';
+
+/**
+ * Detecting wether our code is running in a test environment or not.
+ *
+ * Note: This is only useful when HappyDOM or jsdom has been added to test runner.
+ */
+export function isRunningInTestEnvironmentWithDom(): boolean {
+ return navigator.userAgent.includes(TEST_ENVIRONMENT_AGENT);
+}
diff --git a/wallets/react/src/test-utils/fixtures.ts b/wallets/react/src/test-utils/fixtures.ts
new file mode 100644
index 000000000..f1dc90b6d
--- /dev/null
+++ b/wallets/react/src/test-utils/fixtures.ts
@@ -0,0 +1,225 @@
+import type { LegacyProviderInterface } from '@rango-dev/wallets-core/legacy';
+import type { BlockchainMeta, GenericSigner } from 'rango-types';
+import type { EvmTransaction } from 'rango-types/mainApi';
+
+import { DefaultSignerFactory, TransactionType } from 'rango-types';
+
+export const legacyAddress = '0x000000000000000000000000000000000000dead';
+
+export class MockEvmSigner implements GenericSigner {
+ async signMessage(
+ _msg: string,
+ _address: string,
+ _chainId: string | null
+ ): Promise {
+ return '0x';
+ }
+ async signAndSendTx(
+ _tx: EvmTransaction,
+ _address: string,
+ _chainId: string | null
+ ): Promise<{ hash: string; response?: any }> {
+ return {
+ hash: '0x',
+ };
+ }
+}
+
+export const legacyProvider: LegacyProviderInterface = {
+ config: {
+ type: 'legacy-garbage',
+ },
+ async connect({ network }) {
+ // we added a timeout to simulate requesting to extension for connection.
+ return await new Promise((resolve, reject) => {
+ setTimeout(() => {
+ // This is useful for simulating error scenarios.
+ if (network === 'When Airdrop?') {
+ reject(
+ 'please stay tuned we shall announce the detailed information soon.'
+ );
+ } else {
+ resolve([
+ {
+ accounts: [legacyAddress],
+ chainId: network || '',
+ },
+ ]);
+ }
+ // eslint-disable-next-line @typescript-eslint/no-magic-numbers
+ }, 10);
+ });
+ },
+ getInstance() {
+ return {};
+ },
+ async getSigners() {
+ const signers = new DefaultSignerFactory();
+ signers.registerSigner(TransactionType.EVM, new MockEvmSigner());
+ return signers;
+ },
+ getWalletInfo() {
+ return {
+ name: 'legacy garbage wallet',
+ color: '#000',
+ img: 'https://...',
+ installLink: 'https://...',
+ supportedChains: [],
+ };
+ },
+};
+
+export const blockchainsMeta: BlockchainMeta[] = [
+ {
+ name: 'BTC',
+ defaultDecimals: 8,
+ addressPatterns: [
+ '^[13][a-km-zA-HJ-NP-Z1-9]{25,34}$|^(bc1)[0-9A-Za-z]{39,59}$',
+ ],
+ feeAssets: [
+ {
+ blockchain: 'BTC',
+ symbol: 'BTC',
+ address: null,
+ },
+ ],
+ logo: 'https://raw.githubusercontent.com/rango-exchange/assets/main/blockchains/BTC/icon.svg',
+ displayName: 'Bitcoin',
+ shortName: 'BTC',
+ sort: 12,
+ color: '#F7931A',
+ enabled: true,
+ type: TransactionType.TRANSFER,
+ chainId: null,
+ info: null,
+ },
+ {
+ name: 'ETH',
+ defaultDecimals: 18,
+ addressPatterns: ['^(0x)[0-9A-Fa-f]{40}$'],
+ feeAssets: [
+ {
+ blockchain: 'ETH',
+ symbol: 'ETH',
+ address: null,
+ },
+ ],
+ logo: 'https://raw.githubusercontent.com/rango-exchange/assets/main/blockchains/ETH/icon.svg',
+ displayName: 'Ethereum',
+ shortName: 'ETH',
+ sort: 0,
+ color: '#ecf0f1',
+ enabled: true,
+ type: TransactionType.EVM,
+ chainId: '0x1',
+ info: {
+ infoType: 'EvmMetaInfo',
+ chainName: 'Ethereum Mainnet',
+ nativeCurrency: {
+ name: 'ETH',
+ symbol: 'ETH',
+ decimals: 18,
+ },
+ rpcUrls: ['https://rpc.ankr.com/eth'],
+ blockExplorerUrls: ['https://etherscan.io'],
+ addressUrl: 'https://etherscan.io/address/{wallet}',
+ transactionUrl: 'https://etherscan.io/tx/{txHash}',
+ // enableGasV2: true,
+ },
+ },
+ {
+ name: 'SOLANA',
+ defaultDecimals: 9,
+ addressPatterns: ['^[1-9A-HJ-NP-Za-km-z]{32,44}$'],
+ feeAssets: [
+ {
+ blockchain: 'SOLANA',
+ symbol: 'SOL',
+ address: null,
+ },
+ ],
+ logo: 'https://raw.githubusercontent.com/rango-exchange/assets/main/blockchains/SOLANA/icon.svg',
+ displayName: 'Solana',
+ shortName: 'Solana',
+ sort: 20,
+ color: '#708DD2',
+ enabled: true,
+ type: TransactionType.SOLANA,
+ chainId: 'mainnet-beta',
+ info: null,
+ },
+ {
+ name: 'COSMOS',
+ defaultDecimals: 6,
+ addressPatterns: ['^(cosmos1)[0-9a-z]{38}$'],
+ feeAssets: [
+ {
+ blockchain: 'COSMOS',
+ symbol: 'ATOM',
+ address: null,
+ },
+ ],
+ logo: 'https://raw.githubusercontent.com/rango-exchange/assets/main/blockchains/COSMOS/icon.svg',
+ displayName: 'Cosmos',
+ shortName: 'Cosmos',
+ sort: 15,
+ color: '#2E3148',
+ enabled: true,
+ type: TransactionType.COSMOS,
+ chainId: 'cosmoshub-4',
+ info: {
+ infoType: 'CosmosMetaInfo',
+ experimental: false,
+ rpc: 'https://cosmos-rpc.polkachu.com',
+ rest: 'https://lcd-cosmoshub.blockapsis.com',
+ cosmostationLcdUrl: 'https://lcd-cosmoshub.blockapsis.com',
+ cosmostationApiUrl: 'https://cosmos-rpc.polkachu.com',
+ cosmostationDenomTracePath: '/ibc/apps/transfer/v1/denom_traces/',
+ mintScanName: 'cosmos',
+ chainName: 'Cosmos',
+ stakeCurrency: {
+ coinDenom: 'ATOM',
+ coinMinimalDenom: 'uatom',
+ coinDecimals: 6,
+ coinGeckoId: 'cosmos',
+ coinImageUrl: '/tokens/blockchain/cosmos.svg',
+ },
+ bip44: {
+ coinType: 118,
+ },
+ bech32Config: {
+ bech32PrefixAccAddr: 'cosmos',
+ bech32PrefixAccPub: 'cosmospub',
+ bech32PrefixValAddr: 'cosmosvaloper',
+ bech32PrefixValPub: 'cosmosvaloperpub',
+ bech32PrefixConsAddr: 'cosmosvalcons',
+ bech32PrefixConsPub: 'cosmosvalconspub',
+ },
+ currencies: [
+ {
+ coinDenom: 'ATOM',
+ coinMinimalDenom: 'uatom',
+ coinDecimals: 6,
+ coinGeckoId: 'cosmos',
+ coinImageUrl: '/tokens/blockchain/cosmos.svg',
+ },
+ ],
+ feeCurrencies: [
+ {
+ coinDenom: 'ATOM',
+ coinMinimalDenom: 'uatom',
+ coinDecimals: 6,
+ coinGeckoId: 'cosmos',
+ coinImageUrl: '/tokens/blockchain/cosmos.svg',
+ },
+ ],
+ features: ['stargate', 'ibc-transfer'],
+ explorerUrlToTx: 'https://www.mintscan.io/cosmos/txs/{txHash}',
+ gasPriceStep: {
+ low: 0.01,
+ average: 0.025,
+ high: 0.04,
+ },
+ },
+ },
+];
diff --git a/wallets/react/tests/legacy.test.tsx b/wallets/react/tests/legacy.test.tsx
new file mode 100644
index 000000000..8bf57185c
--- /dev/null
+++ b/wallets/react/tests/legacy.test.tsx
@@ -0,0 +1,261 @@
+import { legacyProviderImportsToVersionsInterface } from '@rango-dev/wallets-core/utils';
+import { Namespace as LegacyNamespace } from '@rango-dev/wallets-shared';
+import { renderHook } from '@testing-library/react-hooks';
+import { TransactionType } from 'rango-types';
+import React from 'react';
+import { describe, expect, test, vi } from 'vitest';
+
+import { Provider, useWallets } from '../src/index.js';
+import {
+ blockchainsMeta,
+ legacyAddress,
+ legacyProvider,
+} from '../src/test-utils/fixtures.js';
+
+describe('check legacy is working correctly', () => {
+ test("initialize legacy provider and it's accessible", async () => {
+ const wrapper = ({ children }: any) => {
+ const list = [legacyProviderImportsToVersionsInterface(legacyProvider)];
+
+ return {children};
+ };
+
+ const { result } = renderHook(() => useWallets(), {
+ wrapper,
+ });
+
+ // providers are evaluated lazily, so before calling `connect` its value is `null`
+ expect(result.current.providers()['legacy-garbage']).toBe(null);
+
+ // while try to connect, `provider` will be initialized.
+ await result.current.connect('legacy-garbage');
+ expect(result.current.providers()['legacy-garbage']).toStrictEqual(
+ legacyProvider.getInstance()
+ );
+ });
+
+ test.todo('check allBlockchains works correctly', () => {
+ //
+ });
+
+ test.todo('check onUpdateState works correctly', () => {
+ //
+ });
+
+ test.todo('change props value after initializing', () => {
+ //
+ });
+});
+
+describe('check legacy connect method is working', () => {
+ test('throw an error if trying to connect to an undefined wallet', async () => {
+ const wrapper = ({ children }: any) => {
+ const list = [legacyProviderImportsToVersionsInterface(legacyProvider)];
+
+ return {children};
+ };
+
+ const { result } = renderHook(() => useWallets(), {
+ wrapper,
+ });
+
+ await expect(result.current.connect('whatever')).rejects.toThrow(
+ 'You should add'
+ );
+ });
+
+ test('will be ignored and use first namespace when passing multiple namespaces', async () => {
+ const wrapper = ({ children }: any) => {
+ const list = [legacyProviderImportsToVersionsInterface(legacyProvider)];
+
+ return {children};
+ };
+
+ const { result } = renderHook(() => useWallets(), {
+ wrapper,
+ });
+
+ const connectResult = await result.current.connect('legacy-garbage', [
+ {
+ namespace: LegacyNamespace.Evm,
+ network: 'eth',
+ },
+ {
+ namespace: LegacyNamespace.Evm,
+ network: 'arb',
+ },
+ ]);
+
+ expect(connectResult).toHaveLength(1);
+ expect(connectResult[0].network).toBe('eth');
+ });
+ test('update internal states correctly', async () => {
+ const wrapper = ({ children }: any) => {
+ const list = [legacyProviderImportsToVersionsInterface(legacyProvider)];
+
+ return (
+
+ {children}
+
+ );
+ };
+
+ const { result } = renderHook(() => useWallets(), {
+ wrapper,
+ });
+
+ const initialState = {
+ installed: true,
+ connecting: false,
+ connected: false,
+ accounts: null,
+ network: null,
+ };
+ expect(result.current.state('legacy-garbage')).toMatchObject(initialState);
+
+ // connecting successfully.
+ await result.current.connect('legacy-garbage', [
+ { namespace: LegacyNamespace.Evm, network: 'ETH' },
+ ]);
+
+ expect(result.current.state('legacy-garbage')).toMatchObject({
+ installed: true,
+ connecting: false,
+ connected: true,
+ accounts: [`ETH:${legacyAddress}`],
+ network: 'ETH',
+ });
+
+ // unsuccessful connection
+ await expect(
+ result.current.connect('legacy-garbage', [
+ { namespace: LegacyNamespace.Evm, network: 'When Airdrop?' },
+ ])
+ ).rejects.toThrowError();
+ // state should be reset
+ expect(result.current.state('legacy-garbage')).toMatchObject(initialState);
+ });
+
+ test.todo("throw error when it's already on connecting", async () => {
+ //
+ });
+
+ test.todo('ensure extra context added to `connect` function', async () => {
+ // make sure correct values passed to `provider connect fn`: { instance, network, meta, namespaces}
+ });
+
+ test.todo(
+ 'return multiple result from connect should handle network and accounts correctly ',
+ async () => {
+ // if connect fn returns array, it has own logic.
+ }
+ );
+
+ test.todo('return empty result from connect', async () => {
+ // if connect fn return empty array, state shouldn't be updated.
+ });
+
+ test.todo('suggestAndConnect', async () => {
+ //
+ });
+});
+
+describe('check legacy switching network', () => {
+ test('switch network & canSwitchNetworkTo', async () => {
+ const switchNetwork = vi.fn();
+
+ const wrapper = ({ children }: any) => {
+ const extendLegacyProvider = { ...legacyProvider };
+ extendLegacyProvider.canSwitchNetworkTo = ({ meta, network }) => {
+ return !!meta.find((blockchain) => blockchain.name === network);
+ };
+ extendLegacyProvider.getWalletInfo = (allBlockChains) => {
+ const base = legacyProvider.getWalletInfo(allBlockChains);
+ return {
+ ...base,
+ supportedChains: blockchainsMeta,
+ };
+ };
+ extendLegacyProvider.switchNetwork = async () => {
+ switchNetwork();
+ };
+
+ const list = [
+ legacyProviderImportsToVersionsInterface(extendLegacyProvider),
+ ];
+
+ return (
+
+ {children}
+
+ );
+ };
+
+ const { result } = renderHook(() => useWallets(), {
+ wrapper,
+ });
+
+ // First we should connect to any network
+ await result.current.connect('legacy-garbage', [
+ {
+ namespace: LegacyNamespace.Evm,
+ network: 'ETH',
+ },
+ ]);
+
+ expect(result.current.state('legacy-garbage')).toMatchObject({
+ network: 'ETH',
+ });
+
+ expect(result.current.canSwitchNetworkTo('legacy-garbage', 'COSMOS')).toBe(
+ true
+ );
+ expect(
+ result.current.canSwitchNetworkTo('legacy-garbage', 'whatever')
+ ).toBe(false);
+
+ // Then passing a different network name, will trigger switch network.
+ await result.current.connect('legacy-garbage', [
+ {
+ namespace: LegacyNamespace.Evm,
+ network: 'COSMOS',
+ },
+ ]);
+
+ expect(switchNetwork).toBeCalledTimes(1);
+
+ expect(result.current.state('legacy-garbage')).toMatchObject({
+ network: 'COSMOS',
+ });
+ });
+});
+
+describe('check functionality related to connect', () => {
+ test.todo('disconnect & disconnectAll', async () => {
+ //
+ });
+
+ test.todo('autoConnect', async () => {
+ // connect method has an `if` for persisting wallet, check that as well.
+ });
+});
+
+describe('check signers', () => {
+ test('should signers be accessible', async () => {
+ const wrapper = ({ children }: any) => {
+ const list = [legacyProviderImportsToVersionsInterface(legacyProvider)];
+
+ return {children};
+ };
+
+ const { result } = renderHook(() => useWallets(), {
+ wrapper,
+ });
+
+ const signers = await result.current.getSigners('legacy-garbage');
+ expect(
+ await signers.getSigner(TransactionType.EVM).signMessage('', '', null)
+ ).toBeTypeOf('string');
+ expect(() => signers.getSigner(TransactionType.SOLANA)).toThrowError();
+ });
+});
diff --git a/yarn.lock b/yarn.lock
index 5dcc05a55..86538b301 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -64,6 +64,14 @@
"@babel/highlight" "^7.23.4"
chalk "^2.4.2"
+"@babel/code-frame@^7.10.4", "@babel/code-frame@^7.24.7":
+ version "7.24.7"
+ resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465"
+ integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==
+ dependencies:
+ "@babel/highlight" "^7.24.7"
+ picocolors "^1.0.0"
+
"@babel/code-frame@^7.23.5", "@babel/code-frame@^7.24.1", "@babel/code-frame@^7.24.2":
version "7.24.2"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.2.tgz#718b4b19841809a58b29b68cde80bc5e1aa6d9ae"
@@ -72,14 +80,6 @@
"@babel/highlight" "^7.24.2"
picocolors "^1.0.0"
-"@babel/code-frame@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465"
- integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==
- dependencies:
- "@babel/highlight" "^7.24.7"
- picocolors "^1.0.0"
-
"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.22.9", "@babel/compat-data@^7.23.3":
version "7.23.3"
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.3.tgz#3febd552541e62b5e883a25eb3effd7c7379db11"
@@ -7298,6 +7298,35 @@
dependencies:
rxjs "^7.0.0"
+"@testing-library/dom@^10.1.0":
+ version "10.4.0"
+ resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-10.4.0.tgz#82a9d9462f11d240ecadbf406607c6ceeeff43a8"
+ integrity sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==
+ dependencies:
+ "@babel/code-frame" "^7.10.4"
+ "@babel/runtime" "^7.12.5"
+ "@types/aria-query" "^5.0.1"
+ aria-query "5.3.0"
+ chalk "^4.1.0"
+ dom-accessibility-api "^0.5.9"
+ lz-string "^1.5.0"
+ pretty-format "^27.0.2"
+
+"@testing-library/react-hooks@^8.0.1":
+ version "8.0.1"
+ resolved "https://registry.yarnpkg.com/@testing-library/react-hooks/-/react-hooks-8.0.1.tgz#0924bbd5b55e0c0c0502d1754657ada66947ca12"
+ integrity sha512-Aqhl2IVmLt8IovEVarNDFuJDVWVvhnr9/GCU6UUnrYXwgDFF9h2L2o2P9KBni1AST5sT6riAyoukFLyjQUgD/g==
+ dependencies:
+ "@babel/runtime" "^7.12.5"
+ react-error-boundary "^3.1.0"
+
+"@testing-library/react@^16.0.0":
+ version "16.0.0"
+ resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-16.0.0.tgz#0a1e0c7a3de25841c3591b8cb7fb0cf0c0a27321"
+ integrity sha512-guuxUKRWQ+FgNX0h0NS0FIq3Q3uLtWVpBzcLOggmfMoUpgBnzBzvLLd4fbm6yS8ydJd94cIfY4yP9qUQjM2KwQ==
+ dependencies:
+ "@babel/runtime" "^7.12.5"
+
"@tonconnect/isomorphic-eventsource@^0.0.1":
version "0.0.1"
resolved "https://registry.yarnpkg.com/@tonconnect/isomorphic-eventsource/-/isomorphic-eventsource-0.0.1.tgz#199e5a86c31dad706b79826f65879e0d77d3dd51"
@@ -7508,6 +7537,11 @@
resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad"
integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==
+"@types/aria-query@^5.0.1":
+ version "5.0.4"
+ resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-5.0.4.tgz#1a31c3d378850d2778dabb6374d036dcba4ba708"
+ integrity sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==
+
"@types/babel__core@^7.0.0", "@types/babel__core@^7.18.0":
version "7.20.5"
resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017"
@@ -7884,7 +7918,7 @@
"@types/react" "*"
"@types/reactcss" "*"
-"@types/react-dom@*":
+"@types/react-dom@*", "@types/react-dom@^18.0.25":
version "18.3.0"
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.3.0.tgz#0cbc818755d87066ab6ca74fbedb2547d74a82b0"
integrity sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==
@@ -9094,6 +9128,13 @@ aria-hidden@^1.1.1:
dependencies:
tslib "^2.0.0"
+aria-query@5.3.0:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.0.tgz#650c569e41ad90b51b3d7df5e5eed1c7549c103e"
+ integrity sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==
+ dependencies:
+ dequal "^2.0.3"
+
array-back@^3.0.1, array-back@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/array-back/-/array-back-3.1.0.tgz#b8859d7a508871c9a7b2cf42f99428f65e96bfb0"
@@ -11138,7 +11179,7 @@ depd@2.0.0:
resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
-dequal@^2.0.2:
+dequal@^2.0.2, dequal@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be"
integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==
@@ -11241,6 +11282,11 @@ doctrine@^3.0.0:
dependencies:
esutils "^2.0.2"
+dom-accessibility-api@^0.5.9:
+ version "0.5.16"
+ resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz#5a7429e6066eb3664d911e33fb0e45de8eb08453"
+ integrity sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==
+
dom-converter@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768"
@@ -11497,7 +11543,7 @@ entities@^3.0.1:
resolved "https://registry.yarnpkg.com/entities/-/entities-3.0.1.tgz#2b887ca62585e96db3903482d336c1006c3001d4"
integrity sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==
-entities@^4.2.0, entities@^4.4.0:
+entities@^4.2.0, entities@^4.4.0, entities@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48"
integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==
@@ -12947,6 +12993,15 @@ handlebars@^4.7.7:
optionalDependencies:
uglify-js "^3.1.4"
+happy-dom@^14.12.0:
+ version "14.12.3"
+ resolved "https://registry.yarnpkg.com/happy-dom/-/happy-dom-14.12.3.tgz#1b5892c670461fd1db041bee690981c22d3d521f"
+ integrity sha512-vsYlEs3E9gLwA1Hp+w3qzu+RUDFf4VTT8cyKqVICoZ2k7WM++Qyd2LwzyTi5bqMJFiIC/vNpTDYuxdreENRK/g==
+ dependencies:
+ entities "^4.5.0"
+ webidl-conversions "^7.0.0"
+ whatwg-mimetype "^3.0.0"
+
hard-rejection@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883"
@@ -14673,6 +14728,11 @@ lru-cache@^6.0.0:
dependencies:
yallist "^4.0.0"
+lz-string@^1.5.0:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941"
+ integrity sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==
+
magic-string@^0.27.0:
version "0.27.0"
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.27.0.tgz#e4a3413b4bab6d98d2becffd48b4a257effdbbf3"
@@ -16274,6 +16334,15 @@ pretty-error@^4.0.0:
lodash "^4.17.20"
renderkid "^3.0.0"
+pretty-format@^27.0.2:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e"
+ integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==
+ dependencies:
+ ansi-regex "^5.0.1"
+ ansi-styles "^5.0.0"
+ react-is "^17.0.1"
+
pretty-format@^29.7.0:
version "29.7.0"
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812"
@@ -16758,6 +16827,13 @@ react-element-to-jsx-string@^15.0.0:
is-plain-object "5.0.0"
react-is "18.1.0"
+react-error-boundary@^3.1.0:
+ version "3.1.4"
+ resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-3.1.4.tgz#255db92b23197108757a888b01e5b729919abde0"
+ integrity sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA==
+ dependencies:
+ "@babel/runtime" "^7.12.5"
+
react-error-overlay@6.0.9:
version "6.0.9"
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.9.tgz#3c743010c9359608c375ecd6bc76f35d93995b0a"
@@ -16799,7 +16875,7 @@ react-i18next@^12.2.0:
"@babel/runtime" "^7.20.6"
html-parse-stringify "^3.0.1"
-react-is@17.0.2:
+react-is@17.0.2, react-is@^17.0.1:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
@@ -16809,6 +16885,11 @@ react-is@18.1.0:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.1.0.tgz#61aaed3096d30eacf2a2127118b5b41387d32a67"
integrity sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==
+"react-is@^16.12.0 || ^17.0.0 || ^18.0.0", react-is@^18.3.1:
+ version "18.3.1"
+ resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e"
+ integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==
+
react-is@^16.13.1, react-is@^16.7.0, react-is@^16.8.3:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
@@ -16884,6 +16965,14 @@ react-router@6.20.0:
dependencies:
"@remix-run/router" "1.13.0"
+react-shallow-renderer@^16.15.0:
+ version "16.15.0"
+ resolved "https://registry.yarnpkg.com/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz#48fb2cf9b23d23cde96708fe5273a7d3446f4457"
+ integrity sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA==
+ dependencies:
+ object-assign "^4.1.1"
+ react-is "^16.12.0 || ^17.0.0 || ^18.0.0"
+
react-style-singleton@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.2.1.tgz#f99e420492b2d8f34d38308ff660b60d0b1205b4"
@@ -16915,6 +17004,15 @@ react-syntax-highlighter@^15.5.0:
prismjs "^1.27.0"
refractor "^3.6.0"
+react-test-renderer@^18.3.1:
+ version "18.3.1"
+ resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-18.3.1.tgz#e693608a1f96283400d4a3afead6893f958b80b4"
+ integrity sha512-KkAgygexHUkQqtvvx/otwxtuFu5cVjfzTCtjXLH9boS19/Nbtg84zS7wIQn39G8IlrhThBpQsMKkq5ZHZIYFXA==
+ dependencies:
+ react-is "^18.3.1"
+ react-shallow-renderer "^16.15.0"
+ scheduler "^0.23.2"
+
react-textarea-autosize@^7.1.0:
version "7.1.2"
resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-7.1.2.tgz#70fdb333ef86bcca72717e25e623e90c336e2cda"
@@ -17530,6 +17628,13 @@ scheduler@^0.23.0:
dependencies:
loose-envify "^1.1.0"
+scheduler@^0.23.2:
+ version "0.23.2"
+ resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3"
+ integrity sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==
+ dependencies:
+ loose-envify "^1.1.0"
+
schema-utils@^3.1.1, schema-utils@^3.2.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe"
@@ -19258,6 +19363,11 @@ webidl-conversions@^4.0.2:
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==
+webidl-conversions@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a"
+ integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==
+
webpack-dev-middleware@^6.1.2:
version "6.1.3"
resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-6.1.3.tgz#79f4103f8c898564c9e96c3a9c2422de50f249bc"
@@ -19328,6 +19438,11 @@ whatwg-fetch@>=0.10.0:
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.19.tgz#caefd92ae630b91c07345537e67f8354db470973"
integrity sha512-d67JP4dHSbm2TrpFj8AbO8DnL1JXL5J9u0Kq2xW6d0TFDbCA3Muhdt8orXC22utleTVj7Prqt82baN6RBvnEgw==
+whatwg-mimetype@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz#5fa1a7623867ff1af6ca3dc72ad6b8a4208beba7"
+ integrity sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==
+
whatwg-url@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"