From 22edd8a72c6010ce2be5f89fddbb1aee792746c8 Mon Sep 17 00:00:00 2001 From: axel7083 <42176370+axel7083@users.noreply.github.com> Date: Tue, 21 Apr 2026 09:24:57 +0200 Subject: [PATCH] chore(main): prefer-import-in-mock (#17133) * chore(main): prefer-import-in-mock Signed-off-by: axel7083 <42176370+axel7083@users.noreply.github.com> * fix: type issue Signed-off-by: axel7083 <42176370+axel7083@users.noreply.github.com> --------- Signed-off-by: axel7083 <42176370+axel7083@users.noreply.github.com> --- .../main/src/application-menu-builder.spec.ts | 7 +- packages/main/src/electron-util.spec.ts | 5 +- packages/main/src/index.spec.ts | 12 +-- packages/main/src/main.spec.ts | 6 +- packages/main/src/mainWindow.spec.ts | 5 +- .../app-ready/default-protocol-client.spec.ts | 2 +- .../main/src/plugin/appearance-init.spec.ts | 5 +- packages/main/src/plugin/certificate.spec.ts | 10 +-- .../main/src/plugin/close-behavior.spec.ts | 2 +- .../src/plugin/configuration-registry.spec.ts | 74 ++++++++++--------- .../main/src/plugin/configuration-registry.ts | 2 +- .../src/plugin/container-registry.spec.ts | 17 +---- .../src/plugin/contribution-manager.spec.ts | 29 ++------ .../src/plugin/default-configuration.spec.ts | 2 +- .../main/src/plugin/dialog-registry.spec.ts | 4 +- .../src/plugin/directories-legacy.spec.ts | 2 +- .../docker-desktop-installation.spec.ts | 2 +- .../docker-desktop-installer.spec.ts | 2 +- .../docker-plugin-adapter.spec.ts | 5 +- .../docker/docker-compatibility.spec.ts | 9 ++- ...erimental-feature-feedback-handler.spec.ts | 15 ++-- .../explore-features/explore-features.spec.ts | 16 ++-- .../extension/extension-analyzer.spec.ts | 12 +-- .../plugin/extension/extension-loader.spec.ts | 12 +-- .../extension-tsconfig-parser.spec.ts | 4 +- .../extension/extension-watcher.spec.ts | 2 +- .../main/src/plugin/feedback-handler.spec.ts | 18 +++-- .../main/src/plugin/image-registry.spec.ts | 4 +- packages/main/src/plugin/index.spec.ts | 4 +- .../kubernetes/contexts-manager.spec.ts | 7 +- ...kubernetes-port-forward-connection.spec.ts | 31 +++----- .../kubernetes-port-forward-connection.ts | 7 +- .../kubernetes-port-forward-service.spec.ts | 12 +-- .../kubernetes-port-forward-storage.spec.ts | 2 +- .../src/plugin/locked-configuration.spec.ts | 2 +- .../src/plugin/onboarding-registry.spec.ts | 2 +- packages/main/src/plugin/podman/kube.spec.ts | 6 +- .../main/src/plugin/proxy-resolver.spec.ts | 17 ++--- packages/main/src/plugin/proxy.spec.ts | 4 +- .../recommendations-registry.spec.ts | 44 ++++++----- .../safe-storage-registry.spec.ts | 21 ++++-- .../tasks/notification-registry.spec.ts | 5 +- .../src/plugin/telemetry/telemetry.spec.ts | 28 ++++--- .../main/src/plugin/temp-file-service.spec.ts | 6 +- .../src/plugin/tray-menu-registry.spec.ts | 4 +- packages/main/src/plugin/updater.spec.ts | 65 ++++++++++------ .../plugin/util/directory-strategy.spec.ts | 4 +- packages/main/src/plugin/util/exec.spec.ts | 66 ++++++----------- .../src/plugin/util/spawn-promise.spec.ts | 2 +- .../main/src/plugin/util/sys-info.spec.ts | 4 +- .../plugin/webview/devtools-manager.spec.ts | 20 +++-- .../plugin/webview/webview-registry.spec.ts | 24 +++--- .../main/src/security-restrictions.spec.ts | 14 ++-- .../main/src/system/macos-startup.spec.ts | 10 +-- .../src/system/window/window-handler.spec.ts | 4 +- .../main/src/system/windows-startup.spec.ts | 11 +-- packages/main/src/tray-animate-icon.spec.ts | 8 +- packages/main/src/tray-menu.spec.ts | 4 +- packages/main/src/util.spec.ts | 2 +- 59 files changed, 366 insertions(+), 359 deletions(-) diff --git a/packages/main/src/application-menu-builder.spec.ts b/packages/main/src/application-menu-builder.spec.ts index c6cdb706b26..1d6ebafc301 100644 --- a/packages/main/src/application-menu-builder.spec.ts +++ b/packages/main/src/application-menu-builder.spec.ts @@ -16,6 +16,7 @@ * SPDX-License-Identifier: Apache-2.0 ***********************************************************************/ +import type * as Electron from 'electron'; import { Menu } from 'electron'; import { aboutMenuItem } from 'electron-util/main'; import { beforeEach, expect, test, vi } from 'vitest'; @@ -23,7 +24,7 @@ import { beforeEach, expect, test, vi } from 'vitest'; import { ApplicationMenuBuilder } from './application-menu-builder.js'; import type { ZoomLevelHandler } from './plugin/zoom-level-handler.js'; -vi.mock('electron', async () => { +vi.mock(import('electron'), async () => { class MyCustomWindow { static readonly singleton = new MyCustomWindow(); @@ -53,10 +54,10 @@ vi.mock('electron', async () => { getApplicationMenu: vi.fn(), setApplicationMenu: vi.fn(), }, - }; + } as unknown as typeof Electron; }); -vi.mock('electron-util/main', async () => { +vi.mock(import('electron-util/main'), async () => { return { aboutMenuItem: vi.fn(), }; diff --git a/packages/main/src/electron-util.spec.ts b/packages/main/src/electron-util.spec.ts index 1c753525a15..8be4100df99 100644 --- a/packages/main/src/electron-util.spec.ts +++ b/packages/main/src/electron-util.spec.ts @@ -16,12 +16,13 @@ * SPDX-License-Identifier: Apache-2.0 ***********************************************************************/ +import type Electron from 'electron'; import { BrowserWindow } from 'electron'; import { beforeEach, expect, test, vi } from 'vitest'; import { findWindow } from './electron-util.js'; -vi.mock('electron', async () => { +vi.mock(import('electron'), async () => { class MyCustomWindow { static readonly singleton = new MyCustomWindow(); @@ -46,7 +47,7 @@ vi.mock('electron', async () => { return { BrowserWindow: MyCustomWindow, - }; + } as unknown as typeof Electron; }); beforeEach(() => { diff --git a/packages/main/src/index.spec.ts b/packages/main/src/index.spec.ts index c5eb682298c..cd8569ef307 100644 --- a/packages/main/src/index.spec.ts +++ b/packages/main/src/index.spec.ts @@ -17,6 +17,7 @@ ***********************************************************************/ import type { IConfigurationChangeEvent, IConfigurationRegistry } from '@podman-desktop/core-api/configuration'; +import type Electron from 'electron'; import type { App } from 'electron'; import { app, BrowserWindow, Menu } from 'electron'; import { aboutMenuItem } from 'electron-util/main'; @@ -43,15 +44,16 @@ const constants = vi.hoisted(() => { }); /* eslint-disable @typescript-eslint/no-empty-function */ -vi.mock('electron-is-dev', async () => { +/* eslint-disable import/no-extraneous-dependencies */ +vi.mock(import('electron-is-dev'), async () => { return {}; }); -vi.mock('electron-context-menu', async () => { +vi.mock(import('electron-context-menu'), async () => { return { default: vi.fn(), }; }); -vi.mock('electron-util/main', async () => { +vi.mock(import('electron-util/main'), async () => { return { aboutMenuItem: vi.fn().mockReturnValue({ label: 'foo' }), }; @@ -85,7 +87,7 @@ vi.mock(import('./util.js'), () => ({ isLinux: vi.fn().mockReturnValue(false), })); -vi.mock('electron', async () => { +vi.mock(import('electron'), async () => { return { autoUpdater: { on: vi.fn(), @@ -154,7 +156,7 @@ vi.mock('electron', async () => { setContextMenu = vi.fn(); }, ), - }; + } as unknown as typeof Electron; }); beforeEach(() => { diff --git a/packages/main/src/main.spec.ts b/packages/main/src/main.spec.ts index 21187146338..6106146ba0c 100644 --- a/packages/main/src/main.spec.ts +++ b/packages/main/src/main.spec.ts @@ -27,9 +27,9 @@ import { isLinux, isMac, isWindows } from '/@/util.js'; import { Main } from './main.js'; // mock electron -vi.mock('electron'); -vi.mock('/@/util.js'); -vi.mock('/@/security-restrictions.js'); +vi.mock(import('electron')); +vi.mock(import('/@/util.js')); +vi.mock(import('/@/security-restrictions.js')); vi.mock(import('electron-context-menu'), () => ({ default: vi.fn(), })); diff --git a/packages/main/src/mainWindow.spec.ts b/packages/main/src/mainWindow.spec.ts index cc910140fd8..df16b62c4e3 100644 --- a/packages/main/src/mainWindow.spec.ts +++ b/packages/main/src/mainWindow.spec.ts @@ -17,6 +17,7 @@ ***********************************************************************/ import type { Configuration } from '@podman-desktop/api'; +import type Electron from 'electron'; import { app, BrowserWindow, ipcMain, screen } from 'electron'; import { afterEach, assert, beforeEach, describe, expect, test, vi } from 'vitest'; @@ -40,7 +41,7 @@ vi.mock(import('./util.js'), async () => ({ stoppedExtensions: { val: true }, })); -vi.mock('electron', async () => { +vi.mock(import('electron'), async () => { return { autoUpdater: { on: vi.fn(), @@ -70,7 +71,7 @@ vi.mock('electron', async () => { BrowserWindow: Object.assign(vi.fn(), { getAllWindows: vi.fn().mockReturnValue([]), }), - }; + } as unknown as typeof Electron; }); let originalArgv: string[] = []; diff --git a/packages/main/src/plugin/app-ready/default-protocol-client.spec.ts b/packages/main/src/plugin/app-ready/default-protocol-client.spec.ts index f6c73ee6d74..2a12069dc5d 100644 --- a/packages/main/src/plugin/app-ready/default-protocol-client.spec.ts +++ b/packages/main/src/plugin/app-ready/default-protocol-client.spec.ts @@ -24,7 +24,7 @@ import { isWindows } from '/@/util.js'; import { DefaultProtocolClient } from './default-protocol-client.js'; -vi.mock('/@/util.js'); +vi.mock(import('/@/util.js')); const ELECTRON_APP_MOCK: ElectronApp = { setAsDefaultProtocolClient: vi.fn(), diff --git a/packages/main/src/plugin/appearance-init.spec.ts b/packages/main/src/plugin/appearance-init.spec.ts index 057f46449bd..8abb499687b 100644 --- a/packages/main/src/plugin/appearance-init.spec.ts +++ b/packages/main/src/plugin/appearance-init.spec.ts @@ -19,6 +19,7 @@ import type { ApiSenderType } from '@podman-desktop/core-api/api-sender'; import { AppearanceSettings } from '@podman-desktop/core-api/appearance'; import type { IConfigurationChangeEvent } from '@podman-desktop/core-api/configuration'; +import type Electron from 'electron'; import { nativeTheme } from 'electron'; import { beforeAll, expect, test, vi } from 'vitest'; @@ -30,10 +31,10 @@ import type { LockedConfiguration } from './locked-configuration.js'; let configurationRegistry: ConfigurationRegistry; -vi.mock('electron', () => { +vi.mock(import('electron'), () => { return { nativeTheme: {}, - }; + } as unknown as typeof Electron; }); const apiSender: ApiSenderType = { diff --git a/packages/main/src/plugin/certificate.spec.ts b/packages/main/src/plugin/certificate.spec.ts index 34c46314716..94aff62aadb 100644 --- a/packages/main/src/plugin/certificate.spec.ts +++ b/packages/main/src/plugin/certificate.spec.ts @@ -33,25 +33,25 @@ const END_CERTIFICATE = '-----END CERTIFICATE-----'; const CR = '\n'; // mock spawn -vi.mock('node:child_process', () => { +vi.mock(import('node:child_process'), () => { return { spawn: vi.fn(), }; }); -vi.mock('./util/spawn-promise.js', () => { +vi.mock(import('./util/spawn-promise.js'), () => { return { spawnWithPromise: vi.fn(), }; }); -vi.mock('node:fs'); +vi.mock(import('node:fs')); // Fake root certificates for mocking tls.rootCertificates // These are simple fake PEM strings (not valid X.509, but sufficient for testing fallback behavior) const FAKE_ROOT_CERTIFICATES = ['fake-cert-1', 'fake-cert-2']; -vi.mock('node:tls', () => { +vi.mock(import('node:tls'), () => { return { rootCertificates: ['fake-cert-1', 'fake-cert-2'], }; @@ -73,7 +73,7 @@ interface WincaAPIOptions { onend?: () => void; } -vi.mock('win-ca/api', () => { +vi.mock(import('win-ca/api'), () => { const wincaAPI = vi.fn(); (wincaAPI as unknown as WincaProcedure).exe = vi.fn(); (wincaAPI as unknown as WincaProcedure).inject = vi.fn(); diff --git a/packages/main/src/plugin/close-behavior.spec.ts b/packages/main/src/plugin/close-behavior.spec.ts index e7bcbf60a70..57f90ed0379 100644 --- a/packages/main/src/plugin/close-behavior.spec.ts +++ b/packages/main/src/plugin/close-behavior.spec.ts @@ -26,7 +26,7 @@ import type { DefaultConfiguration } from './default-configuration.js'; import type { Directories } from './directories.js'; import type { LockedConfiguration } from './locked-configuration.js'; -vi.mock('./util', () => { +vi.mock(import('/@/util.js'), () => { return { isUnixLike: vi.fn(), }; diff --git a/packages/main/src/plugin/configuration-registry.spec.ts b/packages/main/src/plugin/configuration-registry.spec.ts index cb3cdad0689..41aeec00ab7 100644 --- a/packages/main/src/plugin/configuration-registry.spec.ts +++ b/packages/main/src/plugin/configuration-registry.spec.ts @@ -17,7 +17,8 @@ ***********************************************************************/ // Import to access mocked functionionalities such as using vi.mock (we don't want to actually call node:fs methods) -import * as fs from 'node:fs'; +import { cpSync, readFileSync, writeFileSync } from 'node:fs'; +import { access, copyFile, mkdir, readFile, writeFile } from 'node:fs/promises'; import type { IDisposable } from '@podman-desktop/core-api'; import type { ApiSenderType } from '@podman-desktop/core-api/api-sender'; @@ -35,17 +36,18 @@ import type { LockedConfiguration } from './locked-configuration.js'; import type { NotificationRegistry } from './tasks/notification-registry.js'; // mock the fs module -vi.mock('node:fs', () => ({ +vi.mock(import('node:fs'), () => ({ readFileSync: vi.fn(), writeFileSync: vi.fn(), cpSync: vi.fn(), - promises: { - access: vi.fn(), - mkdir: vi.fn(), - writeFile: vi.fn(), - readFile: vi.fn(), - copyFile: vi.fn(), - }, +})); + +vi.mock(import('node:fs/promises'), () => ({ + access: vi.fn(), + mkdir: vi.fn(), + writeFile: vi.fn(), + readFile: vi.fn(), + copyFile: vi.fn(), })); // mock DefaultConfiguration for the new managed defaults functionality @@ -93,19 +95,19 @@ beforeEach(async () => { getManagedDefaultsDirectoryMock.mockReturnValue('/usr/share/podman-desktop'); // Mock basic fs functions needed for initialization - const readFileSync = vi.mocked(fs.readFileSync); - const accessMock = vi.mocked(fs.promises.access); - const mkdirMock = vi.mocked(fs.promises.mkdir); - const writeFileMock = vi.mocked(fs.promises.writeFile); - const readFileMock = vi.mocked(fs.promises.readFile); - const cpSync = vi.mocked(fs.cpSync); + const readFileSyncMock = vi.mocked(readFileSync); + const accessMock = vi.mocked(access); + const mkdirMock = vi.mocked(mkdir); + const writeFileMock = vi.mocked(writeFile); + const readFileMock = vi.mocked(readFile); + const cpSyncMock = vi.mocked(cpSync); - readFileSync.mockReturnValue(JSON.stringify({})); + readFileSyncMock.mockReturnValue(JSON.stringify({})); accessMock.mockResolvedValue(undefined); mkdirMock.mockResolvedValue(undefined); writeFileMock.mockResolvedValue(undefined); readFileMock.mockResolvedValue(JSON.stringify({})); - cpSync.mockReturnValue(undefined); + cpSyncMock.mockReturnValue(undefined); // Setup DefaultConfiguration mock for the new functionality getContentMock.mockResolvedValue({}); @@ -224,17 +226,17 @@ test('Should not find configuration after dispose', async () => { test('should work with an invalid configuration file', async () => { // Mock fs functions needed for this specific test - const readFileSync = vi.mocked(fs.readFileSync); - const accessMock = vi.mocked(fs.promises.access); - const readFileMock = vi.mocked(fs.promises.readFile); - const copyFileMock = vi.mocked(fs.promises.copyFile); + const readFileSyncMock = vi.mocked(readFileSync); + const accessMock = vi.mocked(access); + const readFileMock = vi.mocked(readFile); + const copyFileMock = vi.mocked(copyFile); getConfigurationDirectoryMock.mockReturnValue('/my-config-dir'); configurationRegistry = new ConfigurationRegistry(apiSender, directories, defaultConfiguration, lockedConfiguration); - readFileSync.mockReturnValue('invalid JSON content'); + readFileSyncMock.mockReturnValue('invalid JSON content'); - // Mock fs.promises methods for this test + // Mock promises methods for this test accessMock.mockResolvedValue(undefined); readFileMock.mockResolvedValue('invalid JSON content'); copyFileMock.mockResolvedValue(undefined); @@ -394,7 +396,7 @@ describe('should be notified when a configuration is updated', async () => { test('should remove the object configuration if value is equal to default one', async () => { // Mock fs function needed for this specific test - const writeFileSync = vi.mocked(fs.writeFileSync); + const writeFileSyncMock = vi.mocked(writeFileSync); const node: IConfigurationNode = { id: 'custom', @@ -434,7 +436,7 @@ test('should remove the object configuration if value is equal to default one', { label: 'bar', value: 2 }, ]); - expect(writeFileSync).toHaveBeenNthCalledWith( + expect(writeFileSyncMock).toHaveBeenNthCalledWith( 2, expect.anything(), expect.stringContaining(JSON.stringify({}, undefined, 2)), @@ -443,11 +445,11 @@ test('should remove the object configuration if value is equal to default one', // Tests for applyManagedDefaults method describe('applyManagedDefaults function tests', () => { - let writeFileSync: ReturnType>; + let writeFileSyncMock: ReturnType>; beforeEach(() => { - writeFileSync = vi.mocked(fs.writeFileSync); - writeFileSync.mockClear(); + writeFileSyncMock = vi.mocked(writeFileSync); + writeFileSyncMock.mockClear(); }); test('apply default-config.json values to undefined keys in config', async () => { @@ -482,8 +484,8 @@ describe('applyManagedDefaults function tests', () => { 'setting.bar': 'defaultValue2', }; - // Mock fs.promises.readFile to return user settings.json - const readFileMock = vi.mocked(fs.promises.readFile); + // Mock readFile to return user settings.json + const readFileMock = vi.mocked(readFile); readFileMock.mockResolvedValue(JSON.stringify(userSettings)); getContentMock.mockResolvedValue(managedDefaults); @@ -650,12 +652,12 @@ describe('applyManagedDefaults function tests', () => { // Clear previous calls and trigger saveDefault to check what would be written // now that configurations are registered - writeFileSync.mockClear(); + writeFileSyncMock.mockClear(); testRegistry.saveDefault(); // The value should NOT be in the settings.json since it matches the schema default - expect(writeFileSync).toHaveBeenCalled(); - const writtenContent = JSON.parse(writeFileSync.mock.calls[0]?.[1] as string); + expect(writeFileSyncMock).toHaveBeenCalled(); + const writtenContent = JSON.parse(writeFileSyncMock.mock.calls[0]?.[1] as string); expect(writtenContent['my.fake.property']).toBeUndefined(); }); @@ -686,12 +688,12 @@ describe('applyManagedDefaults function tests', () => { testRegistry.registerConfigurations([node]); // Clear previous calls and trigger saveDefault to check what would be written - writeFileSync.mockClear(); + writeFileSyncMock.mockClear(); testRegistry.saveDefault(); // The value SHOULD be in the settings.json since it differs from schema default - expect(writeFileSync).toHaveBeenCalled(); - const writtenContent = JSON.parse(writeFileSync.mock.calls[0]?.[1] as string); + expect(writeFileSyncMock).toHaveBeenCalled(); + const writtenContent = JSON.parse(writeFileSyncMock.mock.calls[0]?.[1] as string); expect(writtenContent['my.fake.property']).toEqual('customValue'); }); }); diff --git a/packages/main/src/plugin/configuration-registry.ts b/packages/main/src/plugin/configuration-registry.ts index cb65388a80e..1c50090209f 100644 --- a/packages/main/src/plugin/configuration-registry.ts +++ b/packages/main/src/plugin/configuration-registry.ts @@ -17,7 +17,7 @@ ***********************************************************************/ import * as fs from 'node:fs'; -import { promises as fsPromises } from 'node:fs'; +import * as fsPromises from 'node:fs/promises'; import * as path from 'node:path'; import { isDeepStrictEqual } from 'node:util'; diff --git a/packages/main/src/plugin/container-registry.spec.ts b/packages/main/src/plugin/container-registry.spec.ts index a764d82decc..52db7893311 100644 --- a/packages/main/src/plugin/container-registry.spec.ts +++ b/packages/main/src/plugin/container-registry.spec.ts @@ -421,25 +421,16 @@ const configurationRegistry = { getConfiguration: getConfigurationMock, } as unknown as ConfigurationRegistry; -vi.mock('node:fs', async () => { - return { - promises: { - readdir: vi.fn(), - }, - createWriteStream: vi.fn(), - existsSync: vi.fn(), - }; -}); - -vi.mock('node:stream/promises', async () => { +vi.mock(import('node:fs')); +vi.mock(import('node:stream/promises'), async () => { return { pipeline: vi.fn(), readFile: vi.fn(), }; }); -vi.mock('node:fs/promises'); -vi.mock('/@/plugin/podman/kube.js'); +vi.mock(import('node:fs/promises')); +vi.mock(import('/@/plugin/podman/kube.js')); beforeEach(() => { vi.mocked(apiSender.receive).mockClear(); diff --git a/packages/main/src/plugin/contribution-manager.spec.ts b/packages/main/src/plugin/contribution-manager.spec.ts index 6ebbb883e6d..e043929e147 100644 --- a/packages/main/src/plugin/contribution-manager.spec.ts +++ b/packages/main/src/plugin/contribution-manager.spec.ts @@ -35,6 +35,11 @@ import type { Directories } from './directories.js'; import type { Proxy } from './proxy.js'; import { Exec } from './util/exec.js'; +vi.mock(import('node:fs')); +vi.mock(import('/@/plugin/util/exec.js')); +vi.mock(import('/@/util.js')); +vi.mock(import('js-yaml')); + let contributionManager: TestContributionManager; let composeFileExample: ComposeObject; @@ -216,9 +221,6 @@ test('Should add a service to expose port if socket', async () => { }); test('Check invalid port file', async () => { - vi.mock('node:fs'); - vi.mock('js-yaml'); - const metadata = { vm: { composefile: 'dummy-compose-file', @@ -314,20 +316,7 @@ test('waitForAContainerConnection delayed twice', async () => { }); describe('findComposeBinary', () => { - vi.mock('./util', () => { - return { - isWindows: vi.fn(), - isMac: vi.fn(), - isUnixLike: vi.fn(), - exec: vi.fn(), - }; - }); - - vi.mock(import('/@/plugin/util/exec.js')); - test('Check findComposeBinary on Windows', async () => { - vi.mock('node:fs'); - vi.spyOn(util, 'isWindows').mockImplementation(() => true); // mock exec @@ -339,8 +328,6 @@ describe('findComposeBinary', () => { }); test('Check findComposeBinary not exists on Windows', async () => { - vi.mock('node:fs'); - vi.spyOn(util, 'isWindows').mockImplementation(() => true); // mock exec @@ -353,8 +340,6 @@ describe('findComposeBinary', () => { }); test('Check findComposeBinary on macOS', async () => { - vi.mock('node:fs'); - vi.spyOn(util, 'isMac').mockImplementation(() => true); vi.spyOn(util, 'isWindows').mockImplementation(() => false); @@ -371,8 +356,6 @@ describe('findComposeBinary', () => { }); test('Check findComposeBinary on Linux', async () => { - vi.mock('node:fs'); - vi.spyOn(util, 'isUnixLike').mockImplementation(() => true); vi.spyOn(util, 'isMac').mockImplementation(() => false); vi.spyOn(util, 'isWindows').mockImplementation(() => false); @@ -698,8 +681,6 @@ test('delete extension', async () => { }); test('init', async () => { - vi.mock('node:fs'); - // mock existsSync as always returning true vi.mocked(fs.existsSync).mockReturnValue(true); diff --git a/packages/main/src/plugin/default-configuration.spec.ts b/packages/main/src/plugin/default-configuration.spec.ts index 871ebbcca1f..b231bbf6795 100644 --- a/packages/main/src/plugin/default-configuration.spec.ts +++ b/packages/main/src/plugin/default-configuration.spec.ts @@ -24,7 +24,7 @@ import { DefaultConfiguration } from './default-configuration.js'; import type { Directories } from './directories.js'; // mock the fs module -vi.mock('node:fs/promises'); +vi.mock(import('node:fs/promises')); let defaultConfiguration: DefaultConfiguration; const getManagedDefaultsDirectoryMock = vi.fn(); diff --git a/packages/main/src/plugin/dialog-registry.spec.ts b/packages/main/src/plugin/dialog-registry.spec.ts index 6f163629b41..c93510f1b18 100644 --- a/packages/main/src/plugin/dialog-registry.spec.ts +++ b/packages/main/src/plugin/dialog-registry.spec.ts @@ -35,13 +35,13 @@ const fakeBrowserWindow: BrowserWindow = { }, } as unknown as BrowserWindow; -vi.mock('electron', async () => { +vi.mock(import('electron'), async () => { return { dialog: { showOpenDialog: vi.fn(), showSaveDialog: vi.fn(), }, - }; + } as unknown as typeof Electron; }); class TestDialogRegistry extends DialogRegistry {} diff --git a/packages/main/src/plugin/directories-legacy.spec.ts b/packages/main/src/plugin/directories-legacy.spec.ts index 6ec006d8183..7f940707276 100644 --- a/packages/main/src/plugin/directories-legacy.spec.ts +++ b/packages/main/src/plugin/directories-legacy.spec.ts @@ -37,7 +37,7 @@ beforeEach(() => { process.env = { ...originalProcessEnv }; // Mock file system - vi.mock('node:fs'); + vi.mock(import('node:fs')); vi.spyOn(fs, 'existsSync').mockReturnValue(true); vi.spyOn(fs, 'mkdirSync').mockImplementation(() => ''); }); diff --git a/packages/main/src/plugin/docker-extension/docker-desktop-installation.spec.ts b/packages/main/src/plugin/docker-extension/docker-desktop-installation.spec.ts index f4f1b801da8..c903dad8d91 100644 --- a/packages/main/src/plugin/docker-extension/docker-desktop-installation.spec.ts +++ b/packages/main/src/plugin/docker-extension/docker-desktop-installation.spec.ts @@ -282,7 +282,7 @@ describe('handleExtensionVMServiceRequest', () => { }); test('Check handlePluginInstall', async () => { - vi.mock('node:fs'); + vi.mock(import('node:fs')); const allReplies: string[] = []; diff --git a/packages/main/src/plugin/docker-extension/docker-desktop-installer.spec.ts b/packages/main/src/plugin/docker-extension/docker-desktop-installer.spec.ts index 3cf58f13dff..45256b4048c 100644 --- a/packages/main/src/plugin/docker-extension/docker-desktop-installer.spec.ts +++ b/packages/main/src/plugin/docker-extension/docker-desktop-installer.spec.ts @@ -46,7 +46,7 @@ beforeEach(() => { }); test('Check extractExtensionFiles', async () => { - vi.mock('node:fs/promises'); + vi.mock(import('node:fs/promises')); const metadataJson = { name: 'My Extension', diff --git a/packages/main/src/plugin/docker-extension/docker-plugin-adapter.spec.ts b/packages/main/src/plugin/docker-extension/docker-plugin-adapter.spec.ts index 37baf953c92..ae8fb54effb 100644 --- a/packages/main/src/plugin/docker-extension/docker-plugin-adapter.spec.ts +++ b/packages/main/src/plugin/docker-extension/docker-plugin-adapter.spec.ts @@ -17,6 +17,7 @@ ***********************************************************************/ import type { SimpleContainerInfo } from '@podman-desktop/core-api'; +import type Electron from 'electron'; import type { IpcMainEvent } from 'electron'; import { beforeAll, beforeEach, describe, expect, test, vi } from 'vitest'; @@ -27,11 +28,11 @@ import { DockerPluginAdapter } from './docker-plugin-adapter.js'; let dockerPluginAdapter: TestDockerPluginAdapter; -vi.mock('electron', () => { +vi.mock(import('electron'), () => { const mockIpcMain = { on: vi.fn().mockReturnThis(), }; - return { ipcMain: mockIpcMain }; + return { ipcMain: mockIpcMain } as unknown as typeof Electron; }); const contributionManager = {} as unknown as ContributionManager; diff --git a/packages/main/src/plugin/docker/docker-compatibility.spec.ts b/packages/main/src/plugin/docker/docker-compatibility.spec.ts index 7b391bde010..9b22588a571 100644 --- a/packages/main/src/plugin/docker/docker-compatibility.spec.ts +++ b/packages/main/src/plugin/docker/docker-compatibility.spec.ts @@ -22,6 +22,7 @@ import { promises } from 'node:fs'; import type { ProviderContainerConnection } from '@podman-desktop/api'; import type { DockerSocketServerInfoType, ProviderInfo } from '@podman-desktop/core-api'; import type { ApiSenderType } from '@podman-desktop/core-api/api-sender'; +import type * as Dockerode from 'dockerode'; import { beforeAll, describe, expect, test, vi } from 'vitest'; import { ConfigurationRegistry } from '/@/plugin/configuration-registry.js'; @@ -50,13 +51,13 @@ class TestDockerCompatibility extends DockerCompatibility { } // mock exists sync -vi.mock('node:fs'); +vi.mock(import('node:fs')); const dockerodeInfoMock = vi.fn(); const dockerodePodmanInfoMock = vi.fn(); -vi.mock('dockerode', async () => { - class Dockerode { +vi.mock(import('dockerode'), async () => { + class DockerodeMock { async info(): Promise { return dockerodeInfoMock(); } @@ -65,7 +66,7 @@ vi.mock('dockerode', async () => { } } - return { default: Dockerode }; + return { default: DockerodeMock } as unknown as typeof Dockerode; }); vi.mock(import('/@/util.js')); diff --git a/packages/main/src/plugin/experimental-feature-feedback-handler.spec.ts b/packages/main/src/plugin/experimental-feature-feedback-handler.spec.ts index 563c7851ece..e2211bc22b3 100644 --- a/packages/main/src/plugin/experimental-feature-feedback-handler.spec.ts +++ b/packages/main/src/plugin/experimental-feature-feedback-handler.spec.ts @@ -18,6 +18,7 @@ import type { Configuration } from '@podman-desktop/api'; import type { IConfigurationPropertyRecordedSchema } from '@podman-desktop/core-api/configuration'; +import type Electron from 'electron'; import { shell } from 'electron'; import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'; @@ -27,11 +28,15 @@ import { ExperimentalFeatureFeedbackHandler } from './experimental-feature-feedb import type { MessageBox } from './message-box.js'; import type { Telemetry } from './telemetry/telemetry.js'; -vi.mock('electron', () => ({ - shell: { - openExternal: vi.fn().mockResolvedValue(undefined), - }, -})); +vi.mock( + import('electron'), + () => + ({ + shell: { + openExternal: vi.fn().mockResolvedValue(undefined), + }, + }) as unknown as typeof Electron, +); const features: Record = { 'feat.feature1': { diff --git a/packages/main/src/plugin/explore-features/explore-features.spec.ts b/packages/main/src/plugin/explore-features/explore-features.spec.ts index 423b3171745..8d960020bab 100644 --- a/packages/main/src/plugin/explore-features/explore-features.spec.ts +++ b/packages/main/src/plugin/explore-features/explore-features.spec.ts @@ -16,7 +16,8 @@ * SPDX-License-Identifier: Apache-2.0 ***********************************************************************/ -import { existsSync, promises } from 'node:fs'; +import { existsSync } from 'node:fs'; +import * as promises from 'node:fs/promises'; import path from 'node:path'; import type { Configuration } from '@podman-desktop/api'; @@ -27,6 +28,7 @@ import type { ProviderInfo, ProviderKubernetesConnectionInfo, } from '@podman-desktop/core-api'; +import type Electron from 'electron'; import { beforeEach, expect, test, vi } from 'vitest'; import type { ConfigurationRegistry } from '/@/plugin/configuration-registry.js'; @@ -38,20 +40,20 @@ import type { ProviderRegistry } from '/@/plugin/provider-registry.js'; import { ExploreFeatures } from './explore-features.js'; -vi.mock('electron', async () => { +vi.mock(import('electron'), async () => { return { app: { getAppPath: vi.fn().mockReturnValue('a-custom-appPath'), }, - }; + } as unknown as typeof Electron; }); -vi.mock('node:fs', () => ({ - promises: { - readFile: vi.fn(), - }, +vi.mock(import('node:fs'), () => ({ existsSync: vi.fn(), })); +vi.mock(import('node:fs/promises'), () => ({ + readFile: vi.fn(), +})); const configurationRegistryMock = { getConfiguration: vi.fn().mockReturnValue({ diff --git a/packages/main/src/plugin/extension/extension-analyzer.spec.ts b/packages/main/src/plugin/extension/extension-analyzer.spec.ts index a1176bd505c..e5e60c997a2 100644 --- a/packages/main/src/plugin/extension/extension-analyzer.spec.ts +++ b/packages/main/src/plugin/extension/extension-analyzer.spec.ts @@ -29,8 +29,8 @@ import type { ExtensionManifest } from './extension-manifest-schema.js'; let extensionAnalyzer: ExtensionAnalyzer; -vi.mock('node:fs'); -vi.mock('node:fs/promises'); +vi.mock(import('node:fs')); +vi.mock(import('node:fs/promises')); beforeEach(() => { vi.resetAllMocks(); @@ -72,8 +72,8 @@ describe('analyze extension and main', () => { }); test('check for extension with linked folder', async () => { - vi.mock('node:fs'); - vi.mock('node:fs/promises'); + vi.mock(import('node:fs')); + vi.mock(import('node:fs/promises')); // mock fs.existsSync const fsExistsSyncMock = vi.spyOn(fs, 'existsSync'); @@ -108,7 +108,7 @@ describe('analyze extension and main', () => { }); test('check for extension without main entry', async () => { - vi.mock('node:fs'); + vi.mock(import('node:fs')); // mock fs.existsSync const fsExistsSyncMock = vi.spyOn(fs, 'existsSync'); @@ -140,7 +140,7 @@ describe('analyze extension and main', () => { }); test('check for extension with devMode', async () => { - vi.mock('node:fs'); + vi.mock(import('node:fs')); // mock fs.existsSync const fsExistsSyncMock = vi.spyOn(fs, 'existsSync'); diff --git a/packages/main/src/plugin/extension/extension-loader.spec.ts b/packages/main/src/plugin/extension/extension-loader.spec.ts index 4c733672df5..b316fb849d4 100644 --- a/packages/main/src/plugin/extension/extension-loader.spec.ts +++ b/packages/main/src/plugin/extension/extension-loader.spec.ts @@ -325,12 +325,12 @@ const createApi = (disposables?: { dispose(): unknown }[]): typeof containerDesk return extensionLoader.createApi(analyzedExtension); }; -vi.mock('electron', () => { +vi.mock(import('electron'), () => { return { app: { getVersion: vi.fn(), }, - }; + } as unknown as typeof Electron; }); vi.mock(import('/@/util.js')); @@ -392,7 +392,7 @@ beforeEach(() => { ); }); -vi.mock('node:fs'); +vi.mock(import('node:fs')); beforeEach(() => { telemetryTrackMock.mockImplementation(() => Promise.resolve()); @@ -548,7 +548,7 @@ test('Should load file from watching scanning folder', async () => { // reduce timeout delay for tests extensionLoader.setWatchTimeout(50); - vi.mock('node:fs'); + vi.mock(import('node:fs')); // mock fs.watch const fsWatchMock = vi.spyOn(fs, 'watch'); fsWatchMock.mockImplementation((filename: fs.PathLike, listener?: fs.WatchListener): fs.FSWatcher => { @@ -1340,7 +1340,7 @@ describe('Removing extension by user', async () => { }); test('check dispose when deactivating', async () => { - vi.mock('node:fs'); + vi.mock(import('node:fs')); const extensionId = 'fooPublisher.fooName'; extensionLoader.setActivatedExtension(extensionId, { @@ -2437,7 +2437,7 @@ describe('containerEngine', async () => { describe('extensionContext', async () => { test('secrets', async () => { - vi.mock('node:fs'); + vi.mock(import('node:fs')); vi.mocked(fs.existsSync).mockReturnValue(true); diff --git a/packages/main/src/plugin/extension/extension-tsconfig-parser.spec.ts b/packages/main/src/plugin/extension/extension-tsconfig-parser.spec.ts index 075b3b88a5a..e4157b8f845 100644 --- a/packages/main/src/plugin/extension/extension-tsconfig-parser.spec.ts +++ b/packages/main/src/plugin/extension/extension-tsconfig-parser.spec.ts @@ -25,8 +25,8 @@ import { beforeEach, expect, test, vi } from 'vitest'; import { ExtensionTypeScriptConfigParser } from './extension-tsconfig-parser.js'; -vi.mock('node:fs'); -vi.mock('get-tsconfig'); +vi.mock(import('node:fs')); +vi.mock(import('get-tsconfig')); beforeEach(() => { vi.restoreAllMocks(); diff --git a/packages/main/src/plugin/extension/extension-watcher.spec.ts b/packages/main/src/plugin/extension/extension-watcher.spec.ts index 503399d0e64..cfb66ced45a 100644 --- a/packages/main/src/plugin/extension/extension-watcher.spec.ts +++ b/packages/main/src/plugin/extension/extension-watcher.spec.ts @@ -26,7 +26,7 @@ import type { AnalyzedExtension } from './extension-analyzer.js'; import type { ActivatedExtension } from './extension-loader.js'; import { ExtensionWatcher } from './extension-watcher.js'; -vi.mock('get-tsconfig'); +vi.mock(import('get-tsconfig')); const fileSystemMonitoring = { createFileSystemWatcher: vi.fn(), diff --git a/packages/main/src/plugin/feedback-handler.spec.ts b/packages/main/src/plugin/feedback-handler.spec.ts index 4d666d6e59c..3956d29e5a7 100644 --- a/packages/main/src/plugin/feedback-handler.spec.ts +++ b/packages/main/src/plugin/feedback-handler.spec.ts @@ -28,19 +28,23 @@ import productJSONFile from '/@product.json' with { type: 'json' }; import { FeedbackHandler } from './feedback-handler.js'; -vi.mock('electron', () => ({ - shell: { - openExternal: vi.fn(), - }, -})); +vi.mock( + import('electron'), + () => + ({ + shell: { + openExternal: vi.fn(), + }, + }) as unknown as typeof Electron, +); -vi.mock('/@/util.js', () => ({ +vi.mock(import('/@/util.js'), () => ({ isLinux: vi.fn(), isMac: vi.fn(), isWindows: vi.fn(), })); -vi.mock('node:os', () => ({ +vi.mock(import('node:os'), () => ({ homedir: vi.fn(() => '/home/user'), release: vi.fn(), })); diff --git a/packages/main/src/plugin/image-registry.spec.ts b/packages/main/src/plugin/image-registry.spec.ts index e8842c85f21..807a8f670e0 100644 --- a/packages/main/src/plugin/image-registry.spec.ts +++ b/packages/main/src/plugin/image-registry.spec.ts @@ -83,13 +83,13 @@ afterEach(() => { server?.close(); }); -vi.mock('fzstd', () => { +vi.mock(import('fzstd'), () => { return { decompress: vi.fn(), }; }); -vi.mock('tar', async () => { +vi.mock(import('tar'), async () => { // eslint-disable-next-line @typescript-eslint/consistent-type-imports const tarActual = await vi.importActual('tar'); diff --git a/packages/main/src/plugin/index.spec.ts b/packages/main/src/plugin/index.spec.ts index 63f1e1478b6..3c3c77065e5 100644 --- a/packages/main/src/plugin/index.spec.ts +++ b/packages/main/src/plugin/index.spec.ts @@ -95,7 +95,7 @@ const mainWindowDeferred = Promise.withResolvers(); const handlers = new Map(); beforeAll(async () => { - vi.mock('electron', () => { + vi.mock(import('electron'), () => { return { shell: { openExternal: vi.fn(), @@ -116,7 +116,7 @@ beforeAll(async () => { BrowserWindow: { getAllWindows: vi.fn(), }, - }; + } as unknown as typeof Electron; }); const trayMenuMock = {} as unknown as TrayMenu; pluginSystem = new TestPluginSystem(trayMenuMock, mainWindowDeferred); diff --git a/packages/main/src/plugin/kubernetes/contexts-manager.spec.ts b/packages/main/src/plugin/kubernetes/contexts-manager.spec.ts index 6ac4fe00e65..7fa573002a3 100644 --- a/packages/main/src/plugin/kubernetes/contexts-manager.spec.ts +++ b/packages/main/src/plugin/kubernetes/contexts-manager.spec.ts @@ -22,6 +22,7 @@ import type { CheckingState, ContextGeneralState, KubeContext, ResourceName } fr import type { ApiSenderType } from '@podman-desktop/core-api/api-sender'; import { afterEach, beforeAll, beforeEach, describe, expect, test, vi } from 'vitest'; +import type * as ContextConstant from './contexts-constants.js'; import type { ContextsInformersRegistry } from './contexts-informers-registry.js'; import { ContextsManager } from './contexts-manager.js'; import type { ContextsStatesRegistry } from './contexts-states-registry.js'; @@ -112,7 +113,7 @@ function contextHasBeenChecked(contextName: string): boolean { return false; } -vi.mock('@kubernetes/client-node', async importOriginal => { +vi.mock(import('@kubernetes/client-node'), async importOriginal => { const actual = await importOriginal(); return { ...actual, @@ -128,7 +129,7 @@ const backoffLimitMock = vi.fn(); const backoffLimitCurrentContextMock = vi.fn(); const backoffJitterMock = vi.fn(); const dispatchTimeoutMock = vi.fn(); -vi.mock('./contexts-constants.js', () => { +vi.mock(import('./contexts-constants.js'), () => { return { get connectTimeout(): number { return connectTimeoutMock(); @@ -154,7 +155,7 @@ vi.mock('./contexts-constants.js', () => { get dispatchTimeout(): number { return dispatchTimeoutMock(); }, - }; + } as unknown as typeof ContextConstant; }); const originalConsoleDebug = console.debug; diff --git a/packages/main/src/plugin/kubernetes/kubernetes-port-forward-connection.spec.ts b/packages/main/src/plugin/kubernetes/kubernetes-port-forward-connection.spec.ts index 77e4c6899fc..a39a9717813 100644 --- a/packages/main/src/plugin/kubernetes/kubernetes-port-forward-connection.spec.ts +++ b/packages/main/src/plugin/kubernetes/kubernetes-port-forward-connection.spec.ts @@ -16,7 +16,7 @@ * SPDX-License-Identifier: Apache-2.0 ***********************************************************************/ -import net from 'node:net'; +import { createServer, type Server, type Socket } from 'node:net'; import { AppsV1Api, @@ -66,18 +66,11 @@ const mockAppsV1Api = { vi.mock(import('@kubernetes/client-node')); -vi.mock('node:net', async () => { - // eslint-disable-next-line @typescript-eslint/consistent-type-imports - const { Server } = await vi.importActual('node:net'); +vi.mock(import('node:net'), async importOriginal => { + const { Server } = await importOriginal(); return { Server, - default: { - createServer: vi.fn(() => ({ - listen: vi.fn(), - on: vi.fn(), - close: vi.fn(), - })), - }, + createServer: vi.fn(), }; }); @@ -150,7 +143,7 @@ class TestablePortForwardConnectionService extends PortForwardConnectionService return super.getForwardingSetup(resource, forward); } - public override createServer(forwardSetup: ForwardingSetup): net.Server { + public override createServer(forwardSetup: ForwardingSetup): Server { return super.createServer(forwardSetup); } @@ -208,16 +201,14 @@ describe('PortForwardConnectionService', () => { close: vi.fn(), }; - (net.createServer as unknown as MockedFunction).mockReturnValue( - server as unknown as net.Server, - ); + vi.mocked(createServer).mockReturnValue(server as unknown as Server); (global.fetch as unknown as MockedFunction).mockResolvedValueOnce( new Response(undefined, { status: 200 }), ); const disposable = await service.performForward(forwardSetup); - expect(net.createServer).toHaveBeenCalled(); + expect(createServer).toHaveBeenCalled(); expect(server.listen).toHaveBeenCalledWith(3000, 'localhost'); expect(disposable.dispose).toBeInstanceOf(Function); }); @@ -232,7 +223,7 @@ describe('PortForwardConnectionService', () => { const socket = { on: vi.fn(), end: vi.fn(), - } as unknown as net.Socket; + } as unknown as Socket; const server = { listen: vi.fn(), @@ -240,13 +231,13 @@ describe('PortForwardConnectionService', () => { close: vi.fn(), }; - (net.createServer as unknown as MockedFunction).mockImplementation( + vi.mocked(createServer).mockImplementation( // @ts-expect-error we're sure in the method signature (connectionListener?: (socket: net.Socket) => void) => { if (connectionListener) { connectionListener(socket); } - return server as unknown as net.Server; + return server as unknown as Server; }, ); @@ -263,7 +254,7 @@ describe('PortForwardConnectionService', () => { const createdServer = service.createServer(forwardSetup as never); - expect(net.createServer).toHaveBeenCalled(); + expect(createServer).toHaveBeenCalled(); expect(PortForward.prototype.portForward).toHaveBeenCalledWith( forwardSetup.namespace, forwardSetup.name, diff --git a/packages/main/src/plugin/kubernetes/kubernetes-port-forward-connection.ts b/packages/main/src/plugin/kubernetes/kubernetes-port-forward-connection.ts index 7d5205c00a4..f645c6be430 100644 --- a/packages/main/src/plugin/kubernetes/kubernetes-port-forward-connection.ts +++ b/packages/main/src/plugin/kubernetes/kubernetes-port-forward-connection.ts @@ -15,7 +15,8 @@ * * SPDX-License-Identifier: Apache-2.0 ***********************************************************************/ -import net from 'node:net'; +import type { Server } from 'node:net'; +import { createServer } from 'node:net'; import type { V1Deployment, V1Pod, V1Service } from '@kubernetes/client-node'; import { PortForward } from '@kubernetes/client-node'; @@ -91,8 +92,8 @@ export class PortForwardConnectionService { * @param forwardSetup - The forwarding setup information. * @returns The created server. */ - protected createServer(forwardSetup: ForwardingSetup): net.Server { - return net.createServer(socket => { + protected createServer(forwardSetup: ForwardingSetup): Server { + return createServer(socket => { const kubernetesPortForward = new PortForward(this.kubeClient.getKubeConfig()); kubernetesPortForward .portForward( diff --git a/packages/main/src/plugin/kubernetes/kubernetes-port-forward-service.spec.ts b/packages/main/src/plugin/kubernetes/kubernetes-port-forward-service.spec.ts index 15fa74fc958..6b34f115c7d 100644 --- a/packages/main/src/plugin/kubernetes/kubernetes-port-forward-service.spec.ts +++ b/packages/main/src/plugin/kubernetes/kubernetes-port-forward-service.spec.ts @@ -32,12 +32,12 @@ import { } from '/@/plugin/kubernetes/kubernetes-port-forward-service.js'; import type { ConfigManagementService } from '/@/plugin/kubernetes/kubernetes-port-forward-storage.js'; -vi.mock('/@/plugin/kubernetes/kubernetes-port-forward-connection.js'); -vi.mock('/@/plugin/kubernetes/kubernetes-port-forward-storage.js'); -vi.mock('/@/plugin/kubernetes/kubernetes-port-forward-validation.js'); -vi.mock('/@/plugin/util/port.js'); -vi.mock('/@/plugin/directories.js'); -vi.mock('node:crypto'); +vi.mock(import('/@/plugin/kubernetes/kubernetes-port-forward-connection.js')); +vi.mock(import('/@/plugin/kubernetes/kubernetes-port-forward-storage.js')); +vi.mock(import('/@/plugin/kubernetes/kubernetes-port-forward-validation.js')); +vi.mock(import('/@/plugin/util/port.js')); +vi.mock(import('/@/plugin/directories.js')); +vi.mock(import('node:crypto')); class TestKubernetesPortForwardServiceProvider extends KubernetesPortForwardServiceProvider { public override getKubeConfigKey(kubeConfig: KubeConfig): string { diff --git a/packages/main/src/plugin/kubernetes/kubernetes-port-forward-storage.spec.ts b/packages/main/src/plugin/kubernetes/kubernetes-port-forward-storage.spec.ts index 3bc6503f16a..7d1282b315f 100644 --- a/packages/main/src/plugin/kubernetes/kubernetes-port-forward-storage.spec.ts +++ b/packages/main/src/plugin/kubernetes/kubernetes-port-forward-storage.spec.ts @@ -33,7 +33,7 @@ import { PreferenceFolderBasedStorage, } from '/@/plugin/kubernetes/kubernetes-port-forward-storage.js'; -vi.mock('node:fs/promises', () => ({ +vi.mock(import('node:fs/promises'), () => ({ mkdir: vi.fn(), access: vi.fn(), writeFile: vi.fn(), diff --git a/packages/main/src/plugin/locked-configuration.spec.ts b/packages/main/src/plugin/locked-configuration.spec.ts index d90495c13a3..a7f6983e5f6 100644 --- a/packages/main/src/plugin/locked-configuration.spec.ts +++ b/packages/main/src/plugin/locked-configuration.spec.ts @@ -24,7 +24,7 @@ import type { Directories } from './directories.js'; import { LockedConfiguration } from './locked-configuration.js'; // mock the fs/promises module -vi.mock('node:fs/promises'); +vi.mock(import('node:fs/promises')); let lockedConfiguration: LockedConfiguration; const getManagedDefaultsDirectoryMock = vi.fn(); diff --git a/packages/main/src/plugin/onboarding-registry.spec.ts b/packages/main/src/plugin/onboarding-registry.spec.ts index a132a4d3039..28319197ad7 100644 --- a/packages/main/src/plugin/onboarding-registry.spec.ts +++ b/packages/main/src/plugin/onboarding-registry.spec.ts @@ -77,7 +77,7 @@ describe('an OnboardingRegistry instance exists', () => { registerOnboardingDisposable = onboardingRegistry.registerOnboarding(extension, manifest.contributes.onboarding); getConfigMock.mockReturnValue(true); - vi.mock('node:fs'); + vi.mock(import('node:fs')); readFileSync.mockReturnValue(JSON.stringify({})); }); diff --git a/packages/main/src/plugin/podman/kube.spec.ts b/packages/main/src/plugin/podman/kube.spec.ts index 1863e6069e3..b778e8ec43a 100644 --- a/packages/main/src/plugin/podman/kube.spec.ts +++ b/packages/main/src/plugin/podman/kube.spec.ts @@ -25,9 +25,9 @@ import { beforeEach, describe, expect, test, vi } from 'vitest'; import { getImageNamePrefix, KubePlayContext } from '/@/plugin/podman/kube.js'; -vi.mock('node:fs'); -vi.mock('node:fs/promises'); -vi.mock('tar-fs'); +vi.mock(import('node:fs')); +vi.mock(import('node:fs/promises')); +vi.mock(import('tar-fs')); beforeEach(() => { vi.resetAllMocks(); diff --git a/packages/main/src/plugin/proxy-resolver.spec.ts b/packages/main/src/plugin/proxy-resolver.spec.ts index 6881faacd07..073f033df8f 100644 --- a/packages/main/src/plugin/proxy-resolver.spec.ts +++ b/packages/main/src/plugin/proxy-resolver.spec.ts @@ -22,7 +22,7 @@ import { get } from 'node:http'; import * as nodeurl from 'node:url'; -import type { HttpsProxyAgentOptions } from 'hpagent'; +import type * as hpagent from 'hpagent'; import { HttpsProxyAgent } from 'hpagent'; import { beforeEach, expect, test, vi } from 'vitest'; @@ -30,22 +30,21 @@ import type { Certificates } from './certificates.js'; import type { Proxy } from './proxy.js'; import * as ProxyResolver from './proxy-resolver.js'; -vi.mock('http', () => { +vi.mock(import('node:http'), () => { return { get: vi.fn(), request: vi.fn(), }; }); -vi.mock('https', () => { +vi.mock(import('node:https'), () => { return { get: vi.fn(), request: vi.fn(), - Agent: vi.fn(), }; }); -vi.mock('hpagent', () => { +vi.mock(import('hpagent'), () => { return { HttpProxyAgent: function (): void { // @ts-ignore: this implicit any type @@ -55,7 +54,7 @@ vi.mock('hpagent', () => { // @ts-ignore: this implicit any type this.https = true; }, - }; + } as unknown as typeof hpagent; }); function createProxy(enabled: boolean, httpsProxy?: string, httpProxy?: string): Proxy { @@ -148,7 +147,7 @@ test('patched http get when called with url and callback calls original with opt expect(get).toHaveBeenCalledTimes(2); expect(get).toBeCalledWith( { - agent: new HttpsProxyAgent({} as HttpsProxyAgentOptions), + agent: new HttpsProxyAgent({} as hpagent.HttpsProxyAgentOptions), hostname: `fe80${colon}${colon}1802${colon}20ff${colon}fe8d${colon}d4ce`, path: '/', port: '', @@ -171,7 +170,7 @@ test('patched http get translates username@password in url to auth option', () = expect(get).toHaveBeenCalledTimes(2); expect(get).toBeCalledWith( { - agent: new HttpsProxyAgent({} as HttpsProxyAgentOptions), + agent: new HttpsProxyAgent({} as hpagent.HttpsProxyAgentOptions), hostname: 'rest.url', path: '/', port: '', @@ -198,7 +197,7 @@ test('patched http get works when url passed as protocol and hostname in options } expect(get).toBeCalledWith( { - agent: new HttpsProxyAgent({} as HttpsProxyAgentOptions), + agent: new HttpsProxyAgent({} as hpagent.HttpsProxyAgentOptions), ...options, }, callback, diff --git a/packages/main/src/plugin/proxy.spec.ts b/packages/main/src/plugin/proxy.spec.ts index 16153b3982f..adbb871ff77 100644 --- a/packages/main/src/plugin/proxy.spec.ts +++ b/packages/main/src/plugin/proxy.spec.ts @@ -38,14 +38,14 @@ import { getProxySettingsFromSystem } from './proxy-system.js'; const URL = 'https://podman-desktop.io'; -vi.mock('./proxy-system.js', () => { +vi.mock(import('./proxy-system.js'), () => { return { getProxySettingsFromSystem: vi.fn(), }; }); // Mock the fs module -vi.mock('node:fs'); +vi.mock(import('node:fs')); const readFileSync = vi.spyOn(fs, 'readFileSync'); const writeFileSync = vi.spyOn(fs, 'writeFileSync'); const existsSync = vi.spyOn(fs, 'existsSync'); diff --git a/packages/main/src/plugin/recommendations/recommendations-registry.spec.ts b/packages/main/src/plugin/recommendations/recommendations-registry.spec.ts index 94135f7e8e9..a107e0b018b 100644 --- a/packages/main/src/plugin/recommendations/recommendations-registry.spec.ts +++ b/packages/main/src/plugin/recommendations/recommendations-registry.spec.ts @@ -26,6 +26,8 @@ import type { ExtensionsCatalog } from '/@/plugin/extension/catalog/extensions-c import type { ExtensionLoader } from '/@/plugin/extension/extension-loader.js'; import type { Featured } from '/@/plugin/featured/featured.js'; +// eslint-disable-next-line no-restricted-imports +import type * as Recommendations from '../../../../../recommendations.json'; import { RecommendationsRegistry } from './recommendations-registry.js'; let recommendationsRegistry: RecommendationsRegistry; @@ -33,26 +35,30 @@ let recommendationsRegistry: RecommendationsRegistry; const registerConfigurationsMock = vi.fn(); const getRecommendationIgnored = vi.fn(); -vi.mock('../../../../../recommendations.json', () => ({ - default: { - extensions: Array.from({ length: 10 }, (_, i) => ({ - extensionId: `dummy.id-${i}`, - title: 'dummy title', - description: 'dummy description', - icon: 'data:image/png;base64-icon', - thumbnail: 'data:image/png;base64-thumbnail', - publishDate: '2020-01-01', - })), - registries: [ - { - id: 'my.registry.com', - name: 'My Extension', - extensionId: 'my.extensionId', - errors: ['is denied'], +vi.mock( + import('../../../../../recommendations.json'), + () => + ({ + default: { + extensions: Array.from({ length: 10 }, (_, i) => ({ + extensionId: `dummy.id-${i}`, + title: 'dummy title', + description: 'dummy description', + icon: 'data:image/png;base64-icon', + thumbnail: 'data:image/png;base64-thumbnail', + publishDate: '2020-01-01', + })), + registries: [ + { + id: 'my.registry.com', + name: 'My Extension', + extensionId: 'my.extensionId', + errors: ['is denied'], + }, + ], }, - ], - }, -})); + }) as unknown as typeof Recommendations, +); const configurationRegistryMock = { registerConfigurations: registerConfigurationsMock, diff --git a/packages/main/src/plugin/safe-storage/safe-storage-registry.spec.ts b/packages/main/src/plugin/safe-storage/safe-storage-registry.spec.ts index 3781103c669..be7f9a7a0fa 100644 --- a/packages/main/src/plugin/safe-storage/safe-storage-registry.spec.ts +++ b/packages/main/src/plugin/safe-storage/safe-storage-registry.spec.ts @@ -19,6 +19,7 @@ import { existsSync } from 'node:fs'; import { readFile, writeFile } from 'node:fs/promises'; +import type Electron from 'electron'; import { safeStorage } from 'electron'; import { beforeEach, expect, test, vi } from 'vitest'; @@ -27,15 +28,19 @@ import { type Directories } from '/@/plugin/directories.js'; import type { SecretStorageChangeEvent } from './safe-storage-registry.js'; import { SafeStorageRegistry } from './safe-storage-registry.js'; -vi.mock('electron', () => ({ - safeStorage: { - encryptString: vi.fn(), - decryptString: vi.fn(), - }, -})); +vi.mock( + import('electron'), + () => + ({ + safeStorage: { + encryptString: vi.fn(), + decryptString: vi.fn(), + }, + }) as unknown as typeof Electron, +); -vi.mock('node:fs'); -vi.mock('node:fs/promises'); +vi.mock(import('node:fs')); +vi.mock(import('node:fs/promises')); let safeStorageRegistry: SafeStorageRegistry; diff --git a/packages/main/src/plugin/tasks/notification-registry.spec.ts b/packages/main/src/plugin/tasks/notification-registry.spec.ts index ee694ee4f6d..736fd5edfbf 100644 --- a/packages/main/src/plugin/tasks/notification-registry.spec.ts +++ b/packages/main/src/plugin/tasks/notification-registry.spec.ts @@ -17,6 +17,7 @@ ***********************************************************************/ import type { ApiSenderType } from '@podman-desktop/core-api/api-sender'; +import type Electron from 'electron'; import { assert, beforeEach, expect, test, vi } from 'vitest'; import { Disposable } from '/@/plugin/types/disposable.js'; @@ -42,7 +43,7 @@ beforeEach(() => { vi.resetAllMocks(); }); -vi.mock('electron', async () => { +vi.mock(import('electron'), async () => { class Notification { show(): void {} close(): void {} @@ -50,7 +51,7 @@ vi.mock('electron', async () => { return { Notification, - }; + } as unknown as typeof Electron; }); test('expect notification added to the queue', async () => { diff --git a/packages/main/src/plugin/telemetry/telemetry.spec.ts b/packages/main/src/plugin/telemetry/telemetry.spec.ts index b537864dd51..6719614fdb2 100644 --- a/packages/main/src/plugin/telemetry/telemetry.spec.ts +++ b/packages/main/src/plugin/telemetry/telemetry.spec.ts @@ -28,6 +28,8 @@ import type { LockedConfiguration } from '/@/plugin/locked-configuration.js'; import { TelemetryTrustedValue } from '/@/plugin/types/telemetry.js'; import product from '/@product.json' with { type: 'json' }; +// eslint-disable-next-line no-restricted-imports +import type * as TelemetryJSON from '../../../../../telemetry.json'; import type { EventType } from './telemetry.js'; import { Telemetry, TelemetryLoggerImpl } from './telemetry.js'; @@ -50,18 +52,22 @@ const lockedConfigurationMock = { getTelemetryInfo: vi.fn(), } as unknown as LockedConfiguration; -vi.mock('../../../../../telemetry.json', () => ({ - default: { - rules: [ - { - event: 'dropMe', - disabled: true, +vi.mock( + import('../../../../../telemetry.json'), + () => + ({ + default: { + rules: [ + { + event: 'dropMe', + disabled: true, + }, + { event: 'sometimes', ratio: 0.5 }, + { event: 'list', frequency: 'dailyPerInstance' }, + ], }, - { event: 'sometimes', ratio: 0.5 }, - { event: 'list', frequency: 'dailyPerInstance' }, - ], - }, -})); + }) as unknown as typeof TelemetryJSON, +); vi.mock(import('/@product.json')); diff --git a/packages/main/src/plugin/temp-file-service.spec.ts b/packages/main/src/plugin/temp-file-service.spec.ts index d0048ba00bf..fb62a9d157d 100644 --- a/packages/main/src/plugin/temp-file-service.spec.ts +++ b/packages/main/src/plugin/temp-file-service.spec.ts @@ -24,16 +24,16 @@ import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'; import { TempFileService } from './temp-file-service.js'; -vi.mock('node:fs/promises', () => ({ +vi.mock(import('node:fs/promises'), () => ({ writeFile: vi.fn(), unlink: vi.fn(), })); -vi.mock('node:os', () => ({ +vi.mock(import('node:os'), () => ({ tmpdir: vi.fn().mockReturnValue('/tmp'), })); -vi.mock('node:path', () => ({ +vi.mock(import('node:path'), () => ({ join: vi.fn().mockImplementation((...args) => args.join('/')), })); diff --git a/packages/main/src/plugin/tray-menu-registry.spec.ts b/packages/main/src/plugin/tray-menu-registry.spec.ts index ca7e8d34d64..ea1c5909a49 100644 --- a/packages/main/src/plugin/tray-menu-registry.spec.ts +++ b/packages/main/src/plugin/tray-menu-registry.spec.ts @@ -30,13 +30,13 @@ import { TrayMenuRegistry } from './tray-menu-registry.js'; let menuRegistry: TrayMenuRegistry; let trayMenu: TrayMenu; -vi.mock('electron', () => { +vi.mock(import('electron'), () => { return { ipcMain: { emit: vi.fn(), on: vi.fn(), }, - }; + } as unknown as typeof Electron; }); beforeAll(() => { diff --git a/packages/main/src/plugin/updater.spec.ts b/packages/main/src/plugin/updater.spec.ts index e3e60c845f4..d60d02e4c54 100644 --- a/packages/main/src/plugin/updater.spec.ts +++ b/packages/main/src/plugin/updater.spec.ts @@ -16,7 +16,8 @@ * SPDX-License-Identifier: Apache-2.0 ***********************************************************************/ -import type { IncomingMessage } from 'node:http'; +import type { ClientRequest, IncomingMessage, RequestOptions } from 'node:http'; +import { get } from 'node:https'; import type { Configuration } from '@podman-desktop/api'; import type { ApiSenderType } from '@podman-desktop/core-api/api-sender'; @@ -37,20 +38,26 @@ import * as util from '/@/util.js'; import { isLinux, isMac, isWindows } from '/@/util.js'; import product from '/@product.json' with { type: 'json' }; +// eslint-disable-next-line no-restricted-imports +import type PackageJSON from '../../../../package.json'; import type { TaskManager } from './tasks/task-manager.js'; -vi.mock('electron', () => ({ - app: { - getVersion: vi.fn(), - getPath: vi.fn(), - getAppPath: vi.fn().mockReturnValue('a-custom-appPath'), - }, - shell: { - openExternal: vi.fn(), - }, -})); +vi.mock( + import('electron'), + () => + ({ + app: { + getVersion: vi.fn(), + getPath: vi.fn(), + getAppPath: vi.fn().mockReturnValue('a-custom-appPath'), + }, + shell: { + openExternal: vi.fn(), + }, + }) as unknown as typeof Electron, +); -vi.mock('electron-updater', () => ({ +vi.mock(import('electron-updater'), () => ({ autoUpdater: { downloadUpdate: vi.fn(), quitAndInstall: vi.fn(), @@ -58,10 +65,10 @@ vi.mock('electron-updater', () => ({ on: vi.fn(), autoDownload: true, disableDifferentialDownload: false, - }, + } as unknown as AppUpdater, })); -vi.mock('/@/util.js', () => ({ +vi.mock(import('/@/util.js'), () => ({ isLinux: vi.fn(), isWindows: vi.fn(), isMac: vi.fn(), @@ -69,17 +76,12 @@ vi.mock('/@/util.js', () => ({ const getStatusCodeMock = { statusCode: 200 } as IncomingMessage; -vi.mock('https', () => ({ - get: (_: string, callback: (_: IncomingMessage) => void): void => { - callback(getStatusCodeMock); - }, -})); - -vi.mock('../../../../package.json', () => ({ +vi.mock(import('node:https')); +vi.mock(import('../../../../package.json'), () => ({ default: { homepage: 'appHomepage', repository: 'appRepo', - }, + } as unknown as typeof PackageJSON, })); vi.mock(import('/@product.json')); @@ -126,10 +128,29 @@ function mockConfiguration(options: Record): void { }); } +/** + * The {@link import(`node:https`).get} has two signature. + * We need to make a weird function to be able to typesafely mock it + */ +function getMock( + _: RequestOptions | string | URL, + arg2: RequestOptions | ((res: IncomingMessage) => void), + arg3?: (res: IncomingMessage) => void, +): ClientRequest { + if (typeof arg2 === 'function') { + arg2?.(getStatusCodeMock); + } else if (typeof arg3 === 'function') { + arg3?.(getStatusCodeMock); + } + return {} as unknown as ClientRequest; +} + beforeEach(() => { vi.useFakeTimers(); vi.resetAllMocks(); + vi.mocked(get).mockImplementation(getMock); + // Simulate PROD env vi.stubEnv('PROD', true); diff --git a/packages/main/src/plugin/util/directory-strategy.spec.ts b/packages/main/src/plugin/util/directory-strategy.spec.ts index 98c0e2e037c..1a214ec5d9b 100644 --- a/packages/main/src/plugin/util/directory-strategy.spec.ts +++ b/packages/main/src/plugin/util/directory-strategy.spec.ts @@ -25,11 +25,11 @@ import { isLinux } from '/@/util.js'; import { DirectoryStrategy } from './directory-strategy.js'; // Mock the external modules -vi.mock('node:fs', () => ({ +vi.mock(import('node:fs'), () => ({ existsSync: vi.fn(), })); -vi.mock('/@/util.js', () => ({ +vi.mock(import('/@/util.js'), () => ({ isLinux: vi.fn(), })); diff --git a/packages/main/src/plugin/util/exec.spec.ts b/packages/main/src/plugin/util/exec.spec.ts index 3a7d3cbc3e5..d78141f233a 100644 --- a/packages/main/src/plugin/util/exec.spec.ts +++ b/packages/main/src/plugin/util/exec.spec.ts @@ -27,24 +27,14 @@ import type { Mock } from 'vitest'; import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'; import type { Proxy } from '/@/plugin/proxy.js'; -import * as util from '/@/util.js'; +import { isLinux, isMac, isWindows } from '/@/util.js'; import { Exec, getInstallationPath, macosExtraPath } from './exec.js'; // Mock sudo-prompt exec to resolve everytime. -vi.mock(import('@expo/sudo-prompt'), async () => { - return { - exec: vi.fn(), - }; -}); - +vi.mock(import('@expo/sudo-prompt')); vi.mock(import('/@/util.js')); - -vi.mock('child_process', () => { - return { - spawn: vi.fn(), - }; -}); +vi.mock(import('node:child_process')); const setEncodingMock = vi.fn(); @@ -55,7 +45,6 @@ describe('exec', () => { beforeEach(() => { vi.resetAllMocks(); - vi.clearAllMocks(); }); const exec = new Exec(proxy); @@ -142,7 +131,7 @@ describe('exec', () => { test('should reject with an error when the process error event received', async () => { const command = 'nonexistent-command'; - vi.mock('child_process', () => { + vi.mock(import('node:child_process'), () => { return { spawn: vi.fn(), }; @@ -210,18 +199,12 @@ describe('exec', () => { const command = 'echo'; const args = ['Hello, World!']; const error = new Error('Error message'); - (util.isWindows as Mock).mockReturnValue(true); + vi.mocked(isWindows).mockReturnValue(true); (sudo.exec as Mock).mockImplementation((_command, _options, callback) => { callback(error); }); - vi.mock('child_process', () => { - return { - spawn: vi.fn(), - }; - }); - const execResult = exec.exec(command, args, { isAdmin: true }); await expect(execResult).rejects.toThrowError(/Failed to execute command: Error message/); @@ -341,7 +324,7 @@ describe('exec', () => { const command = 'echo'; const args = ['Hello, "World"!']; - (util.isMac as Mock).mockReturnValue(true); + vi.mocked(isMac).mockReturnValue(true); const on = vi.fn().mockImplementationOnce((event: string, cb: (arg0: string) => string) => { if (event === 'data') { @@ -377,7 +360,7 @@ describe('exec', () => { const command = 'echo'; const args = ['Hello, World!']; - (util.isLinux as Mock).mockReturnValue(true); + vi.mocked(isLinux).mockReturnValue(true); const on = vi.fn().mockImplementationOnce((event: string, cb: (arg0: string) => string) => { if (event === 'data') { @@ -410,7 +393,7 @@ describe('exec', () => { const command = 'echo'; const args = ['Hello, World!']; - (util.isLinux as Mock).mockReturnValue(true); + vi.mocked(isLinux).mockReturnValue(true); const on = vi.fn().mockImplementationOnce((event: string, cb: (arg0: string) => string) => { if (event === 'data') { @@ -446,7 +429,7 @@ describe('exec', () => { test('should run the command with privileges using exec on Windows', async () => { const command = 'echo'; const args = ['Hello, World!']; - (util.isWindows as Mock).mockReturnValue(true); + vi.mocked(isWindows).mockReturnValue(true); (sudo.exec as Mock).mockImplementation((_command, _options, callback) => { callback(undefined); @@ -477,7 +460,7 @@ describe('exec', () => { test('should run the command with privileges on Windows and remove unsupported environment', async () => { const command = 'echo'; const args = ['Hello, World!']; - (util.isWindows as Mock).mockReturnValue(true); + vi.mocked(isWindows).mockReturnValue(true); let options: | { env?: { [p: string]: string }; @@ -574,7 +557,7 @@ describe('exec', () => { const command = 'echo'; const args = ['Hello, World!']; - (util.isLinux as Mock).mockReturnValue(true); + vi.mocked(isLinux).mockReturnValue(true); const on = vi.fn().mockImplementationOnce((event: string, cb: (arg0: string) => string) => { if (event === 'data') { @@ -610,13 +593,6 @@ describe('exec', () => { }); }); -vi.mock('./util', () => { - return { - isWindows: vi.fn(), - isMac: vi.fn(), - }; -}); - describe('getInstallationPath', () => { let originalPath: string | undefined; @@ -634,8 +610,8 @@ describe('getInstallationPath', () => { skip: platform() !== 'win32', }, () => { beforeEach(() => { - vi.spyOn(util, 'isWindows').mockImplementation(() => true); - vi.spyOn(util, 'isMac').mockImplementation(() => false); + vi.mocked(isWindows).mockReturnValue(true); + vi.mocked(isMac).mockReturnValue(false); }); test('should return the installation paths for Windows', () => { @@ -672,8 +648,8 @@ describe('getInstallationPath', () => { }); test('should return the installation path for macOS', () => { - vi.spyOn(util, 'isWindows').mockImplementation(() => false); - vi.spyOn(util, 'isMac').mockImplementation(() => true); + vi.mocked(isWindows).mockReturnValue(false); + vi.mocked(isMac).mockReturnValue(true); process.env['PATH'] = '/usr/bin'; @@ -683,8 +659,8 @@ describe('getInstallationPath', () => { }); test('should return the installation path for macOS with defined param', () => { - vi.spyOn(util, 'isWindows').mockImplementation(() => false); - vi.spyOn(util, 'isMac').mockImplementation(() => true); + vi.mocked(isWindows).mockReturnValue(false); + vi.mocked(isMac).mockReturnValue(true); process.env['PATH'] = '/usr/bin'; @@ -694,8 +670,8 @@ describe('getInstallationPath', () => { }); test('should return the installation path for other platforms', () => { - vi.spyOn(util, 'isWindows').mockImplementation(() => false); - vi.spyOn(util, 'isMac').mockImplementation(() => false); + vi.mocked(isWindows).mockReturnValue(false); + vi.mocked(isMac).mockReturnValue(false); process.env['PATH'] = '/usr/bin'; // Example PATH for other platforms const path = getInstallationPath(); @@ -704,8 +680,8 @@ describe('getInstallationPath', () => { }); test('should return the installation path for other platforms with defined param', () => { - vi.spyOn(util, 'isWindows').mockImplementation(() => false); - vi.spyOn(util, 'isMac').mockImplementation(() => false); + vi.mocked(isWindows).mockReturnValue(false); + vi.mocked(isMac).mockReturnValue(false); process.env['PATH'] = '/usr/bin'; // Example PATH for other platforms const path = getInstallationPath('/usr/other'); diff --git a/packages/main/src/plugin/util/spawn-promise.spec.ts b/packages/main/src/plugin/util/spawn-promise.spec.ts index 011168b1a3b..2b3a92ba0e5 100644 --- a/packages/main/src/plugin/util/spawn-promise.spec.ts +++ b/packages/main/src/plugin/util/spawn-promise.spec.ts @@ -25,7 +25,7 @@ import { beforeEach, expect, test, vi } from 'vitest'; import { spawnWithPromise } from './spawn-promise.js'; // mock spawn -vi.mock('node:child_process', () => { +vi.mock(import('node:child_process'), () => { return { spawn: vi.fn(), }; diff --git a/packages/main/src/plugin/util/sys-info.spec.ts b/packages/main/src/plugin/util/sys-info.spec.ts index 06ba1bbb814..94cbe1c421d 100644 --- a/packages/main/src/plugin/util/sys-info.spec.ts +++ b/packages/main/src/plugin/util/sys-info.spec.ts @@ -23,13 +23,13 @@ import { beforeEach, expect, test, vi } from 'vitest'; import { getSystemInfo } from '/@/plugin/util/sys-info.js'; import { isLinux, isMac, isWindows } from '/@/util.js'; -vi.mock('/@/util.js', () => ({ +vi.mock(import('/@/util.js'), () => ({ isLinux: vi.fn(), isMac: vi.fn(), isWindows: vi.fn(), })); -vi.mock('node:os', () => ({ +vi.mock(import('node:os'), () => ({ arch: vi.fn(), release: vi.fn(), version: vi.fn(), diff --git a/packages/main/src/plugin/webview/devtools-manager.spec.ts b/packages/main/src/plugin/webview/devtools-manager.spec.ts index feb87c4450b..b74cb4ab6e0 100644 --- a/packages/main/src/plugin/webview/devtools-manager.spec.ts +++ b/packages/main/src/plugin/webview/devtools-manager.spec.ts @@ -21,14 +21,18 @@ import { beforeEach, describe, expect, test, vi } from 'vitest'; import { DevToolsManager } from './devtools-manager.js'; -vi.mock('electron', () => ({ - webContents: { - fromId: vi.fn(), - }, - BrowserWindow: { - getAllWindows: vi.fn(), - }, -})); +vi.mock( + import('electron'), + () => + ({ + webContents: { + fromId: vi.fn(), + }, + BrowserWindow: { + getAllWindows: vi.fn(), + }, + }) as unknown as typeof Electron, +); const mockWebContents = vi.mocked(webContents); const mockBrowserWindow = vi.mocked(BrowserWindow); diff --git a/packages/main/src/plugin/webview/webview-registry.spec.ts b/packages/main/src/plugin/webview/webview-registry.spec.ts index 663487ac87d..f580546e8b8 100644 --- a/packages/main/src/plugin/webview/webview-registry.spec.ts +++ b/packages/main/src/plugin/webview/webview-registry.spec.ts @@ -30,20 +30,24 @@ import type { WebviewPanelImpl } from './webview-panel-impl.js'; import { WebviewRegistry } from './webview-registry.js'; // mock node:fs -vi.mock('node:fs'); +vi.mock(import('node:fs')); // mock express dependency and default export -vi.mock('express', () => ({ - default: (): typeof express => +vi.mock( + import('express'), + () => ({ - use: vi.fn(), - listen: vi.fn().mockImplementation((_portNumber, _hostname, func: () => void) => { - func(); - return { on: vi.fn() }; - }), - on: vi.fn().mockResolvedValue(undefined), + default: (): typeof express => + ({ + use: vi.fn(), + listen: vi.fn().mockImplementation((_portNumber, _hostname, func: () => void) => { + func(); + return { on: vi.fn() }; + }), + on: vi.fn().mockResolvedValue(undefined), + }) as unknown as typeof express, }) as unknown as typeof express, -})); +); // provide a custom free port number vi.mock(import('/@/plugin/util/port.js'), () => ({ diff --git a/packages/main/src/security-restrictions.spec.ts b/packages/main/src/security-restrictions.spec.ts index 0e99037351f..c3bf995e8a7 100644 --- a/packages/main/src/security-restrictions.spec.ts +++ b/packages/main/src/security-restrictions.spec.ts @@ -27,11 +27,15 @@ import type { import { shell } from 'electron'; import { beforeEach, describe, expect, test, vi } from 'vitest'; -vi.mock('electron', () => ({ - shell: { - openExternal: vi.fn(), - }, -})); +vi.mock( + import('electron'), + () => + ({ + shell: { + openExternal: vi.fn(), + }, + }) as unknown as typeof Electron, +); const ELECTRON_APP_MOCK: ElectronApp = { on: vi.fn(), diff --git a/packages/main/src/system/macos-startup.spec.ts b/packages/main/src/system/macos-startup.spec.ts index b9c32f34cfd..6a4b696f0df 100644 --- a/packages/main/src/system/macos-startup.spec.ts +++ b/packages/main/src/system/macos-startup.spec.ts @@ -27,22 +27,22 @@ import { MacosStartup } from './macos-startup.js'; type AppGetPathParam = Parameters[0]; -vi.mock('electron', async () => { +vi.mock(import('electron'), async () => { return { app: { getPath: vi.fn(), setLoginItemSettings: vi.fn(), }, - }; + } as unknown as typeof Electron; }); -vi.mock('node:fs', async () => { +vi.mock(import('node:fs'), async () => { return { existsSync: vi.fn(), }; }); -vi.mock('node:fs/promises'); -vi.mock('node:path'); +vi.mock(import('node:fs/promises')); +vi.mock(import('node:path')); let macosStartup: MacosStartup; diff --git a/packages/main/src/system/window/window-handler.spec.ts b/packages/main/src/system/window/window-handler.spec.ts index 75693c7f7c1..193c5ca872f 100644 --- a/packages/main/src/system/window/window-handler.spec.ts +++ b/packages/main/src/system/window/window-handler.spec.ts @@ -46,12 +46,12 @@ const browserWindowMock = { getBounds: vi.fn(), } as unknown as BrowserWindow; -vi.mock('electron', async () => { +vi.mock(import('electron'), async () => { return { screen: { getDisplayMatching: vi.fn(), }, - }; + } as unknown as typeof Electron; }); beforeEach(() => { diff --git a/packages/main/src/system/windows-startup.spec.ts b/packages/main/src/system/windows-startup.spec.ts index dfe51afa5d7..b4904000c8d 100644 --- a/packages/main/src/system/windows-startup.spec.ts +++ b/packages/main/src/system/windows-startup.spec.ts @@ -26,21 +26,16 @@ import type { ConfigurationRegistry } from '/@/plugin/configuration-registry.js' import { WindowsStartup } from './windows-startup.js'; -vi.mock('electron', async () => { +vi.mock(import('electron'), async () => { return { app: { getPath: vi.fn(), setLoginItemSettings: vi.fn(), }, - }; + } as unknown as typeof Electron; }); -vi.mock('node:fs', async () => { - return { - existsSync: vi.fn(), - unlink: vi.fn(), - }; -}); +vi.mock(import('node:fs')); const minimizeOnStatup = vi.fn(); const configurationRegistry = { diff --git a/packages/main/src/tray-animate-icon.spec.ts b/packages/main/src/tray-animate-icon.spec.ts index 88bc38eb63f..c88d2ea15f3 100644 --- a/packages/main/src/tray-animate-icon.spec.ts +++ b/packages/main/src/tray-animate-icon.spec.ts @@ -45,7 +45,7 @@ const mockNativeImage = vi.hoisted(() => ({ createFromBuffer: vi.fn().mockReturnValue({ isEmpty: () => false }), })); -vi.mock('electron', async () => { +vi.mock(import('electron'), async () => { return { app: { getAppPath: (): string => 'a-custom-appPath', @@ -56,14 +56,14 @@ vi.mock('electron', async () => { shouldUseDarkColors: false, }, nativeImage: mockNativeImage, - }; + } as unknown as typeof Electron; }); -vi.mock('node:fs', () => ({ +vi.mock(import('node:fs'), () => ({ readFileSync: vi.fn().mockReturnValue(Buffer.from('')), })); -vi.mock('./util.js', () => ({ +vi.mock(import('./util.js'), () => ({ isMac: vi.fn(), isWindows: vi.fn(), })); diff --git a/packages/main/src/tray-menu.spec.ts b/packages/main/src/tray-menu.spec.ts index b7d9b114f7e..682cdb5337b 100644 --- a/packages/main/src/tray-menu.spec.ts +++ b/packages/main/src/tray-menu.spec.ts @@ -29,7 +29,7 @@ import * as util from './util.js'; let trayMenu: TrayMenu; let tray: Tray; let animatedTray: AnimatedTray; -vi.mock('electron', async () => { +vi.mock(import('electron'), async () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any const Menu = {} as unknown as any; Menu['buildFromTemplate'] = vi.fn(); @@ -42,7 +42,7 @@ vi.mock('electron', async () => { nativeImage: { createFromDataURL: vi.fn(), }, - }; + } as unknown as typeof Electron; }); beforeAll(() => { diff --git a/packages/main/src/util.spec.ts b/packages/main/src/util.spec.ts index e150be6351b..d57644099ab 100644 --- a/packages/main/src/util.spec.ts +++ b/packages/main/src/util.spec.ts @@ -23,7 +23,7 @@ import { createHash, formatName, getBase64Image, requireNonUndefined } from './u beforeEach(() => { vi.resetAllMocks(); - vi.mock('node:fs'); + vi.mock(import('node:fs')); }); test('getBase64Image - return undefined if path do not exists', () => {