diff --git a/cli/commands/auth/tests/login.test.ts b/cli/commands/auth/tests/login.test.ts index e673f216ac..a6aa886b23 100644 --- a/cli/commands/auth/tests/login.test.ts +++ b/cli/commands/auth/tests/login.test.ts @@ -29,16 +29,16 @@ vi.mock( 'cli/lib/appdata' ); vi.mock( 'cli/lib/browser' ); vi.mock( 'cli/lib/i18n' ); vi.mock( 'cli/logger', () => ( { - Logger: vi.fn( () => ( { - reportStart: mockReportStart, - reportSuccess: mockReportSuccess, - reportError: mockReportError, - reportProgress: mockReportProgress, - reportWarning: mockReportWarning, - reportKeyValuePair: mockReportKeyValuePair, - spinner: {}, - currentAction: null, - } ) ), + Logger: class { + reportStart = mockReportStart; + reportSuccess = mockReportSuccess; + reportError = mockReportError; + reportProgress = mockReportProgress; + reportWarning = mockReportWarning; + reportKeyValuePair = mockReportKeyValuePair; + spinner = {}; + currentAction = null; + }, LoggerError: class LoggerError extends Error {}, } ) ); diff --git a/cli/commands/auth/tests/logout.test.ts b/cli/commands/auth/tests/logout.test.ts index 776cb9c763..11ce95ed88 100644 --- a/cli/commands/auth/tests/logout.test.ts +++ b/cli/commands/auth/tests/logout.test.ts @@ -21,16 +21,16 @@ import { runCommand } from '../logout'; vi.mock( 'cli/lib/appdata' ); vi.mock( 'cli/lib/api' ); vi.mock( 'cli/logger', () => ( { - Logger: vi.fn( () => ( { - reportStart: mockReportStart, - reportSuccess: mockReportSuccess, - reportError: mockReportError, - reportProgress: mockReportProgress, - reportWarning: mockReportWarning, - reportKeyValuePair: mockReportKeyValuePair, - spinner: {}, - currentAction: null, - } ) ), + Logger: class { + reportStart = mockReportStart; + reportSuccess = mockReportSuccess; + reportError = mockReportError; + reportProgress = mockReportProgress; + reportWarning = mockReportWarning; + reportKeyValuePair = mockReportKeyValuePair; + spinner = {}; + currentAction = null; + }, LoggerError: class LoggerError extends Error {}, } ) ); diff --git a/cli/commands/auth/tests/status.test.ts b/cli/commands/auth/tests/status.test.ts index f188c0ab55..61909956ad 100644 --- a/cli/commands/auth/tests/status.test.ts +++ b/cli/commands/auth/tests/status.test.ts @@ -15,16 +15,16 @@ import { runCommand } from '../status'; vi.mock( 'cli/lib/api' ); vi.mock( 'cli/lib/appdata' ); vi.mock( 'cli/logger', () => ( { - Logger: vi.fn( () => ( { - reportStart: mockReportStart, - reportSuccess: mockReportSuccess, - reportError: mockReportError, - reportProgress: mockReportProgress, - reportWarning: mockReportWarning, - reportKeyValuePair: mockReportKeyValuePair, - spinner: {}, - currentAction: null, - } ) ), + Logger: class { + reportStart = mockReportStart; + reportSuccess = mockReportSuccess; + reportError = mockReportError; + reportProgress = mockReportProgress; + reportWarning = mockReportWarning; + reportKeyValuePair = mockReportKeyValuePair; + spinner = {}; + currentAction = null; + }, LoggerError: class LoggerError extends Error {}, } ) ); diff --git a/cli/commands/preview/tests/create.test.ts b/cli/commands/preview/tests/create.test.ts index 11b4518b76..c2e7932ed6 100644 --- a/cli/commands/preview/tests/create.test.ts +++ b/cli/commands/preview/tests/create.test.ts @@ -31,16 +31,16 @@ vi.mock( 'cli/lib/archive' ); vi.mock( 'cli/lib/api' ); vi.mock( 'cli/lib/snapshots' ); vi.mock( 'cli/logger', () => ( { - Logger: vi.fn( () => ( { - reportStart: mockReportStart, - reportSuccess: mockReportSuccess, - reportError: mockReportError, - reportProgress: mockReportProgress, - reportWarning: mockReportWarning, - reportKeyValuePair: mockReportKeyValuePair, - spinner: {}, - currentAction: null, - } ) ), + Logger: class { + reportStart = mockReportStart; + reportSuccess = mockReportSuccess; + reportError = mockReportError; + reportProgress = mockReportProgress; + reportWarning = mockReportWarning; + reportKeyValuePair = mockReportKeyValuePair; + spinner = {}; + currentAction = null; + }, LoggerError: class LoggerError extends Error {}, } ) ); diff --git a/cli/commands/preview/tests/delete.test.ts b/cli/commands/preview/tests/delete.test.ts index 4f14f21da0..5f0d09c00f 100644 --- a/cli/commands/preview/tests/delete.test.ts +++ b/cli/commands/preview/tests/delete.test.ts @@ -24,16 +24,16 @@ vi.mock( 'cli/lib/appdata', async () => { vi.mock( 'cli/lib/api' ); vi.mock( 'cli/lib/snapshots' ); vi.mock( 'cli/logger', () => ( { - Logger: vi.fn( () => ( { - reportStart: mockReportStart, - reportSuccess: mockReportSuccess, - reportError: mockReportError, - reportProgress: mockReportProgress, - reportWarning: mockReportWarning, - reportKeyValuePair: mockReportKeyValuePair, - spinner: {}, - currentAction: null, - } ) ), + Logger: class { + reportStart = mockReportStart; + reportSuccess = mockReportSuccess; + reportError = mockReportError; + reportProgress = mockReportProgress; + reportWarning = mockReportWarning; + reportKeyValuePair = mockReportKeyValuePair; + spinner = {}; + currentAction = null; + }, LoggerError: class LoggerError extends Error {}, } ) ); diff --git a/cli/commands/preview/tests/list.test.ts b/cli/commands/preview/tests/list.test.ts index 44622ee2a2..ed3851c8e5 100644 --- a/cli/commands/preview/tests/list.test.ts +++ b/cli/commands/preview/tests/list.test.ts @@ -22,16 +22,16 @@ vi.mock( 'cli/lib/appdata', async () => { } ); vi.mock( 'cli/lib/snapshots' ); vi.mock( 'cli/logger', () => ( { - Logger: vi.fn( () => ( { - reportStart: mockReportStart, - reportSuccess: mockReportSuccess, - reportError: mockReportError, - reportProgress: mockReportProgress, - reportWarning: mockReportWarning, - reportKeyValuePair: mockReportKeyValuePair, - spinner: {}, - currentAction: null, - } ) ), + Logger: class { + reportStart = mockReportStart; + reportSuccess = mockReportSuccess; + reportError = mockReportError; + reportProgress = mockReportProgress; + reportWarning = mockReportWarning; + reportKeyValuePair = mockReportKeyValuePair; + spinner = {}; + currentAction = null; + }, LoggerError: class LoggerError extends Error {}, } ) ); diff --git a/cli/commands/preview/tests/update.test.ts b/cli/commands/preview/tests/update.test.ts index f72e7d05a1..1dcb1cf406 100644 --- a/cli/commands/preview/tests/update.test.ts +++ b/cli/commands/preview/tests/update.test.ts @@ -27,11 +27,11 @@ vi.mock( 'cli/lib/api' ); vi.mock( 'cli/lib/snapshots' ); vi.mock( 'cli/logger', () => ( { - Logger: vi.fn( () => ( { - reportStart: mockReportStart, - reportSuccess: mockReportSuccess, - reportError: mockReportError, - } ) ), + Logger: class { + reportStart = mockReportStart; + reportSuccess = mockReportSuccess; + reportError = mockReportError; + }, LoggerError: class LoggerError extends Error {}, } ) ); diff --git a/cli/commands/site/tests/create.test.ts b/cli/commands/site/tests/create.test.ts index 13b759696f..47a668818a 100644 --- a/cli/commands/site/tests/create.test.ts +++ b/cli/commands/site/tests/create.test.ts @@ -58,13 +58,13 @@ vi.mock( 'cli/lib/appdata', async () => { updateSiteLatestCliPid: vi.fn(), updateSiteAutoStart: vi.fn().mockResolvedValue( undefined ), removeSiteFromAppdata: vi.fn(), - getSiteUrl: vi.fn( ( site ) => `http://localhost:${ site.port }` ), + getSiteUrl: vi.fn().mockImplementation( ( site ) => `http://localhost:${ site.port }` ), }; } ); vi.mock( 'cli/lib/language-packs' ); vi.mock( 'cli/lib/pm2-manager' ); vi.mock( 'cli/lib/server-files', () => ( { - getServerFilesPath: vi.fn( () => '/test/server-files' ), + getServerFilesPath: vi.fn().mockReturnValue( '/test/server-files' ), } ) ); vi.mock( 'cli/lib/site-language' ); vi.mock( 'cli/lib/site-utils' ); diff --git a/cli/commands/site/tests/status.test.ts b/cli/commands/site/tests/status.test.ts index 3076bf1201..4c8448ea49 100644 --- a/cli/commands/site/tests/status.test.ts +++ b/cli/commands/site/tests/status.test.ts @@ -10,7 +10,7 @@ vi.mock( 'cli/lib/appdata', async () => { ...actual, getSiteByFolder: vi.fn(), getSiteUrl: vi.fn(), - getAppdataDirectory: vi.fn( () => '/test/appdata' ), + getAppdataDirectory: vi.fn().mockReturnValue( '/test/appdata' ), }; } ); vi.mock( 'cli/lib/pm2-manager' ); diff --git a/cli/lib/tests/api.test.ts b/cli/lib/tests/api.test.ts index ad3cc26c55..fb9e780f1a 100644 --- a/cli/lib/tests/api.test.ts +++ b/cli/lib/tests/api.test.ts @@ -4,7 +4,12 @@ import wpcomFactory from 'src/lib/wpcom-factory'; import { vi } from 'vitest'; import { uploadArchive, waitForSiteReady, SnapshotStatus } from 'cli/lib/api'; import { LoggerError } from 'cli/logger'; -vi.mock( 'fs' ); + +vi.mock( 'fs', () => ( { + default: { + createReadStream: vi.fn(), + }, +} ) ); vi.mock( 'wpcom' ); vi.mock( 'wpcom-xhr-request' ); vi.mock( 'src/lib/wpcom-factory', () => ( { @@ -18,11 +23,11 @@ describe( 'API Module', () => { const mockWordPressVersion = '6.8.1'; const mockSiteUrl = 'test-site.wp.build'; const mockSiteId = 12345; - const mockReadStream = { pipe: vi.fn() }; + const mockReadStream = { pipe: vi.fn() } as unknown as ReturnType< typeof fs.createReadStream >; beforeEach( () => { vi.clearAllMocks(); - vi.mocked( fs.createReadStream, { partial: true } ).mockReturnValue( mockReadStream ); + vi.mocked( fs.createReadStream ).mockReturnValue( mockReadStream ); } ); describe( 'uploadArchive', () => { @@ -37,7 +42,9 @@ describe( 'API Module', () => { post: vi.fn().mockResolvedValue( mockResponse ), } ), }; - vi.mocked( wpcomFactory, { partial: true } ).mockReturnValue( mockWpcom ); + vi.mocked( wpcomFactory ).mockReturnValue( + mockWpcom as unknown as ReturnType< typeof wpcomFactory > + ); const result = await uploadArchive( mockArchivePath, mockToken, mockWordPressVersion ); @@ -72,7 +79,9 @@ describe( 'API Module', () => { } ), } ), }; - vi.mocked( wpcomFactory, { partial: true } ).mockReturnValue( mockWpcom ); + vi.mocked( wpcomFactory ).mockReturnValue( + mockWpcom as unknown as ReturnType< typeof wpcomFactory > + ); await uploadArchive( mockArchivePath, mockToken, mockWordPressVersion ); expect( mockWpcom.req.post ).toHaveBeenCalledWith( { @@ -99,7 +108,9 @@ describe( 'API Module', () => { post: vi.fn().mockRejectedValue( mockError ), } ), }; - vi.mocked( wpcomFactory, { partial: true } ).mockReturnValue( mockWpcom ); + vi.mocked( wpcomFactory ).mockReturnValue( + mockWpcom as unknown as ReturnType< typeof wpcomFactory > + ); await expect( uploadArchive( mockArchivePath, mockToken, mockWordPressVersion ) @@ -117,7 +128,9 @@ describe( 'API Module', () => { post: vi.fn().mockResolvedValue( invalidResponse ), } ), }; - vi.mocked( wpcomFactory, { partial: true } ).mockReturnValue( mockWpcom ); + vi.mocked( wpcomFactory ).mockReturnValue( + mockWpcom as unknown as ReturnType< typeof wpcomFactory > + ); await expect( uploadArchive( mockArchivePath, mockToken, mockWordPressVersion ) @@ -161,7 +174,9 @@ describe( 'API Module', () => { .mockResolvedValueOnce( activeResponse ), } ), }; - vi.mocked( wpcomFactory, { partial: true } ).mockReturnValue( mockWpcom ); + vi.mocked( wpcomFactory ).mockReturnValue( + mockWpcom as unknown as ReturnType< typeof wpcomFactory > + ); const result = await waitForSiteReady( mockSiteId, mockToken ); expect( mockWpcom.req.get ).toHaveBeenCalledTimes( 2 ); @@ -181,7 +196,9 @@ describe( 'API Module', () => { get: vi.fn().mockResolvedValue( pendingResponse ), } ), }; - vi.mocked( wpcomFactory, { partial: true } ).mockReturnValue( mockWpcom ); + vi.mocked( wpcomFactory ).mockReturnValue( + mockWpcom as unknown as ReturnType< typeof wpcomFactory > + ); try { await waitForSiteReady( mockSiteId, mockToken ); @@ -212,7 +229,9 @@ describe( 'API Module', () => { .mockResolvedValueOnce( validResponse ), } ), }; - vi.mocked( wpcomFactory, { partial: true } ).mockReturnValue( mockWpcom ); + vi.mocked( wpcomFactory ).mockReturnValue( + mockWpcom as unknown as ReturnType< typeof wpcomFactory > + ); const result = await waitForSiteReady( mockSiteId, mockToken ); expect( mockWpcom.req.get ).toHaveBeenCalledTimes( 2 ); diff --git a/cli/lib/tests/appdata.test.ts b/cli/lib/tests/appdata.test.ts index 6a5d9f058a..325a453609 100644 --- a/cli/lib/tests/appdata.test.ts +++ b/cli/lib/tests/appdata.test.ts @@ -13,15 +13,31 @@ import { unlockAppdata, } from 'cli/lib/appdata'; -vi.mock( 'fs' ); -vi.mock( 'os' ); -vi.mock( 'path' ); +vi.mock( 'fs', () => ( { + default: { + existsSync: vi.fn(), + }, +} ) ); +vi.mock( 'os', () => ( { + default: { + homedir: vi.fn(), + }, +} ) ); +vi.mock( 'path', () => ( { + default: { + join: vi.fn(), + basename: vi.fn(), + resolve: vi.fn(), + }, +} ) ); vi.mock( 'atomically', () => ( { readFile: vi.fn(), writeFile: vi.fn(), } ) ); -vi.mock( 'common/lib/fs-utils' ); +vi.mock( 'common/lib/fs-utils', () => ( { + arePathsEqual: vi.fn(), +} ) ); vi.mock( 'cli/lib/api', () => ( { validateAccessToken: vi.fn().mockResolvedValue( undefined ), } ) ); diff --git a/cli/lib/tests/archive.test.ts b/cli/lib/tests/archive.test.ts index 1576efca5a..a1d4f29977 100644 --- a/cli/lib/tests/archive.test.ts +++ b/cli/lib/tests/archive.test.ts @@ -3,9 +3,22 @@ import path from 'path'; import archiver from 'archiver'; import { vi } from 'vitest'; import { archiveSiteContent, cleanup } from 'cli/lib/archive'; -vi.mock( 'fs' ); -vi.mock( 'path' ); -vi.mock( 'archiver' ); + +vi.mock( 'fs', () => ( { + default: { + createWriteStream: vi.fn(), + existsSync: vi.fn(), + unlinkSync: vi.fn(), + }, +} ) ); +vi.mock( 'path', () => ( { + default: { + join: vi.fn(), + }, +} ) ); +vi.mock( 'archiver', () => ( { + default: vi.fn(), +} ) ); describe( 'Archive Module', () => { const mockSiteFolder = '/mock/site/folder'; @@ -44,8 +57,12 @@ describe( 'Archive Module', () => { vi.clearAllMocks(); mockArchiver = createMockArchiver(); mockWriteStream = createMockWriteStream(); - vi.mocked( archiver, { partial: true } ).mockReturnValue( mockArchiver ); - vi.mocked( fs.createWriteStream, { partial: true } ).mockReturnValue( mockWriteStream ); + vi.mocked( archiver ).mockReturnValue( + mockArchiver as unknown as ReturnType< typeof archiver > + ); + vi.mocked( fs.createWriteStream ).mockReturnValue( + mockWriteStream as unknown as ReturnType< typeof fs.createWriteStream > + ); vi.mocked( path.join ).mockImplementation( ( ...args ) => args.join( '/' ) ); } ); diff --git a/cli/lib/tests/pm2-manager.test.ts b/cli/lib/tests/pm2-manager.test.ts index 73352dfcb1..a14a6770cd 100644 --- a/cli/lib/tests/pm2-manager.test.ts +++ b/cli/lib/tests/pm2-manager.test.ts @@ -3,7 +3,13 @@ import { clearCache } from 'common/lib/cache-function-ttl'; import { vi } from 'vitest'; import { getAppdataPath } from 'cli/lib/appdata'; import { ManagerMessage } from '../types/wordpress-server-ipc'; -vi.mock( 'fs' ); + +vi.mock( 'fs', () => ( { + default: { + existsSync: vi.fn().mockReturnValue( true ), + mkdirSync: vi.fn(), + }, +} ) ); vi.mock( 'os', () => ( { default: { homedir: vi.fn().mockReturnValue( '/home/user' ), @@ -25,8 +31,18 @@ const mockPm2Instance = { }; vi.mock( 'pm2', () => { + class MockPM2 { + connect = mockPm2Instance.connect; + disconnect = mockPm2Instance.disconnect; + list = mockPm2Instance.list; + start = mockPm2Instance.start; + delete = mockPm2Instance.delete; + launchBus = mockPm2Instance.launchBus; + sendDataToProcessId = mockPm2Instance.sendDataToProcessId; + } + return { - custom: vi.fn().mockImplementation( () => mockPm2Instance ), + custom: MockPM2, }; } ); diff --git a/cli/lib/tests/snapshots.test.ts b/cli/lib/tests/snapshots.test.ts index 4e82b6dfd2..feb3f9e704 100644 --- a/cli/lib/tests/snapshots.test.ts +++ b/cli/lib/tests/snapshots.test.ts @@ -11,11 +11,11 @@ import { LoggerError } from 'cli/logger'; const mocks = vi.hoisted( () => ( { readFile: vi.fn(), writeFile: vi.fn(), - pathJoin: vi.fn( ( ...args: string[] ) => args.join( '/' ) ), - pathResolve: vi.fn( ( path: string ) => path ), + pathJoin: vi.fn().mockImplementation( ( ...args: string[] ) => args.join( '/' ) ), + pathResolve: vi.fn().mockImplementation( ( path: string ) => path ), pathBasename: vi.fn(), - lockfileLock: vi.fn( ( path, options, callback ) => callback( null ) ), - lockfileUnlock: vi.fn( ( path, callback ) => callback( null ) ), + lockfileLock: vi.fn().mockImplementation( ( path, options, callback ) => callback( null ) ), + lockfileUnlock: vi.fn().mockImplementation( ( path, callback ) => callback( null ) ), arePathsEqual: vi.fn(), isWordPressDirectory: vi.fn(), existsSync: vi.fn(), diff --git a/cli/lib/tests/validation.test.ts b/cli/lib/tests/validation.test.ts index 259379275b..768461d8d8 100644 --- a/cli/lib/tests/validation.test.ts +++ b/cli/lib/tests/validation.test.ts @@ -4,8 +4,17 @@ import { calculateDirectorySize, isWordPressDirectory } from 'common/lib/fs-util import { vi } from 'vitest'; import { validateSiteSize } from 'cli/lib/validation'; import { LoggerError } from 'cli/logger'; -vi.mock( 'fs' ); -vi.mock( 'path' ); + +vi.mock( 'fs', () => ( { + default: { + existsSync: vi.fn(), + }, +} ) ); +vi.mock( 'path', () => ( { + default: { + join: vi.fn(), + }, +} ) ); vi.mock( 'common/lib/fs-utils', () => ( { calculateDirectorySize: vi.fn(), isWordPressDirectory: vi.fn(), diff --git a/package-lock.json b/package-lock.json index b394e6df23..362d47149d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -71,11 +71,11 @@ "@electron-forge/maker-zip": "^7.11.1", "@electron-forge/plugin-auto-unpack-natives": "^7.11.1", "@eslint/js": "^9.39.2", - "@playwright/test": "^1.58.1", + "@playwright/test": "^1.58.2", "@sentry/react": "^7.120.3", "@sentry/vite-plugin": "^4.3.0", "@testing-library/jest-dom": "^6.9.1", - "@testing-library/react": "^16.3.1", + "@testing-library/react": "^16.3.2", "@testing-library/user-event": "^14.6.1", "@types/archiver": "^6.0.4", "@types/follow-redirects": "^1.14.4", @@ -91,7 +91,7 @@ "@types/yargs": "^17.0.35", "@types/yauzl": "^2.10.3", "@vitejs/plugin-react": "^5.1.4", - "@vitest/ui": "^2.1.8", + "@vitest/ui": "^4.0.18", "@wordpress/components": "^32.1.0", "@wordpress/element": "^6.39.0", "@wordpress/react-i18n": "^4.39.0", @@ -125,7 +125,7 @@ "vite-plugin-static-copy": "^3.1.5", "vite-plugin-top-level-await": "^1.6.0", "vite-plugin-wasm": "^3.5.0", - "vitest": "^2.1.9", + "vitest": "^4.0.18", "web-streams-polyfill": "^4.2.0" }, "engines": { @@ -3611,74 +3611,6 @@ "version": "0.3.1", "license": "MIT" }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/@esbuild/darwin-arm64": { "version": "0.25.12", "cpu": [ @@ -3694,210 +3626,6 @@ "node": ">=18" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/@esbuild/netbsd-arm64": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", @@ -3915,23 +3643,6 @@ "node": ">=18" } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/@esbuild/openbsd-arm64": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", @@ -3949,23 +3660,6 @@ "node": ">=18" } }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/@esbuild/openharmony-arm64": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", @@ -3983,74 +3677,6 @@ "node": ">=18" } }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/@eslint-community/eslint-utils": { "version": "4.9.1", "license": "MIT", @@ -7283,11 +6909,13 @@ } }, "node_modules/@playwright/test": { - "version": "1.58.1", + "version": "1.58.2", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.58.2.tgz", + "integrity": "sha512-akea+6bHYBBfA9uQqSYmlJXn61cTa+jbO87xVLCWbTqbWadRVmhxlXATaOjOgcBaWU4ePo0wB41KMFv3o35IXA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.58.1" + "playwright": "1.58.2" }, "bin": { "playwright": "cli.js" @@ -8620,7 +8248,9 @@ "license": "MIT" }, "node_modules/@testing-library/react": { - "version": "16.3.1", + "version": "16.3.2", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.2.tgz", + "integrity": "sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==", "dev": true, "license": "MIT", "dependencies": { @@ -8779,6 +8409,17 @@ "@types/responselike": "^1.0.0" } }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, "node_modules/@types/connect": { "version": "3.4.38", "license": "MIT", @@ -8793,6 +8434,13 @@ "@types/ms": "*" } }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/eslint": { "version": "9.6.1", "dev": true, @@ -9635,59 +9283,98 @@ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, - "node_modules/@vitest/expect": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.9.tgz", - "integrity": "sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==", + "node_modules/@vitest/expect": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.18.tgz", + "integrity": "sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.0.18", + "@vitest/utils": "4.0.18", + "chai": "^6.2.1", + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.18.tgz", + "integrity": "sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "4.0.18", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0-0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/mocker/node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "2.1.9", - "@vitest/utils": "2.1.9", - "chai": "^5.1.2", - "tinyrainbow": "^1.2.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "@jridgewell/sourcemap-codec": "^1.5.5" } }, "node_modules/@vitest/pretty-format": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.9.tgz", - "integrity": "sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==", + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.18.tgz", + "integrity": "sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw==", "dev": true, "license": "MIT", "dependencies": { - "tinyrainbow": "^1.2.0" + "tinyrainbow": "^3.0.3" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/runner": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.9.tgz", - "integrity": "sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==", + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.18.tgz", + "integrity": "sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "2.1.9", - "pathe": "^1.1.2" + "@vitest/utils": "4.0.18", + "pathe": "^2.0.3" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/snapshot": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.9.tgz", - "integrity": "sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==", + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.18.tgz", + "integrity": "sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.1.9", - "magic-string": "^0.30.12", - "pathe": "^1.1.2" + "@vitest/pretty-format": "4.0.18", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" }, "funding": { "url": "https://opencollective.com/vitest" @@ -9704,50 +9391,46 @@ } }, "node_modules/@vitest/spy": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.9.tgz", - "integrity": "sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==", + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.18.tgz", + "integrity": "sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw==", "dev": true, "license": "MIT", - "dependencies": { - "tinyspy": "^3.0.2" - }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/ui": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-2.1.9.tgz", - "integrity": "sha512-izzd2zmnk8Nl5ECYkW27328RbQ1nKvkm6Bb5DAaz1Gk59EbLkiCMa6OLT0NoaAYTjOFS6N+SMYW1nh4/9ljPiw==", + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-4.0.18.tgz", + "integrity": "sha512-CGJ25bc8fRi8Lod/3GHSvXRKi7nBo3kxh0ApW4yCjmrWmRmlT53B5E08XRSZRliygG0aVNxLrBEqPYdz/KcCtQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "2.1.9", + "@vitest/utils": "4.0.18", "fflate": "^0.8.2", - "flatted": "^3.3.1", - "pathe": "^1.1.2", - "sirv": "^3.0.0", - "tinyglobby": "^0.2.10", - "tinyrainbow": "^1.2.0" + "flatted": "^3.3.3", + "pathe": "^2.0.3", + "sirv": "^3.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.0.3" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "vitest": "2.1.9" + "vitest": "4.0.18" } }, "node_modules/@vitest/utils": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.9.tgz", - "integrity": "sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==", + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.18.tgz", + "integrity": "sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.1.9", - "loupe": "^3.1.2", - "tinyrainbow": "^1.2.0" + "@vitest/pretty-format": "4.0.18", + "tinyrainbow": "^3.0.3" }, "funding": { "url": "https://opencollective.com/vitest" @@ -12445,18 +12128,11 @@ } }, "node_modules/chai": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", - "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", "dev": true, "license": "MIT", - "dependencies": { - "assertion-error": "^2.0.1", - "check-error": "^2.1.1", - "deep-eql": "^5.0.1", - "loupe": "^3.1.0", - "pathval": "^2.0.0" - }, "engines": { "node": ">=18" } @@ -12529,16 +12205,6 @@ "version": "0.7.0", "license": "MIT" }, - "node_modules/check-error": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz", - "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 16" - } - }, "node_modules/chokidar": { "version": "3.6.0", "dev": true, @@ -13296,16 +12962,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/deep-eql": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", - "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -18503,13 +18159,6 @@ "loose-envify": "cli.js" } }, - "node_modules/loupe": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", - "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", - "dev": true, - "license": "MIT" - }, "node_modules/lower-case": { "version": "2.0.2", "license": "MIT", @@ -20113,6 +19762,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/obug": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", + "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT" + }, "node_modules/octokit": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/octokit/-/octokit-3.1.2.tgz", @@ -20672,20 +20332,12 @@ } }, "node_modules/pathe": { - "version": "1.1.2", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", "dev": true, "license": "MIT" }, - "node_modules/pathval": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", - "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.16" - } - }, "node_modules/pe-library": { "version": "1.0.1", "dev": true, @@ -20791,11 +20443,13 @@ } }, "node_modules/playwright": { - "version": "1.58.1", + "version": "1.58.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.58.2.tgz", + "integrity": "sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.58.1" + "playwright-core": "1.58.2" }, "bin": { "playwright": "cli.js" @@ -20808,7 +20462,9 @@ } }, "node_modules/playwright-core": { - "version": "1.58.1", + "version": "1.58.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.58.2.tgz", + "integrity": "sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==", "dev": true, "license": "Apache-2.0", "bin": { @@ -20820,7 +20476,10 @@ }, "node_modules/playwright/node_modules/fsevents": { "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, + "hasInstallScript": true, "license": "MIT", "optional": true, "os": [ @@ -23750,9 +23409,14 @@ "license": "MIT" }, "node_modules/tinyexec": { - "version": "0.3.2", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", + "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=18" + } }, "node_modules/tinyglobby": { "version": "0.2.15", @@ -23796,26 +23460,10 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/tinypool": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.0.0 || >=20.0.0" - } - }, "node_modules/tinyrainbow": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/tinyspy": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", - "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.0.3.tgz", + "integrity": "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==", "dev": true, "license": "MIT", "engines": { @@ -24816,145 +24464,6 @@ } } }, - "node_modules/vite-node": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.9.tgz", - "integrity": "sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==", - "dev": true, - "license": "MIT", - "dependencies": { - "cac": "^6.7.14", - "debug": "^4.3.7", - "es-module-lexer": "^1.5.4", - "pathe": "^1.1.2", - "vite": "^5.0.0" - }, - "bin": { - "vite-node": "vite-node.mjs" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/vite-node/node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, - "node_modules/vite-node/node_modules/vite": { - "version": "5.4.21", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", - "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, "node_modules/vite-plugin-static-copy": { "version": "3.2.0", "dev": true, @@ -25529,47 +25038,50 @@ } }, "node_modules/vitest": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.9.tgz", - "integrity": "sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/expect": "2.1.9", - "@vitest/mocker": "2.1.9", - "@vitest/pretty-format": "^2.1.9", - "@vitest/runner": "2.1.9", - "@vitest/snapshot": "2.1.9", - "@vitest/spy": "2.1.9", - "@vitest/utils": "2.1.9", - "chai": "^5.1.2", - "debug": "^4.3.7", - "expect-type": "^1.1.0", - "magic-string": "^0.30.12", - "pathe": "^1.1.2", - "std-env": "^3.8.0", + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.18.tgz", + "integrity": "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "4.0.18", + "@vitest/mocker": "4.0.18", + "@vitest/pretty-format": "4.0.18", + "@vitest/runner": "4.0.18", + "@vitest/snapshot": "4.0.18", + "@vitest/spy": "4.0.18", + "@vitest/utils": "4.0.18", + "es-module-lexer": "^1.7.0", + "expect-type": "^1.2.2", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^3.10.0", "tinybench": "^2.9.0", - "tinyexec": "^0.3.1", - "tinypool": "^1.0.1", - "tinyrainbow": "^1.2.0", - "vite": "^5.0.0", - "vite-node": "2.1.9", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.0.3", + "vite": "^6.0.0 || ^7.0.0", "why-is-node-running": "^2.3.0" }, "bin": { "vitest": "vitest.mjs" }, "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { "@edge-runtime/vm": "*", - "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "2.1.9", - "@vitest/ui": "2.1.9", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.0.18", + "@vitest/browser-preview": "4.0.18", + "@vitest/browser-webdriverio": "4.0.18", + "@vitest/ui": "4.0.18", "happy-dom": "*", "jsdom": "*" }, @@ -25577,106 +25089,32 @@ "@edge-runtime/vm": { "optional": true }, + "@opentelemetry/api": { + "optional": true + }, "@types/node": { "optional": true }, - "@vitest/browser": { + "@vitest/browser-playwright": { "optional": true }, - "@vitest/ui": { + "@vitest/browser-preview": { "optional": true }, - "happy-dom": { + "@vitest/browser-webdriverio": { "optional": true }, - "jsdom": { + "@vitest/ui": { "optional": true - } - } - }, - "node_modules/vitest/node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@vitest/mocker": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.9.tgz", - "integrity": "sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/spy": "2.1.9", - "estree-walker": "^3.0.3", - "magic-string": "^0.30.12" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "msw": "^2.4.9", - "vite": "^5.0.0" - }, - "peerDependenciesMeta": { - "msw": { + }, + "happy-dom": { "optional": true }, - "vite": { + "jsdom": { "optional": true } } }, - "node_modules/vitest/node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, "node_modules/vitest/node_modules/magic-string": { "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", @@ -25687,64 +25125,17 @@ "@jridgewell/sourcemap-codec": "^1.5.5" } }, - "node_modules/vitest/node_modules/vite": { - "version": "5.4.21", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", - "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", + "node_modules/vitest/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" - }, - "bin": { - "vite": "bin/vite.js" - }, "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": ">=12" }, "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } + "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/w3c-xmlserializer": { diff --git a/package.json b/package.json index 7bebd6956b..dd41ac0f0a 100644 --- a/package.json +++ b/package.json @@ -52,11 +52,11 @@ "@electron-forge/maker-zip": "^7.11.1", "@electron-forge/plugin-auto-unpack-natives": "^7.11.1", "@eslint/js": "^9.39.2", - "@playwright/test": "^1.58.1", + "@playwright/test": "^1.58.2", "@sentry/react": "^7.120.3", "@sentry/vite-plugin": "^4.3.0", "@testing-library/jest-dom": "^6.9.1", - "@testing-library/react": "^16.3.1", + "@testing-library/react": "^16.3.2", "@testing-library/user-event": "^14.6.1", "@types/archiver": "^6.0.4", "@types/follow-redirects": "^1.14.4", @@ -72,7 +72,7 @@ "@types/yargs": "^17.0.35", "@types/yauzl": "^2.10.3", "@vitejs/plugin-react": "^5.1.4", - "@vitest/ui": "^2.1.8", + "@vitest/ui": "^4.0.18", "@wordpress/components": "^32.1.0", "@wordpress/element": "^6.39.0", "@wordpress/react-i18n": "^4.39.0", @@ -106,7 +106,7 @@ "vite-plugin-static-copy": "^3.1.5", "vite-plugin-top-level-await": "^1.6.0", "vite-plugin-wasm": "^3.5.0", - "vitest": "^2.1.9", + "vitest": "^4.0.18", "web-streams-polyfill": "^4.2.0" }, "dependencies": { diff --git a/packages/eslint-plugin-studio/tests/require-lock-before-save.test.ts b/packages/eslint-plugin-studio/tests/require-lock-before-save.test.ts index c173288ef1..60394ed65d 100644 --- a/packages/eslint-plugin-studio/tests/require-lock-before-save.test.ts +++ b/packages/eslint-plugin-studio/tests/require-lock-before-save.test.ts @@ -1,5 +1,5 @@ import { RuleTester } from 'eslint'; -import { describe, it } from 'vitest'; +import { describe } from 'vitest'; import rule from '../src/rules/require-lock-before-save'; const ruleTester = new RuleTester( { @@ -10,8 +10,7 @@ const ruleTester = new RuleTester( { } ); describe( 'require-lock-before-save', () => { - it( 'should enforce locking when calling saveUserData or saveAppdata', () => { - ruleTester.run( 'require-lock-before-save', rule, { + ruleTester.run( 'require-lock-before-save', rule, { valid: [ // Functions not calling save functions (allowed) { @@ -106,5 +105,4 @@ describe( 'require-lock-before-save', () => { }, ], } ); - } ); } ); diff --git a/src/lib/deeplink/tests/add-site.test.ts b/src/lib/deeplink/tests/add-site.test.ts index e49a49e1a4..4ec959bb67 100644 --- a/src/lib/deeplink/tests/add-site.test.ts +++ b/src/lib/deeplink/tests/add-site.test.ts @@ -13,7 +13,7 @@ vi.mock( 'src/ipc-utils' ); vi.mock( 'src/lib/download' ); vi.mock( 'src/main-window' ); vi.mock( 'src/logging', () => ( { - getLogsFilePath: vi.fn( () => '/mock/path/to/logs.log' ), + getLogsFilePath: vi.fn().mockReturnValue( '/mock/path/to/logs.log' ), } ) ); vi.mock( 'common/lib/blueprint-validation', () => ( { validateBlueprintData: vi.fn(), diff --git a/src/lib/import-export/tests/export/export-manager.test.ts b/src/lib/import-export/tests/export/export-manager.test.ts index 9409be0f70..f2bfd66f4e 100644 --- a/src/lib/import-export/tests/export/export-manager.test.ts +++ b/src/lib/import-export/tests/export/export-manager.test.ts @@ -13,81 +13,75 @@ describe( 'exportBackup', () => { const mockExport = vi.fn(); const mockCanHandle = vi.fn().mockResolvedValue( true ); - const MockExporter1 = vi.fn().mockImplementation( () => ( { - canHandle: mockCanHandle, - export: mockExport, - on: vi.fn(), - emit: vi.fn(), - } ) ); + class MockExporter1 { + canHandle = mockCanHandle; + export = mockExport; + on = vi.fn(); + emit = vi.fn(); + } - const MockExporter2 = vi.fn().mockImplementation( () => ( { - canHandle: mockCanHandle, - export: mockExport, - on: vi.fn(), - emit: vi.fn(), - } ) ); + class MockExporter2 { + canHandle = mockCanHandle; + export = mockExport; + on = vi.fn(); + emit = vi.fn(); + } const exporters: NewExporter[] = [ MockExporter1, MockExporter2 ]; const result = await exportBackup( mockExportOptions, vi.fn(), exporters ); expect( result ).toBeTruthy(); - expect( MockExporter1 ).toHaveBeenCalledWith( mockExportOptions ); expect( mockCanHandle ).toHaveBeenCalled(); expect( mockExport ).toHaveBeenCalled(); - expect( MockExporter2 ).not.toHaveBeenCalled(); } ); it( 'should call the second exporter if first exporter can not handle export', async () => { const ExportMethod1 = vi.fn(); - const MockExporter1 = vi.fn().mockImplementation( () => ( { - canHandle: vi.fn().mockResolvedValue( false ), - export: ExportMethod1, - on: vi.fn(), - emit: vi.fn(), - } ) ); + class MockExporter1 { + canHandle = vi.fn().mockResolvedValue( false ); + export = ExportMethod1; + on = vi.fn(); + emit = vi.fn(); + } const ExportMethod2 = vi.fn(); - const MockExporter2 = vi.fn().mockImplementation( () => ( { - canHandle: vi.fn().mockResolvedValue( true ), - export: ExportMethod2, - on: vi.fn(), - emit: vi.fn(), - } ) ); + class MockExporter2 { + canHandle = vi.fn().mockResolvedValue( true ); + export = ExportMethod2; + on = vi.fn(); + emit = vi.fn(); + } const exporters: NewExporter[] = [ MockExporter1, MockExporter2 ]; const result = await exportBackup( mockExportOptions, vi.fn(), exporters ); expect( result ).toBeTruthy(); - expect( MockExporter1 ).toHaveBeenCalledWith( mockExportOptions ); expect( ExportMethod1 ).not.toHaveBeenCalled(); - expect( MockExporter2 ).toHaveBeenCalledWith( mockExportOptions ); expect( ExportMethod2 ).toHaveBeenCalled(); } ); it( 'returns false if no exporter is found', async () => { const ExportMethod1 = vi.fn(); - const MockExporter1 = vi.fn( () => ( { - canHandle: vi.fn().mockResolvedValue( false ), - export: ExportMethod1, - on: vi.fn(), - emit: vi.fn(), - } ) ); + class MockExporter1 { + canHandle = vi.fn().mockResolvedValue( false ); + export = ExportMethod1; + on = vi.fn(); + emit = vi.fn(); + } const ExportMethod2 = vi.fn(); - const MockExporter2 = vi.fn( () => ( { - canHandle: vi.fn().mockResolvedValue( false ), - export: ExportMethod2, - on: vi.fn(), - emit: vi.fn(), - } ) ); + class MockExporter2 { + canHandle = vi.fn().mockResolvedValue( false ); + export = ExportMethod2; + on = vi.fn(); + emit = vi.fn(); + } const exporters: NewExporter[] = [ MockExporter1, MockExporter2 ]; const result = await exportBackup( mockExportOptions, vi.fn(), exporters ); expect( result ).toBeFalsy(); - expect( MockExporter1 ).toHaveBeenCalledWith( mockExportOptions ); expect( ExportMethod1 ).not.toHaveBeenCalled(); - expect( MockExporter2 ).toHaveBeenCalledWith( mockExportOptions ); expect( ExportMethod2 ).not.toHaveBeenCalled(); } ); } ); diff --git a/src/lib/import-export/tests/export/exporters/default-exporter.test.ts b/src/lib/import-export/tests/export/exporters/default-exporter.test.ts index 329a23ebdb..a3f87fde62 100644 --- a/src/lib/import-export/tests/export/exporters/default-exporter.test.ts +++ b/src/lib/import-export/tests/export/exporters/default-exporter.test.ts @@ -15,9 +15,34 @@ import { import { SiteServer } from 'src/site-server'; import { platformTestSuite } from 'src/tests/utils/platform-test-suite'; -vi.mock( 'fs' ); -vi.mock( 'fs/promises' ); -vi.mock( 'os' ); +vi.mock( 'fs', () => ( { + default: { + existsSync: vi.fn(), + statSync: vi.fn(), + readFileSync: vi.fn(), + createWriteStream: vi.fn(), + writeFileSync: vi.fn(), + readdirSync: vi.fn(), + }, +} ) ); +vi.mock( 'fs/promises', () => ( { + default: { + readdir: vi.fn(), + readFile: vi.fn(), + writeFile: vi.fn(), + mkdir: vi.fn(), + mkdtemp: vi.fn(), + copyFile: vi.fn(), + rm: vi.fn(), + stat: vi.fn(), + unlink: vi.fn(), + }, +} ) ); +vi.mock( 'os', () => ( { + default: { + tmpdir: vi.fn(), + }, +} ) ); vi.mock( 'fs-extra' ); vi.mock( 'date-fns', () => ( { format: vi.fn(), @@ -50,7 +75,7 @@ const createMockArchiver = (): { // Mock archiver module vi.mock( 'archiver', () => { - return { default: vi.fn( () => createMockArchiver() ) }; + return { default: vi.fn().mockImplementation( () => createMockArchiver() ) }; } ); // Mock SiteServer @@ -240,7 +265,7 @@ platformTestSuite( 'DefaultExporter', ( { normalize } ) => { phpVersion: '8.0', running: false, }, - executeWpCliCommand: vi.fn( function ( command: string ) { + executeWpCliCommand: vi.fn().mockImplementation( function ( command: string ) { switch ( true ) { case /plugin list/.test( command ): return Promise.resolve( { @@ -550,7 +575,7 @@ platformTestSuite( 'DefaultExporter', ( { normalize } ) => { phpVersion: '8.0', running: false, }, - executeWpCliCommand: vi.fn( function ( command: string ) { + executeWpCliCommand: vi.fn().mockImplementation( function ( command: string ) { switch ( true ) { case /plugin list/.test( command ): case /theme list/.test( command ): diff --git a/src/lib/import-export/tests/import/handlers/backup-handler.test.ts b/src/lib/import-export/tests/import/handlers/backup-handler.test.ts index 078c81c8e6..8a518e80d9 100644 --- a/src/lib/import-export/tests/import/handlers/backup-handler.test.ts +++ b/src/lib/import-export/tests/import/handlers/backup-handler.test.ts @@ -202,7 +202,7 @@ describe( 'BackupHandlerFactory', () => { const extractionDirectory = '/tmp/extracted'; const createReadStreamMock: Partial< fs.ReadStream > = { - on: vi.fn( ( event, callback ) => { + on: vi.fn().mockImplementation( ( event, callback ) => { if ( event === 'finish' ) { callback(); } diff --git a/src/lib/import-export/tests/import/import-manager.test.ts b/src/lib/import-export/tests/import/import-manager.test.ts index 9c1d11c485..1eaf737251 100644 --- a/src/lib/import-export/tests/import/import-manager.test.ts +++ b/src/lib/import-export/tests/import/import-manager.test.ts @@ -20,9 +20,23 @@ vi.mock( 'src/storage/paths', () => ( { .mockReturnValue( '/path/to/app/appData/App Name/appdata-v1.json.lock' ), } ) ); vi.mock( 'src/lib/import-export/import/handlers/backup-handler-factory' ); -vi.mock( 'fs/promises' ); -vi.mock( 'os' ); -vi.mock( 'path' ); +vi.mock( 'fs/promises', () => ( { + default: { + mkdtemp: vi.fn(), + stat: vi.fn(), + rm: vi.fn(), + }, +} ) ); +vi.mock( 'os', () => ( { + default: { + tmpdir: vi.fn(), + }, +} ) ); +vi.mock( 'path', () => ( { + default: { + join: vi.fn(), + }, +} ) ); describe( 'importManager', () => { describe( 'selectImporter', () => { @@ -112,7 +126,11 @@ describe( 'importManager', () => { on: vi.fn(), emit: vi.fn(), }; - const MockImporterClass = vi.fn().mockImplementation( () => mockImporter ); + class MockImporterClass { + import = mockImporter.import; + on = mockImporter.on; + emit = mockImporter.emit; + } const mockBackupHandler = { listFiles: vi.fn().mockResolvedValue( [ 'file1.txt', 'file2.txt' ] ), diff --git a/src/lib/import-export/tests/import/importer/jetpack-importer.test.ts b/src/lib/import-export/tests/import/importer/jetpack-importer.test.ts index a2a51b0200..b5fc6161d8 100644 --- a/src/lib/import-export/tests/import/importer/jetpack-importer.test.ts +++ b/src/lib/import-export/tests/import/importer/jetpack-importer.test.ts @@ -6,7 +6,20 @@ import { BackupContents } from 'src/lib/import-export/import/types'; import { SiteServer } from 'src/site-server'; import { platformTestSuite } from 'src/tests/utils/platform-test-suite'; -vi.mock( 'fs/promises' ); +vi.mock( 'fs/promises', () => { + const mockFns = { + mkdir: vi.fn(), + copyFile: vi.fn(), + writeFile: vi.fn(), + readFile: vi.fn(), + readdir: vi.fn(), + rm: vi.fn(), + }; + return { + default: mockFns, + ...mockFns, + }; +} ); vi.mock( 'src/site-server' ); vi.mock( 'fs-extra', () => ( { lstat: vi.fn(), @@ -46,13 +59,15 @@ platformTestSuite( 'JetpackImporter', ( { normalize } ) => { phpVersion: '8.0', running: false, }, - executeWpCliCommand: vi.fn( ( command: string ) => - Promise.resolve( - command === 'option get siteurl' - ? { stdout: 'http://localhost:8881', stderr: '', exitCode: 0 } - : { stdout: '', stderr: '', exitCode: 0 } - ) - ), + executeWpCliCommand: vi + .fn() + .mockImplementation( ( command: string ) => + Promise.resolve( + command === 'option get siteurl' + ? { stdout: 'http://localhost:8881', stderr: '', exitCode: 0 } + : { stdout: '', stderr: '', exitCode: 0 } + ) + ), } ); // mock move diff --git a/src/lib/import-export/tests/import/importer/local-importer.test.ts b/src/lib/import-export/tests/import/importer/local-importer.test.ts index ed8ab77018..78ff6f9f31 100644 --- a/src/lib/import-export/tests/import/importer/local-importer.test.ts +++ b/src/lib/import-export/tests/import/importer/local-importer.test.ts @@ -6,7 +6,20 @@ import { BackupContents } from 'src/lib/import-export/import/types'; import { SiteServer } from 'src/site-server'; import { platformTestSuite } from 'src/tests/utils/platform-test-suite'; -vi.mock( 'fs/promises' ); +vi.mock( 'fs/promises', () => { + const mockFns = { + mkdir: vi.fn(), + copyFile: vi.fn(), + writeFile: vi.fn(), + readFile: vi.fn(), + readdir: vi.fn(), + rm: vi.fn(), + }; + return { + default: mockFns, + ...mockFns, + }; +} ); vi.mock( 'src/site-server' ); vi.mock( 'fs-extra', () => ( { lstat: vi.fn(), @@ -46,13 +59,15 @@ platformTestSuite( 'LocalImporter', ( { normalize } ) => { phpVersion: '8.0', running: false, }, - executeWpCliCommand: vi.fn( ( command: string ) => - Promise.resolve( - command === 'option get siteurl' - ? { stdout: 'http://localhost:8881', stderr: '', exitCode: 0 } - : { stdout: '', stderr: '', exitCode: 0 } - ) - ), + executeWpCliCommand: vi + .fn() + .mockImplementation( ( command: string ) => + Promise.resolve( + command === 'option get siteurl' + ? { stdout: 'http://localhost:8881', stderr: '', exitCode: 0 } + : { stdout: '', stderr: '', exitCode: 0 } + ) + ), } ); // mock move diff --git a/src/lib/import-export/tests/import/importer/playground-importer.test.ts b/src/lib/import-export/tests/import/importer/playground-importer.test.ts index ea1b7b8471..e3bac649e7 100644 --- a/src/lib/import-export/tests/import/importer/playground-importer.test.ts +++ b/src/lib/import-export/tests/import/importer/playground-importer.test.ts @@ -6,7 +6,20 @@ import { BackupContents } from 'src/lib/import-export/import/types'; import { SiteServer } from 'src/site-server'; import { platformTestSuite } from 'src/tests/utils/platform-test-suite'; -vi.mock( 'fs/promises' ); +vi.mock( 'fs/promises', () => { + const mockFns = { + mkdir: vi.fn(), + copyFile: vi.fn(), + writeFile: vi.fn(), + readFile: vi.fn(), + readdir: vi.fn(), + rm: vi.fn(), + }; + return { + default: mockFns, + ...mockFns, + }; +} ); vi.mock( 'src/site-server' ); vi.mock( 'fs-extra', () => ( { lstat: vi.fn(), @@ -42,13 +55,15 @@ platformTestSuite( 'PlaygroundImporter', ( { normalize } ) => { phpVersion: '8.0', running: false, }, - executeWpCliCommand: vi.fn( ( command: string ) => - Promise.resolve( - command === 'option get siteurl' - ? { stdout: 'http://localhost:8881', stderr: '', exitCode: 0 } - : { stdout: '', stderr: '', exitCode: 0 } - ) - ), + executeWpCliCommand: vi + .fn() + .mockImplementation( ( command: string ) => + Promise.resolve( + command === 'option get siteurl' + ? { stdout: 'http://localhost:8881', stderr: '', exitCode: 0 } + : { stdout: '', stderr: '', exitCode: 0 } + ) + ), } ); // mock move diff --git a/src/lib/tests/hosts-file.test.ts b/src/lib/tests/hosts-file.test.ts index eec4d5e895..53d6a6cc02 100644 --- a/src/lib/tests/hosts-file.test.ts +++ b/src/lib/tests/hosts-file.test.ts @@ -10,10 +10,10 @@ import { const readFileCallbackMock = vi.fn(); vi.mock( 'fs', () => { - const mockReadFile = vi.fn( ( path, encoding, callback ) => { + const mockReadFile = vi.fn().mockImplementation( ( path, encoding, callback ) => { callback( null, readFileCallbackMock() ); } ); - const mockWriteFile = vi.fn( ( path, data, callback ) => { + const mockWriteFile = vi.fn().mockImplementation( ( path, data, callback ) => { callback( null ); } ); @@ -28,7 +28,7 @@ vi.mock( 'fs', () => { } ); vi.mock( '@vscode/sudo-prompt', () => { - const mockExec = vi.fn( ( command, options, callback ) => { + const mockExec = vi.fn().mockImplementation( ( command, options, callback ) => { callback( null, 'Mocked output' ); } ); return { diff --git a/src/lib/tests/windows-helpers.test.ts b/src/lib/tests/windows-helpers.test.ts index 9a84854cd5..0c59088a52 100644 --- a/src/lib/tests/windows-helpers.test.ts +++ b/src/lib/tests/windows-helpers.test.ts @@ -27,7 +27,7 @@ vi.mock( 'electron', async () => { }; } ); vi.mock( '@vscode/sudo-prompt', () => ( { - exec: vi.fn( ( _command, _options, callback ) => { + exec: vi.fn().mockImplementation( ( _command, _options, callback ) => { callback( null ); } ), } ) ); diff --git a/src/stores/tests/installed-apps-api.test.ts b/src/stores/tests/installed-apps-api.test.ts index 7a728cc569..83f75c393f 100644 --- a/src/stores/tests/installed-apps-api.test.ts +++ b/src/stores/tests/installed-apps-api.test.ts @@ -14,9 +14,9 @@ vi.mock( 'src/lib/get-ipc-api', () => ( { } ) ); vi.mock( 'src/lib/app-globals', () => ( { - getAppGlobals: vi.fn( () => ( { + getAppGlobals: vi.fn().mockReturnValue( { platform: 'darwin', - } ) ), + } ), } ) ); const mockIpcApi = { diff --git a/src/tests/execute-wp-cli.test.ts b/src/tests/execute-wp-cli.test.ts index 9bc8fcf1ae..347550b494 100644 --- a/src/tests/execute-wp-cli.test.ts +++ b/src/tests/execute-wp-cli.test.ts @@ -2,10 +2,8 @@ import { ChildProcess } from 'node:child_process'; import EventEmitter from 'node:events'; import { vi } from 'vitest'; // Mock executeCliCommand before importing SiteServer -const mockEventEmitter = new EventEmitter(); -const mockChildProcess = { kill: vi.fn() } as unknown as ChildProcess; vi.mock( 'src/modules/cli/lib/execute-command', () => ( { - executeCliCommand: vi.fn( () => [ mockEventEmitter, mockChildProcess ] ), + executeCliCommand: vi.fn().mockReturnValue( [ new EventEmitter(), { kill: vi.fn() } ] ), } ) ); vi.mock( 'src/constants', () => ( { WP_CLI_DEFAULT_RESPONSE_TIMEOUT: 100, // Short timeout for tests @@ -18,6 +16,8 @@ import { executeCliCommand } from 'src/modules/cli/lib/execute-command'; import type { CliCommandResult } from 'src/modules/cli/lib/execute-command'; const mockExecuteCliCommand = vi.mocked( executeCliCommand ); +const mockEventEmitter = new EventEmitter(); +const mockChildProcess = { kill: vi.fn() } as unknown as ChildProcess; function simulateCliResponse( { stdout = '', @@ -33,6 +33,7 @@ function simulateCliResponse( { const payload: { result: CliCommandResult } = { result: { stdout, stderr }, }; + // Use the mockEventEmitter directly mockEventEmitter.emit( exitCode === 0 ? 'success' : 'failure', payload ); } ); } diff --git a/src/tests/index.test.ts b/src/tests/index.test.ts index e0cb403f8a..4f4364d231 100644 --- a/src/tests/index.test.ts +++ b/src/tests/index.test.ts @@ -19,12 +19,12 @@ vi.mock( '@sentry/electron/main', () => ( { } ) ); vi.mock( 'common/lib/bump-stat', () => ( { bumpStat: vi.fn(), - bumpAggregatedUniqueStat: vi.fn( () => Promise.resolve() ), + bumpAggregatedUniqueStat: vi.fn().mockResolvedValue( undefined ), } ) ); vi.mock( 'src/lib/user-data-watcher' ); vi.mock( 'src/setup-wp-server-files', () => ( { - setupWPServerFiles: vi.fn( () => Promise.resolve() ), - updateWPServerFiles: vi.fn( () => Promise.resolve() ), + setupWPServerFiles: vi.fn().mockResolvedValue( undefined ), + updateWPServerFiles: vi.fn().mockResolvedValue( undefined ), } ) ); vi.mock( 'atomically', () => ( { readFile: vi.fn().mockResolvedValue( Buffer.from( JSON.stringify( { sites: [] } ) ) ), @@ -63,10 +63,10 @@ vi.mock( 'src/modules/cli/lib/execute-command', () => { }; } ); vi.mock( 'src/modules/cli/lib/windows-installation-manager', () => ( { - updateWindowsCliVersionedPathIfNeeded: vi.fn().mockReturnValue( Promise.resolve() ), + updateWindowsCliVersionedPathIfNeeded: vi.fn().mockResolvedValue( undefined ), } ) ); vi.mock( 'electron-devtools-installer', () => ( { - installExtension: vi.fn( () => Promise.resolve( { id: 'test-extension' } ) ), + installExtension: vi.fn().mockResolvedValue( { id: 'test-extension' } ), REACT_DEVELOPER_TOOLS: { id: 'fmkadmapgofadopljbjfkapdkoienihi' }, REDUX_DEVTOOLS: { id: 'lmhkpmbekcpmknklioeibfkpmmfibljd' }, } ) ); @@ -89,12 +89,12 @@ function mockElectron() { vi.doMock( 'electron', () => { return { app: { - on: vi.fn( ( event, callback ) => { + on: vi.fn().mockImplementation( ( event, callback ) => { mockedEvents[ event ] = callback; } ), off: vi.fn(), getVersion: vi.fn().mockReturnValue( '1.0.0' ), - getPath: vi.fn( ( name: string ) => { + getPath: vi.fn().mockImplementation( ( name: string ) => { switch ( name ) { case 'home': return '/mock/home/path'; @@ -236,7 +236,7 @@ describe( 'App initialization', () => { it( 'should wait app initialization before creating main window via second-instance event', async () => { vi.mocked( getMainWindow, { partial: true } ).mockResolvedValue( { focus: vi.fn(), - isMinimized: vi.fn( () => false ), + isMinimized: vi.fn().mockReturnValue( false ), } ); const { mockedEvents } = mockElectron(); diff --git a/src/tests/ipc-handlers.test.ts b/src/tests/ipc-handlers.test.ts index 1850da8863..94017561e4 100644 --- a/src/tests/ipc-handlers.test.ts +++ b/src/tests/ipc-handlers.test.ts @@ -75,7 +75,7 @@ vi.mocked( SiteServer.create ).mockResolvedValue( { start: vi.fn(), details: mockSiteDetails, updateSiteDetails: vi.fn(), - updateCachedThumbnail: vi.fn( () => Promise.resolve() ), + updateCachedThumbnail: vi.fn().mockResolvedValue( undefined ), } as unknown as SiteServer, details: mockSiteDetails, } ); @@ -84,7 +84,7 @@ vi.mocked( SiteServer.register, { partial: true } ).mockImplementation( ( detail start: vi.fn(), details, updateSiteDetails: vi.fn(), - updateCachedThumbnail: vi.fn( () => Promise.resolve() ), + updateCachedThumbnail: vi.fn().mockResolvedValue( undefined ), } ) ); const mockUserData = { @@ -101,7 +101,7 @@ if ( '__setFileContents' in fs ) { vi.mocked( readFile ).mockResolvedValue( Buffer.from( JSON.stringify( mockUserData ) ) ); const mockIpcMainInvokeEvent = { - sender: { isDestroyed: vi.fn( () => false ) }, + sender: { isDestroyed: vi.fn().mockReturnValue( false ) }, // Double assert the type with `unknown` to simplify mocking this value } as unknown as IpcMainInvokeEvent; diff --git a/src/tests/main-window.test.ts b/src/tests/main-window.test.ts index ec30744b1f..f0119b3bb8 100644 --- a/src/tests/main-window.test.ts +++ b/src/tests/main-window.test.ts @@ -32,7 +32,7 @@ const mockEventHandlers = new Map< string, ( ( ...args: any[] ) => void )[] >(); vi.mock( 'electron', () => { class MockBrowserWindow { - static fromWebContents = vi.fn( () => new MockBrowserWindow() ); + static fromWebContents = vi.fn().mockImplementation( () => new MockBrowserWindow() ); static getFocusedWindow = vi.fn(); static getAllWindows = vi.fn().mockReturnValue( [] ); @@ -43,7 +43,7 @@ vi.mock( 'electron', () => { setBackgroundColor = vi.fn(); getBounds = vi.fn().mockReturnValue( { x: 0, y: 0, width: 800, height: 600 } ); - on = vi.fn( ( event: string, handler: ( ...args: any[] ) => void ) => { + on = vi.fn().mockImplementation( ( event: string, handler: ( ...args: any[] ) => void ) => { if ( ! mockEventHandlers.has( event ) ) { mockEventHandlers.set( event, [] ); } @@ -53,7 +53,7 @@ vi.mock( 'electron', () => { webContents = { isDestroyed: vi.fn().mockReturnValue( false ), send: vi.fn(), - on: vi.fn( ( event: string, handler: ( ...args: any[] ) => void ) => { + on: vi.fn().mockImplementation( ( event: string, handler: ( ...args: any[] ) => void ) => { if ( event === 'did-finish-load' ) { // Call handler immediately to resolve window creation setImmediate( handler ); diff --git a/src/tests/show-site-context-menu.test.ts b/src/tests/show-site-context-menu.test.ts index 527d05425c..86137d1aea 100644 --- a/src/tests/show-site-context-menu.test.ts +++ b/src/tests/show-site-context-menu.test.ts @@ -1,39 +1,69 @@ /** * @vitest-environment node */ -import { IpcMainInvokeEvent, BrowserWindow, Menu, MenuItem } from 'electron'; +import { IpcMainInvokeEvent, BrowserWindow, MenuItem } from 'electron'; import { vi } from 'vitest'; import { showSiteContextMenu } from 'src/ipc-handlers'; import { sendIpcEventToRendererWithWindow } from 'src/ipc-utils'; +// Track menu items and menu instance +let menuItems: MenuItem[] = []; +let mockMenu: { + append: ReturnType< typeof vi.fn >; + popup: ReturnType< typeof vi.fn >; +}; + +vi.mock( 'electron', () => { + class MockMenu { + append = vi.fn().mockImplementation( ( item: MenuItem ) => menuItems.push( item ) ); + popup = vi.fn(); + + constructor() { + // Store the instance in the outer mockMenu variable + // eslint-disable-next-line @typescript-eslint/no-this-alias + mockMenu = this; + } + } + + class MockMenuItem { + constructor( config: Record< string, unknown > ) { + Object.assign( this, config ); + } + } + + class MockBrowserWindow { + static fromWebContents = vi.fn(); + isDestroyed = vi.fn().mockReturnValue( false ); + } + + return { + Menu: MockMenu, + MenuItem: MockMenuItem, + BrowserWindow: MockBrowserWindow, + app: { + getPath: vi.fn().mockReturnValue( '/mock/app/path' ), + }, + }; +} ); + vi.mock( 'src/ipc-utils' ); vi.mock( 'fs' ); const mockIpcMainInvokeEvent = { - sender: { isDestroyed: vi.fn( () => false ) }, + sender: { isDestroyed: vi.fn().mockReturnValue( false ) }, // Double assert the type with `unknown` to simplify mocking this value } as unknown as IpcMainInvokeEvent; describe( 'showSiteContextMenu', () => { - let mockMenu: Partial< Menu >; let mockWindow: Partial< BrowserWindow >; - let menuItems: MenuItem[]; beforeEach( () => { vi.clearAllMocks(); menuItems = []; - mockMenu = { - append: vi.fn( ( item: MenuItem ) => menuItems.push( item ) ), - popup: vi.fn(), - }; mockWindow = { - isDestroyed: vi.fn( () => false ), + isDestroyed: vi.fn().mockReturnValue( false ), }; - vi.mocked( Menu, { partial: true } ).mockImplementation( () => mockMenu as Menu ); - vi.mocked( MenuItem, { partial: true } ).mockImplementation( - ( config ) => config as unknown as MenuItem - ); vi.mocked( BrowserWindow.fromWebContents, { partial: true } ).mockReturnValue( mockWindow as BrowserWindow ); diff --git a/src/tests/site-server.test.ts b/src/tests/site-server.test.ts index c65edb07dc..ef7250dfae 100644 --- a/src/tests/site-server.test.ts +++ b/src/tests/site-server.test.ts @@ -18,77 +18,77 @@ vi.mock( 'src/lib/wordpress-setup', () => ( { } ) ); // Mock the WordPress provider +const mockStartServer = vi.fn().mockResolvedValue( { + url: 'http://localhost:1234', + options: { port: 1234, phpVersion: '8.0' }, + _internal: { mode: 'wordpress', port: 1234 }, +} ); + vi.mock( 'src/lib/wordpress-provider', () => { const mockProvider = { DEFAULT_PHP_VERSION: '8.0', DEFAULT_WORDPRESS_VERSION: 'latest', ALLOWED_PHP_VERSIONS: [ '8.0', '8.1', '8.2', '8.3' ], SQLITE_FILENAME: 'sqlite-database-integration', - getWordPressVersionPath: vi.fn( ( version ) => `/mock/path/to/wp-${ version }` ), - getSqlitePath: vi.fn( () => '/mock/path/to/sqlite' ), - getWpCliPath: vi.fn( () => '/mock/path/to/wp-cli' ), - getWpCliFolderPath: vi.fn( () => '/mock/path/to/wp-cli-folder' ), + getWordPressVersionPath: vi + .fn() + .mockImplementation( ( version ) => `/mock/path/to/wp-${ version }` ), + getSqlitePath: vi.fn().mockReturnValue( '/mock/path/to/sqlite' ), + getWpCliPath: vi.fn().mockReturnValue( '/mock/path/to/wp-cli' ), + getWpCliFolderPath: vi.fn().mockReturnValue( '/mock/path/to/wp-cli-folder' ), downloadWordPress: vi.fn(), downloadWpCli: vi.fn(), downloadSQLiteCommand: vi.fn(), - setupWordPressSite: vi.fn( () => Promise.resolve( true ) ), - startServer: vi.fn( () => - Promise.resolve( { - url: 'http://localhost:1234', - options: { port: 1234, phpVersion: '8.0' }, - _internal: { mode: 'wordpress', port: 1234 }, - } ) - ), - createServerProcess: vi.fn( () => ( { + setupWordPressSite: vi.fn().mockResolvedValue( true ), + startServer: mockStartServer, + createServerProcess: vi.fn().mockReturnValue( { url: 'http://localhost:1234', php: {}, - start: vi.fn( () => Promise.resolve() ), - stop: vi.fn( () => Promise.resolve() ), - runPhp: vi.fn( () => Promise.resolve( '' ) ), - } ) ), + start: vi.fn().mockResolvedValue( undefined ), + stop: vi.fn().mockResolvedValue( undefined ), + runPhp: vi.fn().mockResolvedValue( '' ), + } ), executeWPCli: vi.fn(), - isValidWordPressVersion: vi.fn( () => true ), - getConfig: vi.fn( () => Promise.resolve( {} ) ), + isValidWordPressVersion: vi.fn().mockReturnValue( true ), + getConfig: vi.fn().mockResolvedValue( {} ), }; return { ...mockProvider, - getWordPressProvider: vi.fn( () => mockProvider ), + getWordPressProvider: vi.fn().mockReturnValue( mockProvider ), }; } ); // Mock the wp-now config that the provider uses internally - +const mockGetWpNowConfig = vi.fn().mockReturnValue( { mode: 'wordpress', port: 1234 } ); vi.mock( 'vendor/wp-now/src', () => ( { - getWpNowConfig: vi.fn( () => ( { mode: 'wordpress', port: 1234 } ) ), + getWpNowConfig: mockGetWpNowConfig, } ) ); // Mock CliServerProcess with a start method that calls startServer -vi.mock( 'src/modules/cli/lib/cli-server-process', () => ( { - CliServerProcess: vi.fn().mockImplementation( () => ( { - url: 'http://localhost:1234', - start: vi.fn( async () => { - // eslint-disable-next-line import/no-unresolved - const { startServer } = await import( 'src/lib/wordpress-provider' ); - return startServer(); - } ), - stop: vi.fn(), - delete: vi.fn(), - } ) ), -} ) ); +vi.mock( 'src/modules/cli/lib/cli-server-process', () => { + class MockCliServerProcess { + url = 'http://localhost:1234'; + start = vi.fn().mockImplementation( async () => { + return mockStartServer(); + } ); + stop = vi.fn(); + delete = vi.fn(); + } + + return { + CliServerProcess: MockCliServerProcess, + }; +} ); vi.mock( 'src/storage/user-data' ); describe( 'SiteServer', () => { describe( 'start', () => { it( 'should throw if the server starts with a non-WordPress mode', async () => { - // eslint-disable-next-line import/no-unresolved - const { getWpNowConfig } = await import( 'vendor/wp-now/src' ); - vi.mocked( getWpNowConfig ).mockReturnValue( { mode: 'theme', port: 1234 } ); + mockGetWpNowConfig.mockReturnValue( { mode: 'theme', port: 1234 } ); - // eslint-disable-next-line import/no-unresolved - const { startServer } = await import( 'src/lib/wordpress-provider' ); - vi.mocked( startServer ).mockRejectedValue( + mockStartServer.mockRejectedValue( new Error( "Site server started with Playground's 'theme' mode. Studio only supports 'wordpress' mode." ) diff --git a/vitest.config.mts b/vitest.config.mts index 2fd0b146e1..831dffe7fe 100644 --- a/vitest.config.mts +++ b/vitest.config.mts @@ -4,6 +4,8 @@ import path from 'path'; export default defineConfig( { test: { pool: 'threads', + maxThreads: 8, + minThreads: 1, globals: true, environment: 'jsdom', environmentOptions: { @@ -29,12 +31,6 @@ export default defineConfig( { external: [ 'electron' ], }, }, - poolOptions: { - threads: { - maxThreads: 8, - minThreads: 1, - }, - }, css: false, }, resolve: {