diff --git a/package.json b/package.json index 06c55819..1d03f168 100644 --- a/package.json +++ b/package.json @@ -96,7 +96,8 @@ "ts-jest": "^29.2.5", "typescript": "^5.3.3", "vite-tsconfig-paths": "^5.1.3", - "vitest": "^2.1.5" + "vitest": "^2.1.5", + "vitest-canvas-mock": "^0.3.3" }, "ci": { "type": "aci", diff --git a/packages/bridge/package.json b/packages/bridge/package.json index 10c802de..9f940079 100755 --- a/packages/bridge/package.json +++ b/packages/bridge/package.json @@ -41,7 +41,6 @@ "react-dom": "^18.0.0" }, "devDependencies": { - "babel-jest": "^29.7.0", "@portkey/did-ui-react": "^2.15.9", "@portkey/types": "^2.15.9", "@portkey/utils": "^2.15.9", diff --git a/packages/react/package.json b/packages/react/package.json index 1b7cc23a..17ff1091 100755 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -40,7 +40,6 @@ "@babel/preset-env": "^7.24.7", "@babel/preset-react": "^7.24.7", "@babel/preset-typescript": "^7.24.7", - "@types/jest": "^29.5.13", "@types/react": "^18.3.1", "@types/react-dom": "^18.3.0", "father": "^4.3.8" diff --git a/packages/tools/__mocks__/setupGlobal.ts b/packages/tools/__mocks__/setupGlobal.ts index 461458c4..59f0746b 100644 --- a/packages/tools/__mocks__/setupGlobal.ts +++ b/packages/tools/__mocks__/setupGlobal.ts @@ -1,4 +1,5 @@ import '@testing-library/jest-dom'; +import 'vitest-canvas-mock'; import { cleanup } from '@testing-library/react'; import { afterEach, beforeAll, vi } from 'vitest'; diff --git a/packages/tools/vite.config.ts b/packages/tools/vite.config.ts index 45adf8a4..18c9442a 100644 --- a/packages/tools/vite.config.ts +++ b/packages/tools/vite.config.ts @@ -20,6 +20,7 @@ export default defineConfig({ optimizer: { web: { enabled: true, + include: ['vitest-canvas-mock'], }, }, }, diff --git a/packages/utils/package.json b/packages/utils/package.json index fa1d6c03..e476cf4b 100755 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -23,9 +23,10 @@ "scripts": { "dev": "father dev", "build": "father build", - "test": "jest --config=jest.config.ts --detectOpenHandles", - "test:watch": "jest --config=jest.config.ts --watch --detectOpenHandles", - "test:coverage": "jest --config=jest.config.ts --coverage --detectOpenHandles" + "test": "vitest", + "test:dev": "pnpm test -- --watch", + "test:coverage": "pnpm test -- --coverage", + "test:ui": "pnpm test:dev --ui" }, "dependencies": { "@aelf-web-login/wallet-adapter-base": "0.1.2", diff --git a/packages/utils/src/address/__tests__/decodeAddress.test.ts b/packages/utils/src/address/__tests__/decodeAddress.test.ts index 8539726c..c534b7b8 100644 --- a/packages/utils/src/address/__tests__/decodeAddress.test.ts +++ b/packages/utils/src/address/__tests__/decodeAddress.test.ts @@ -1,18 +1,21 @@ +import { type Mock } from 'vitest'; import { decodeAddress } from '../decodeAddress'; import AElf from 'aelf-sdk'; // Mock AElf.utils.decodeAddressRep to avoid actual decoding during tests -jest.mock('aelf-sdk', () => { +vi.mock('aelf-sdk', () => { return { - utils: { - decodeAddressRep: jest.fn(), + default: { + utils: { + decodeAddressRep: vi.fn(), + }, }, }; }); describe('decodeAddress', () => { beforeEach(() => { - (AElf.utils.decodeAddressRep as jest.Mock).mockClear(); + (AElf.utils.decodeAddressRep as Mock).mockClear(); }); it('should return false when address is empty', () => { @@ -38,7 +41,7 @@ describe('decodeAddress', () => { }); it('should return false when AElf.utils.decodeAddressRep throws an error', () => { - (AElf.utils.decodeAddressRep as jest.Mock).mockImplementation(() => { + (AElf.utils.decodeAddressRep as Mock).mockImplementation(() => { throw new Error('Decoding failed'); }); expect(decodeAddress('validAddress')).toBe(false); diff --git a/packages/utils/src/contract/__tests__/getRawTransaction.test.ts b/packages/utils/src/contract/__tests__/getRawTransaction.test.ts index 80b026c2..e11337b4 100644 --- a/packages/utils/src/contract/__tests__/getRawTransaction.test.ts +++ b/packages/utils/src/contract/__tests__/getRawTransaction.test.ts @@ -3,23 +3,24 @@ import getRawTransactionDiscover from '../getRawTransactionDiscover'; import getRawTransactionPortkey from '../getRawTransactionPortkey'; import { getRawTransaction } from '../getRawTransaction'; import { WalletTypeEnum, TWalletInfo } from '@aelf-web-login/wallet-adapter-base'; +import { type Mock } from 'vitest'; -jest.mock('../getRawTransactionNight', () => ({ +vi.mock('../getRawTransactionNight', () => ({ __esModule: true, - default: jest.fn().mockResolvedValue('encodedDataMock1'), + default: vi.fn().mockResolvedValue('encodedDataMock1'), })); -jest.mock('../getRawTransactionDiscover', () => ({ +vi.mock('../getRawTransactionDiscover', () => ({ __esModule: true, - default: jest.fn().mockResolvedValue('encodedDataMock2'), + default: vi.fn().mockResolvedValue('encodedDataMock2'), })); -jest.mock('../getRawTransactionPortkey', () => ({ +vi.mock('../getRawTransactionPortkey', () => ({ __esModule: true, - default: jest.fn().mockResolvedValue('encodedDataMock3'), + default: vi.fn().mockResolvedValue('encodedDataMock3'), })); describe('getRawTransaction', () => { afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it('should call getRawTransactionPortkey for WalletTypeEnum.aa and return its result', async () => { @@ -100,9 +101,9 @@ describe('getRawTransaction', () => { it('should log and return null when an error occurs', async () => { const walletInfo: TWalletInfo = { address: 'mockAddress' }; - const consoleLogSpy = jest.spyOn(console, 'log').mockImplementation(); + const consoleLogSpy = vi.spyOn(console, 'log').mockImplementation(); - (getRawTransactionDiscover as jest.Mock).mockImplementation(() => { + (getRawTransactionDiscover as Mock).mockImplementation(() => { throw new Error('Decoding failed'); }); diff --git a/packages/utils/src/contract/__tests__/getRawTransactionNight.test.ts b/packages/utils/src/contract/__tests__/getRawTransactionNight.test.ts index 1ce9676b..2728afa7 100644 --- a/packages/utils/src/contract/__tests__/getRawTransactionNight.test.ts +++ b/packages/utils/src/contract/__tests__/getRawTransactionNight.test.ts @@ -1,20 +1,21 @@ import { getContractBasic } from '@portkey/contracts'; import getRawTransactionNight, { CreateTransactionParamsOfNight } from '../getRawTransactionNight'; +import { type Mock } from 'vitest'; -jest.mock('@portkey/contracts', () => ({ - getContractBasic: jest.fn(), +vi.mock('@portkey/contracts', () => ({ + getContractBasic: vi.fn(), })); describe('getRawTransactionNight', () => { beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it('should return encoded transaction data', async () => { const mockContract = { - encodedTx: jest.fn().mockResolvedValue({ data: 'encodedDataMock' }), + encodedTx: vi.fn().mockResolvedValue({ data: 'encodedDataMock' }), }; - (getContractBasic as jest.Mock).mockResolvedValue(mockContract); + (getContractBasic as Mock).mockResolvedValue(mockContract); const params: CreateTransactionParamsOfNight = { contractAddress: '0xExampleAddress', @@ -39,7 +40,7 @@ describe('getRawTransactionNight', () => { }); it('should handle errors from getContractBasic', async () => { - (getContractBasic as jest.Mock).mockRejectedValue(new Error('Failed to get contract')); + (getContractBasic as Mock).mockRejectedValue(new Error('Failed to get contract')); try { await getRawTransactionNight({ diff --git a/packages/utils/src/contract/__tests__/getRawTransactionPortkey.test.ts b/packages/utils/src/contract/__tests__/getRawTransactionPortkey.test.ts index 4430f3cd..f00fa955 100644 --- a/packages/utils/src/contract/__tests__/getRawTransactionPortkey.test.ts +++ b/packages/utils/src/contract/__tests__/getRawTransactionPortkey.test.ts @@ -3,29 +3,30 @@ import getRawTransactionPortkey, { } from '../getRawTransactionPortkey'; import { getContractBasic } from '@portkey/contracts'; import { aelf } from '@portkey/utils'; +import { type Mock } from 'vitest'; -jest.mock('@portkey/contracts', () => ({ - getContractBasic: jest.fn(), +vi.mock('@portkey/contracts', () => ({ + getContractBasic: vi.fn(), })); -jest.mock('@portkey/utils', () => ({ +vi.mock('@portkey/utils', () => ({ aelf: { - getWallet: jest.fn(), + getWallet: vi.fn(), }, })); describe('getRawTransactionPortkey', () => { beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it('should return encoded transaction data', async () => { const mockContract = { - encodedTx: jest.fn().mockResolvedValue({ data: 'encodedDataMock' }), + encodedTx: vi.fn().mockResolvedValue({ data: 'encodedDataMock' }), }; - (getContractBasic as jest.Mock).mockResolvedValue(mockContract); + (getContractBasic as Mock).mockResolvedValue(mockContract); - (aelf.getWallet as jest.Mock).mockReturnValue({ + (aelf.getWallet as Mock).mockReturnValue({ address: 'testAddress', }); @@ -57,7 +58,7 @@ describe('getRawTransactionPortkey', () => { }); it('should reject with error when getContractBasic fails', async () => { - (getContractBasic as jest.Mock).mockRejectedValue(new Error('Failed to get contract')); + (getContractBasic as Mock).mockRejectedValue(new Error('Failed to get contract')); const params: IRowTransactionPortkeyParams = { caHash: '0xExampleCaHash', diff --git a/packages/utils/src/contract/__tests__/getTxResultRetry.test.ts b/packages/utils/src/contract/__tests__/getTxResultRetry.test.ts index e9a8cbb3..dea93f09 100644 --- a/packages/utils/src/contract/__tests__/getTxResultRetry.test.ts +++ b/packages/utils/src/contract/__tests__/getTxResultRetry.test.ts @@ -1,24 +1,25 @@ +import { type Mock } from 'vitest'; import { getAElf, getTxResultRetry } from '../getTxResultRetry'; import { getTxResult } from '@portkey/contracts'; -jest.mock('@portkey/contracts', () => ({ - getTxResult: jest.fn(), +vi.mock('@portkey/contracts', () => ({ + getTxResult: vi.fn(), })); describe('test getAElf', () => { beforeEach(() => { - const mockConstructor = jest.fn((param1) => { + const mockConstructor = vi.fn((param1) => { return { param1, }; }); - const mockProviders = jest.fn().mockImplementation(() => { + const mockProviders = vi.fn().mockImplementation(() => { return { - HttpProvider: jest.fn().mockReturnValueOnce({}), + HttpProvider: vi.fn().mockReturnValueOnce({}), }; }); - jest.doMock('aelf-sdk', () => ({ + vi.doMock('aelf-sdk', () => ({ __esModule: true, default: mockConstructor, providers: mockProviders, @@ -48,7 +49,7 @@ describe('test getAElf', () => { describe('test getTxResultRetry', () => { beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it('returns mined transaction result', async () => { @@ -56,7 +57,7 @@ describe('test getTxResultRetry', () => { Status: 'MINED', }; - (getTxResult as jest.Mock).mockResolvedValue(mockTxResult); + (getTxResult as Mock).mockResolvedValue(mockTxResult); const TransactionId = 'some-transaction-id'; const rpcUrl = 'https://example-rpc.com'; @@ -70,7 +71,7 @@ describe('test getTxResultRetry', () => { const mockTxResult = { Status: 'FAILED', }; - (getTxResult as jest.Mock).mockResolvedValue(mockTxResult); + (getTxResult as Mock).mockResolvedValue(mockTxResult); const TransactionId = 'another-transaction-id'; const rpcUrl = 'https://example-rpc.com'; diff --git a/packages/utils/src/contract/__tests__/useCheckAllowanceAndApprove.test.ts b/packages/utils/src/contract/__tests__/useCheckAllowanceAndApprove.test.ts index fb76edb3..8752e2e7 100644 --- a/packages/utils/src/contract/__tests__/useCheckAllowanceAndApprove.test.ts +++ b/packages/utils/src/contract/__tests__/useCheckAllowanceAndApprove.test.ts @@ -3,19 +3,20 @@ import { renderHook, act } from '@testing-library/react'; import { useCheckAllowanceAndApprove } from '../useCheckAllowanceAndApprove'; import { useConnectWallet } from '@aelf-web-login/wallet-adapter-react'; -import { TChainId } from '@aelf-web-login/wallet-adapter-base'; +import { type TChainId } from '@aelf-web-login/wallet-adapter-base'; +import { type Mock } from 'vitest'; -jest.mock('@aelf-web-login/wallet-adapter-react', () => ({ - // ...jest.requireActual('@aelf-web-login/wallet-adapter-react'), - useConnectWallet: jest.fn(), +vi.mock('@aelf-web-login/wallet-adapter-react', () => ({ + // ...vi.requireActual('@aelf-web-login/wallet-adapter-react'), + useConnectWallet: vi.fn(), })); describe('useCheckAllowanceAndApprove allowance is little than amount', () => { - let mockCallViewMethod: jest.Mock; - let mockCallSendMethod: jest.Mock; + let mockCallViewMethod: Mock; + let mockCallSendMethod: Mock; beforeEach(() => { - mockCallViewMethod = jest.fn((params) => { + mockCallViewMethod = vi.fn((params) => { switch (params.methodName) { case 'GetAllowance': return Promise.resolve({ @@ -29,15 +30,15 @@ describe('useCheckAllowanceAndApprove allowance is little than amount', () => { return Promise.reject(new Error('Unsupported method')); } }); - mockCallSendMethod = jest.fn(); - (useConnectWallet as jest.Mock).mockReturnValue({ + mockCallSendMethod = vi.fn(); + (useConnectWallet as Mock).mockReturnValue({ callViewMethod: mockCallViewMethod, callSendMethod: mockCallSendMethod, }); }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it('should correctly call GetAllowance and GetTokenInfo when starting', async () => { @@ -82,18 +83,18 @@ describe('useCheckAllowanceAndApprove allowance is little than amount', () => { }); it('should log and return error when an error occurs', async () => { - (mockCallViewMethod as jest.Mock).mockImplementation(() => { + (mockCallViewMethod as Mock).mockImplementation(() => { throw new Error('failed'); }); }); }); describe('useCheckAllowanceAndApprove allowance is big than amount', () => { - let mockCallViewMethod: jest.Mock; - let mockCallSendMethod: jest.Mock; + let mockCallViewMethod: Mock; + let mockCallSendMethod: Mock; beforeEach(() => { - mockCallViewMethod = jest.fn((params) => { + mockCallViewMethod = vi.fn((params) => { switch (params.methodName) { case 'GetAllowance': return Promise.resolve({ @@ -111,15 +112,15 @@ describe('useCheckAllowanceAndApprove allowance is big than amount', () => { return Promise.reject(new Error('Unsupported method')); } }); - mockCallSendMethod = jest.fn(); - (useConnectWallet as jest.Mock).mockReturnValue({ + mockCallSendMethod = vi.fn(); + (useConnectWallet as Mock).mockReturnValue({ callViewMethod: mockCallViewMethod, callSendMethod: mockCallSendMethod, }); }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it('should correctly call GetAllowance and GetTokenInfo when starting', async () => { @@ -152,20 +153,20 @@ describe('useCheckAllowanceAndApprove allowance is big than amount', () => { }); describe('useCheckAllowanceAndApprove error occurs', () => { - let mockCallViewMethod: jest.Mock; - let mockCallSendMethod: jest.Mock; + let mockCallViewMethod: Mock; + let mockCallSendMethod: Mock; beforeEach(() => { - mockCallViewMethod = jest.fn(); - mockCallSendMethod = jest.fn(); - (useConnectWallet as jest.Mock).mockReturnValue({ + mockCallViewMethod = vi.fn(); + mockCallSendMethod = vi.fn(); + (useConnectWallet as Mock).mockReturnValue({ callViewMethod: mockCallViewMethod, callSendMethod: mockCallSendMethod, }); }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it('should log and return error when an error occurs', async () => { @@ -186,7 +187,7 @@ describe('useCheckAllowanceAndApprove error occurs', () => { chainId, }), ); - (mockCallViewMethod as jest.Mock).mockImplementation(() => { + (mockCallViewMethod as Mock).mockImplementation(() => { throw new Error('failed'); }); diff --git a/packages/utils/src/contract/__tests__/useGetBalance.test.ts b/packages/utils/src/contract/__tests__/useGetBalance.test.ts index 67e26e39..beb29d6a 100644 --- a/packages/utils/src/contract/__tests__/useGetBalance.test.ts +++ b/packages/utils/src/contract/__tests__/useGetBalance.test.ts @@ -1,16 +1,14 @@ /** @jest-environment jsdom */ import { renderHook, act } from '@testing-library/react'; import { useGetBalance } from '../useGetBalance'; -import { setupJestCanvasMock } from 'jest-canvas-mock'; beforeEach(() => { - jest.clearAllMocks(); - setupJestCanvasMock(); + vi.clearAllMocks(); }); -jest.mock('@aelf-web-login/wallet-adapter-react', () => ({ - useConnectWallet: jest.fn(() => ({ - callViewMethod: jest.fn(), +vi.mock('@aelf-web-login/wallet-adapter-react', () => ({ + useConnectWallet: vi.fn(() => ({ + callViewMethod: vi.fn(), })), })); diff --git a/packages/utils/src/is/__tests__/isAElfBridge.test.ts b/packages/utils/src/is/__tests__/isAElfBridge.test.ts index e52c1513..4c618d30 100644 --- a/packages/utils/src/is/__tests__/isAElfBridge.test.ts +++ b/packages/utils/src/is/__tests__/isAElfBridge.test.ts @@ -8,14 +8,14 @@ describe('test isAElfBridge', () => { rpcUrl: 'test', chainId: 'test', }, - connect: jest.fn(), + connect: vi.fn(), }; expect(isAElfBridge(aelfBridge as unknown as AElfDappBridge)).toBeTruthy(); }); test('return false when miss options and connect', () => { const aelfBridge = { - connect: jest.fn(), + connect: vi.fn(), }; expect(isAElfBridge(aelfBridge as unknown as AElfDappBridge)).toBeFalsy(); }); diff --git a/packages/utils/src/is/__tests__/isPortkey.test.ts b/packages/utils/src/is/__tests__/isPortkey.test.ts index f8af8cc6..460d7332 100644 --- a/packages/utils/src/is/__tests__/isPortkey.test.ts +++ b/packages/utils/src/is/__tests__/isPortkey.test.ts @@ -12,8 +12,8 @@ describe('isPortkey in window', () => { (global as any).window = { document: { body: {}, - addEventListener: jest.fn(), - removeEventListener: jest.fn(), + addEventListener: vi.fn(), + removeEventListener: vi.fn(), }, navigator: { userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)', @@ -21,8 +21,8 @@ describe('isPortkey in window', () => { }, location: { href: '', - reload: jest.fn(), - replace: jest.fn(), + reload: vi.fn(), + replace: vi.fn(), }, }; }); diff --git a/packages/utils/src/is/__tests__/isPrivateKey.test.ts b/packages/utils/src/is/__tests__/isPrivateKey.test.ts index 1c5aebef..4bfc75af 100644 --- a/packages/utils/src/is/__tests__/isPrivateKey.test.ts +++ b/packages/utils/src/is/__tests__/isPrivateKey.test.ts @@ -10,7 +10,7 @@ describe('test isPrivateKey', () => { test('returns false when Buffer.from throw error', () => { const originalFrom = Buffer.from; - jest.spyOn(Buffer, 'from').mockImplementationOnce(() => { + vi.spyOn(Buffer, 'from').mockImplementationOnce(() => { throw new Error('Mocked buffer error'); }); diff --git a/packages/utils/src/utility/__tests__/Loading.test.tsx b/packages/utils/src/utility/__tests__/Loading.test.tsx index 2fff47e8..134de89a 100644 --- a/packages/utils/src/utility/__tests__/Loading.test.tsx +++ b/packages/utils/src/utility/__tests__/Loading.test.tsx @@ -11,7 +11,7 @@ describe('Loading class', () => { }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); document.body.innerHTML = ''; }); diff --git a/packages/utils/src/utility/__tests__/sleep.test.ts b/packages/utils/src/utility/__tests__/sleep.test.ts index 76f2ea7e..419a172c 100644 --- a/packages/utils/src/utility/__tests__/sleep.test.ts +++ b/packages/utils/src/utility/__tests__/sleep.test.ts @@ -1,7 +1,7 @@ import { sleep } from '../sleep'; -jest.useFakeTimers(); -jest.spyOn(global, 'setTimeout'); +vi.useFakeTimers(); +vi.spyOn(global, 'setTimeout'); test('waits 1 second', () => { sleep(1000); diff --git a/packages/utils/vite.config.ts b/packages/utils/vite.config.ts new file mode 100644 index 00000000..08b9a087 --- /dev/null +++ b/packages/utils/vite.config.ts @@ -0,0 +1,4 @@ +import baseViteConfig from '../tools/vite.config'; +import { mergeConfig } from 'vitest/config'; + +export default mergeConfig(baseViteConfig, {}); diff --git a/packages/utils/vitest.setup.ts b/packages/utils/vitest.setup.ts new file mode 100644 index 00000000..a5309360 --- /dev/null +++ b/packages/utils/vitest.setup.ts @@ -0,0 +1,2 @@ +import '../tools/__mocks__/setupGlobal'; +import '../tools/__mocks__/setupLocal'; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e48a166d..605b1696 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -150,6 +150,9 @@ importers: vitest: specifier: ^2.1.5 version: 2.1.5(@types/node@22.9.3)(@vitest/ui@2.1.5)(happy-dom@15.11.6)(jsdom@23.2.0)(less@4.2.0)(lightningcss@1.22.1)(sass@1.79.3)(terser@5.34.0) + vitest-canvas-mock: + specifier: ^0.3.3 + version: 0.3.3(vitest@2.1.5) packages/base: dependencies: @@ -215,9 +218,6 @@ importers: antd: specifier: 4.24.14 version: 4.24.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - babel-jest: - specifier: ^29.7.0 - version: 29.7.0(@babel/core@7.25.2) father: specifier: ^4.3.8 version: 4.5.0(@babel/core@7.25.2)(@types/node@22.9.3)(styled-components@6.1.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(type-fest@0.21.3)(webpack@5.95.0(@swc/core@1.9.3(@swc/helpers@0.5.1))) @@ -252,9 +252,6 @@ importers: '@babel/preset-typescript': specifier: ^7.24.7 version: 7.24.7(@babel/core@7.25.2) - '@types/jest': - specifier: ^29.5.13 - version: 29.5.13 '@types/react': specifier: ^18.3.1 version: 18.3.9 @@ -10945,6 +10942,11 @@ packages: terser: optional: true + vitest-canvas-mock@0.3.3: + resolution: {integrity: sha512-3P968tYBpqYyzzOaVtqnmYjqbe13576/fkjbDEJSfQAkHtC5/UjuRHOhFEN/ZV5HVZIkaROBUWgazDKJ+Ibw+Q==} + peerDependencies: + vitest: '*' + vitest@2.1.5: resolution: {integrity: sha512-P4ljsdpuzRTPI/kbND2sDZ4VmieerR2c9szEZpjc+98Z9ebvnXmM5+0tHEKqYZumXqlvnmfWsjeFOjXVriDG7A==} engines: {node: ^18.0.0 || >=20.0.0} @@ -24954,6 +24956,11 @@ snapshots: sass: 1.79.3 terser: 5.34.0 + vitest-canvas-mock@0.3.3(vitest@2.1.5): + dependencies: + jest-canvas-mock: 2.5.2 + vitest: 2.1.5(@types/node@22.9.3)(@vitest/ui@2.1.5)(happy-dom@15.11.6)(jsdom@23.2.0)(less@4.2.0)(lightningcss@1.22.1)(sass@1.79.3)(terser@5.34.0) + vitest@2.1.5(@types/node@22.9.3)(@vitest/ui@2.1.5)(happy-dom@15.11.6)(jsdom@23.2.0)(less@4.2.0)(lightningcss@1.22.1)(sass@1.79.3)(terser@5.34.0): dependencies: '@vitest/expect': 2.1.5