From 6e5731b554d58fb8becd0ed928c5fbaeba830a30 Mon Sep 17 00:00:00 2001
From: Trim21 <trim21.me@gmail.com>
Date: Wed, 26 Feb 2025 22:18:38 +0800
Subject: [PATCH] test: migrate from jest to vitest (#34499)

---
 lib/config/decrypt/openpgp.spec.ts            |   4 +-
 lib/config/options/index.spec.ts              |   4 +-
 lib/config/presets/internal/index.spec.ts     |   2 +-
 lib/config/presets/internal/schedule.spec.ts  |  20 +-
 lib/config/presets/util.spec.ts               |   2 +-
 lib/instrumentation/decorator.spec.ts         |   2 +-
 lib/logger/index.spec.ts                      |  12 +-
 lib/logger/once.spec.ts                       |  20 +-
 lib/logger/utils.spec.ts                      |   4 +-
 lib/modules/datasource/deb/index.spec.ts      |   4 +-
 .../datasource/docker/dockerhub-cache.spec.ts |   2 +-
 lib/modules/datasource/docker/index.spec.ts   |  24 +-
 .../github-release-attachments/index.spec.ts  |   2 +-
 .../datasource/github-releases/index.spec.ts  |   4 +-
 .../datasource/github-tags/index.spec.ts      |  16 +-
 lib/modules/datasource/go/index.spec.ts       |  18 +-
 .../datasource/go/releases-direct.spec.ts     |   9 +-
 .../datasource/go/releases-goproxy.spec.ts    |   7 +-
 lib/modules/datasource/maven/index.spec.ts    |   8 +-
 .../datasource/packagist/index.spec.ts        |   4 +-
 lib/modules/datasource/pypi/index.spec.ts     |  12 +-
 .../datasource/python-version/index.spec.ts   |   2 +-
 lib/modules/datasource/utils.spec.ts          |  16 +-
 .../manager/bazel-module/extract.spec.ts      |   4 +-
 .../manager/bundler/update-locked.spec.ts     |   6 +-
 .../manager/cargo/update-locked.spec.ts       |   7 +-
 .../manager/cocoapods/artifacts.spec.ts       |   2 +-
 lib/modules/manager/copier/artifacts.spec.ts  |   4 +-
 lib/modules/manager/fleet/extract.spec.ts     |   2 +-
 .../manager/gradle-wrapper/artifacts.spec.ts  |   2 +-
 .../manager/gradle-wrapper/util.spec.ts       |   2 +-
 lib/modules/manager/gradle/artifacts.spec.ts  |   2 +-
 lib/modules/manager/gradle/extract.spec.ts    |   4 +-
 .../manager/maven-wrapper/artifacts.spec.ts   |   2 +-
 lib/modules/manager/mix/artifacts.spec.ts     |   4 +-
 lib/modules/manager/npm/artifacts.spec.ts     |   2 +-
 lib/modules/manager/npm/extract/pnpm.spec.ts  |   4 +-
 .../manager/npm/post-update/index.spec.ts     |   8 +-
 .../manager/npm/post-update/yarn.spec.ts      |   2 +-
 .../npm/update/package-version/index.spec.ts  |   2 +-
 .../manager/pep621/processors/uv.spec.ts      |  12 +-
 lib/modules/manager/poetry/artifacts.spec.ts  |   8 +-
 .../manager/terraform/lockfile/index.spec.ts  |   8 +-
 .../terraform/lockfile/update-locked.spec.ts  |   4 +-
 .../platform/azure/azure-got-wrapper.spec.ts  |   2 +-
 .../platform/azure/azure-helper.spec.ts       |  36 +--
 lib/modules/platform/azure/index.spec.ts      | 306 +++++++++---------
 lib/modules/platform/codecommit/index.spec.ts |  14 +-
 lib/modules/platform/gitea/index.spec.ts      |   8 +-
 lib/modules/platform/github/index.spec.ts     |  12 +-
 lib/modules/platform/github/scm.spec.ts       |   2 +-
 lib/renovate.spec.ts                          |   2 +-
 lib/util/cache/package/decorator.spec.ts      |  20 +-
 lib/util/date.spec.ts                         |   4 +-
 lib/util/decorator/index.spec.ts              |   4 +-
 lib/util/exec/common.spec.ts                  |   4 +-
 lib/util/exec/docker/index.spec.ts            |  21 +-
 lib/util/git/index.spec.ts                    |  32 +-
 .../package-cache-strategy.spec.ts            |   4 +-
 lib/util/github/tags.spec.ts                  |   2 +-
 .../cache/package-http-cache-provider.spec.ts |   2 +-
 lib/util/http/hooks.spec.ts                   |   2 +-
 lib/util/http/retry-after.spec.ts             |  20 +-
 lib/util/json-writer/editor-config.spec.ts    |   6 +-
 lib/util/lazy.spec.ts                         |  12 +-
 lib/util/package-rules/current-age.spec.ts    |   4 +-
 .../package-rules/current-version.spec.ts     |   2 +-
 lib/util/pretty-time.spec.ts                  |   4 +-
 lib/util/result.spec.ts                       |  16 +-
 lib/util/s3.spec.ts                           |   2 +-
 lib/util/stats.spec.ts                        |  12 +-
 lib/workers/global/config/parse/env.spec.ts   |   5 +-
 lib/workers/global/config/parse/file.spec.ts  |   6 +-
 lib/workers/global/index.spec.ts              |   8 +-
 .../config-migration/branch/create.spec.ts    |   5 +-
 .../config-migration/branch/index.spec.ts     |   4 +-
 .../config-migration/branch/rebase.spec.ts    |   5 +-
 .../repository/dependency-dashboard.spec.ts   |  12 +-
 .../repository/extract/manager-files.spec.ts  |   2 +-
 .../finalize/repository-statistics.spec.ts    |   4 +-
 lib/workers/repository/init/inherited.spec.ts |   8 +-
 lib/workers/repository/init/merge.spec.ts     |  12 +-
 .../repository/process/extract-update.spec.ts |   4 +-
 lib/workers/repository/process/index.spec.ts  |   4 +-
 .../repository/process/lookup/index.spec.ts   |  41 +--
 .../process/vulnerabilities.spec.ts           |   2 +-
 .../update/branch/automerge.spec.ts           |   2 +-
 .../update/branch/get-updated.spec.ts         |   2 +-
 .../repository/update/branch/index.spec.ts    |  14 +-
 .../update/branch/lock-files/index.spec.ts    |   8 +-
 .../repository/update/branch/schedule.spec.ts |  34 +-
 .../repository/update/pr/automerge.spec.ts    |   2 +-
 .../update/pr/changelog/github/index.spec.ts  |   2 +-
 .../update/pr/changelog/release-notes.spec.ts |   2 +-
 .../update/pr/changelog/releases.spec.ts      |   2 +-
 .../repository/update/pr/index.spec.ts        |   6 +-
 .../repository/update/pr/labels.spec.ts       |   2 +-
 .../repository/update/pr/participants.spec.ts |   8 +-
 .../repository/update/pr/pr-cache.spec.ts     |   4 +-
 test/jest-legacy.ts                           |  57 ----
 vitest.config.ts                              |   2 +-
 101 files changed, 511 insertions(+), 602 deletions(-)
 delete mode 100644 test/jest-legacy.ts

diff --git a/lib/config/decrypt/openpgp.spec.ts b/lib/config/decrypt/openpgp.spec.ts
index 272b758df0..3b5cc11800 100644
--- a/lib/config/decrypt/openpgp.spec.ts
+++ b/lib/config/decrypt/openpgp.spec.ts
@@ -16,7 +16,7 @@ describe('config/decrypt/openpgp', () => {
     });
 
     beforeEach(() => {
-      jest.resetModules();
+      vi.resetModules();
       config = {};
       GlobalConfig.reset();
     });
@@ -125,7 +125,7 @@ describe('config/decrypt/openpgp', () => {
     });
 
     it('fails to load openpgp', async () => {
-      jest.doMock('../../expose.cjs', () => ({
+      vi.doMock('../../expose.cjs', () => ({
         openpgp: () => {
           throw new Error('openpgp error');
         },
diff --git a/lib/config/options/index.spec.ts b/lib/config/options/index.spec.ts
index e0078e1f36..652031fd6e 100644
--- a/lib/config/options/index.spec.ts
+++ b/lib/config/options/index.spec.ts
@@ -6,8 +6,8 @@ vi.unmock('../../modules/platform');
 
 describe('config/options/index', () => {
   it('test manager should have no defaultConfig', () => {
-    jest.doMock('../../modules/manager', () => ({
-      getManagers: jest.fn(() => new Map().set('testManager', {})),
+    vi.doMock('../../modules/manager', () => ({
+      getManagers: vi.fn(() => new Map().set('testManager', {})),
     }));
 
     const opts = getOptions();
diff --git a/lib/config/presets/internal/index.spec.ts b/lib/config/presets/internal/index.spec.ts
index a85b009b51..651792ea8a 100644
--- a/lib/config/presets/internal/index.spec.ts
+++ b/lib/config/presets/internal/index.spec.ts
@@ -8,7 +8,7 @@ import * as internal from '.';
 vi.mock('../npm');
 vi.mock('../../../modules/datasource/npm');
 
-jest.spyOn(npm, 'getPreset').mockResolvedValue(undefined);
+vi.spyOn(npm, 'getPreset').mockResolvedValue(undefined);
 
 const ignoredPresets = ['default:group', 'default:timezone'];
 
diff --git a/lib/config/presets/internal/schedule.spec.ts b/lib/config/presets/internal/schedule.spec.ts
index 07d4ae841a..67eddb29f1 100644
--- a/lib/config/presets/internal/schedule.spec.ts
+++ b/lib/config/presets/internal/schedule.spec.ts
@@ -6,11 +6,11 @@ describe('config/presets/internal/schedule', () => {
   let config: RenovateConfig;
 
   beforeAll(() => {
-    jest.useFakeTimers();
+    vi.useFakeTimers();
   });
 
   beforeEach(() => {
-    jest.setSystemTime(new Date('2017-06-30T10:50:00.000')); // Locally 2017-06-30 10:50am
+    vi.setSystemTime(new Date('2017-06-30T10:50:00.000')); // Locally 2017-06-30 10:50am
 
     config = {};
   });
@@ -25,7 +25,7 @@ describe('config/presets/internal/schedule', () => {
       ${'2017-06-30T04:50:00.000'} | ${false}
     `('$datetime', ({ datetime, expected }) => {
       config.schedule = presets.daily.schedule;
-      jest.setSystemTime(new Date(datetime));
+      vi.setSystemTime(new Date(datetime));
       expect(isScheduledNow(config)).toBe(expected);
     });
   });
@@ -41,7 +41,7 @@ describe('config/presets/internal/schedule', () => {
       ${'2017-06-30T00:50:00.000'} | ${false}
     `('$datetime', ({ datetime, expected }) => {
       config.schedule = presets.earlyMondays.schedule;
-      jest.setSystemTime(new Date(datetime));
+      vi.setSystemTime(new Date(datetime));
       expect(isScheduledNow(config)).toBe(expected);
     });
   });
@@ -57,7 +57,7 @@ describe('config/presets/internal/schedule', () => {
       ${'2017-06-02T00:50:00.000'} | ${false}
     `('$datetime', ({ datetime, expected }) => {
       config.schedule = presets.monthly.schedule;
-      jest.setSystemTime(new Date(datetime));
+      vi.setSystemTime(new Date(datetime));
       expect(isScheduledNow(config)).toBe(expected);
     });
   });
@@ -77,7 +77,7 @@ describe('config/presets/internal/schedule', () => {
       ${'2017-06-03T09:50:00.000'} | ${true}
     `('$datetime', ({ datetime, expected }) => {
       config.schedule = presets.nonOfficeHours.schedule;
-      jest.setSystemTime(new Date(datetime));
+      vi.setSystemTime(new Date(datetime));
       expect(isScheduledNow(config)).toBe(expected);
     });
   });
@@ -96,7 +96,7 @@ describe('config/presets/internal/schedule', () => {
       ${'2017-02-01T04:50:00.000'} | ${false}
     `('$datetime', ({ datetime, expected }) => {
       config.schedule = presets.quarterly.schedule;
-      jest.setSystemTime(new Date(datetime));
+      vi.setSystemTime(new Date(datetime));
       expect(isScheduledNow(config)).toBe(expected);
     });
   });
@@ -113,7 +113,7 @@ describe('config/presets/internal/schedule', () => {
       ${'2017-06-07T11:50:00.000'} | ${true}
     `('$datetime', ({ datetime, expected }) => {
       config.schedule = presets.weekdays.schedule;
-      jest.setSystemTime(new Date(datetime));
+      vi.setSystemTime(new Date(datetime));
       expect(isScheduledNow(config)).toBe(expected);
     });
   });
@@ -130,7 +130,7 @@ describe('config/presets/internal/schedule', () => {
       ${'2017-06-07T11:50:00.000'} | ${false}
     `('$datetime', ({ datetime, expected }) => {
       config.schedule = presets.weekends.schedule;
-      jest.setSystemTime(new Date(datetime));
+      vi.setSystemTime(new Date(datetime));
       expect(isScheduledNow(config)).toBe(expected);
     });
   });
@@ -143,7 +143,7 @@ describe('config/presets/internal/schedule', () => {
       ${'2018-01-01T02:50:00.000'} | ${true}
     `('$datetime', ({ datetime, expected }) => {
       config.schedule = presets.yearly.schedule;
-      jest.setSystemTime(new Date(datetime));
+      vi.setSystemTime(new Date(datetime));
       expect(isScheduledNow(config)).toBe(expected);
     });
   });
diff --git a/lib/config/presets/util.spec.ts b/lib/config/presets/util.spec.ts
index 847718adb6..1e12e23e19 100644
--- a/lib/config/presets/util.spec.ts
+++ b/lib/config/presets/util.spec.ts
@@ -8,7 +8,7 @@ const config: FetchPresetConfig = {
   fetch: undefined as never,
 };
 
-const fetch = jest.fn(() => Promise.resolve<Preset | null>({}));
+const fetch = vi.fn(() => Promise.resolve<Preset | null>({}));
 
 describe('config/presets/util', () => {
   beforeEach(() => {
diff --git a/lib/instrumentation/decorator.spec.ts b/lib/instrumentation/decorator.spec.ts
index ff812bed6f..6b44bf76b6 100644
--- a/lib/instrumentation/decorator.spec.ts
+++ b/lib/instrumentation/decorator.spec.ts
@@ -4,7 +4,7 @@ import { disableInstrumentations } from '.';
 afterAll(disableInstrumentations);
 
 describe('instrumentation/decorator', () => {
-  const spy = jest.fn(() => Promise.resolve());
+  const spy = vi.fn(() => Promise.resolve());
 
   it('should instrument async function', async () => {
     class MyClass {
diff --git a/lib/logger/index.spec.ts b/lib/logger/index.spec.ts
index 92a61baeff..14d275789b 100644
--- a/lib/logger/index.spec.ts
+++ b/lib/logger/index.spec.ts
@@ -29,7 +29,7 @@ vi.mock('nanoid', () => ({
   nanoid: () => 'initial_context',
 }));
 
-const bunyanDebugSpy = jest.spyOn(bunyan.prototype, 'debug');
+const bunyanDebugSpy = vi.spyOn(bunyan.prototype, 'debug');
 
 describe('logger/index', () => {
   it('inits', () => {
@@ -183,8 +183,8 @@ describe('logger/index', () => {
 
   it('should create a child logger', () => {
     const childLogger = (logger as RenovateLogger).childLogger();
-    const loggerSpy = jest.spyOn(logger, 'debug');
-    const childLoggerSpy = jest.spyOn(childLogger, 'debug');
+    const loggerSpy = vi.spyOn(logger, 'debug');
+    const childLoggerSpy = vi.spyOn(childLogger, 'debug');
 
     childLogger.debug('test');
 
@@ -236,7 +236,7 @@ describe('logger/index', () => {
 
   it('supports file-based logging', () => {
     let chunk = '';
-    jest.spyOn(fs, 'createWriteStream').mockReturnValueOnce(
+    vi.spyOn(fs, 'createWriteStream').mockReturnValueOnce(
       partial<WriteStream>({
         writable: true,
         write(x: string): boolean {
@@ -259,7 +259,7 @@ describe('logger/index', () => {
 
   it('handles cycles', () => {
     let logged: Record<string, any> = {};
-    jest.spyOn(fs, 'createWriteStream').mockReturnValueOnce(
+    vi.spyOn(fs, 'createWriteStream').mockReturnValueOnce(
       partial<WriteStream>({
         writable: true,
         write(x: string): boolean {
@@ -287,7 +287,7 @@ describe('logger/index', () => {
 
   it('sanitizes secrets', () => {
     let logged: Record<string, any> = {};
-    jest.spyOn(fs, 'createWriteStream').mockReturnValueOnce(
+    vi.spyOn(fs, 'createWriteStream').mockReturnValueOnce(
       partial<WriteStream>({
         writable: true,
         write(x: string): boolean {
diff --git a/lib/logger/once.spec.ts b/lib/logger/once.spec.ts
index cddc4a752e..d08f485eed 100644
--- a/lib/logger/once.spec.ts
+++ b/lib/logger/once.spec.ts
@@ -10,7 +10,7 @@ describe('logger/once', () => {
 
   describe('core', () => {
     it('should call a function only once', () => {
-      const innerFn = jest.fn();
+      const innerFn = vi.fn();
 
       function outerFn() {
         once(innerFn);
@@ -23,8 +23,8 @@ describe('logger/once', () => {
     });
 
     it('supports support distinct calls', () => {
-      const innerFn1 = jest.fn();
-      const innerFn2 = jest.fn();
+      const innerFn1 = vi.fn();
+      const innerFn2 = vi.fn();
 
       function outerFn() {
         once(innerFn1);
@@ -39,7 +39,7 @@ describe('logger/once', () => {
     });
 
     it('resets keys', () => {
-      const innerFn = jest.fn();
+      const innerFn = vi.fn();
 
       function outerFn() {
         once(innerFn);
@@ -55,7 +55,7 @@ describe('logger/once', () => {
 
   describe('logger', () => {
     it('logs once per function call', () => {
-      const debug = jest.spyOn(logger, 'debug');
+      const debug = vi.spyOn(logger, 'debug');
 
       function doSomething() {
         logger.once.debug('test');
@@ -68,8 +68,8 @@ describe('logger/once', () => {
     });
 
     it('distincts between log levels', () => {
-      const debug = jest.spyOn(logger, 'debug');
-      const info = jest.spyOn(logger, 'info');
+      const debug = vi.spyOn(logger, 'debug');
+      const info = vi.spyOn(logger, 'info');
 
       function doSomething() {
         logger.once.debug('test');
@@ -84,7 +84,7 @@ describe('logger/once', () => {
     });
 
     it('distincts between different log statements', () => {
-      const debug = jest.spyOn(logger, 'debug');
+      const debug = vi.spyOn(logger, 'debug');
 
       function doSomething() {
         logger.once.debug('foo');
@@ -101,7 +101,7 @@ describe('logger/once', () => {
     });
 
     it('allows mixing single-time and regular logging', () => {
-      const debug = jest.spyOn(logger, 'debug');
+      const debug = vi.spyOn(logger, 'debug');
 
       function doSomething() {
         logger.once.debug('foo');
@@ -123,7 +123,7 @@ describe('logger/once', () => {
     });
 
     it('supports reset method', () => {
-      const debug = jest.spyOn(logger, 'debug');
+      const debug = vi.spyOn(logger, 'debug');
 
       function doSomething() {
         logger.once.debug('foo');
diff --git a/lib/logger/utils.spec.ts b/lib/logger/utils.spec.ts
index c9c94cb007..145140ab65 100644
--- a/lib/logger/utils.spec.ts
+++ b/lib/logger/utils.spec.ts
@@ -8,7 +8,7 @@ import prepareError, {
 
 describe('logger/utils', () => {
   afterEach(() => {
-    jest.restoreAllMocks();
+    vi.restoreAllMocks();
   });
 
   it('checks for valid log levels', () => {
@@ -29,7 +29,7 @@ describe('logger/utils', () => {
     ${' '}
   `('checks for invalid log level: $input', (input) => {
     // Mock when the function exits
-    const mockExit = jest.spyOn(process, 'exit');
+    const mockExit = vi.spyOn(process, 'exit');
     mockExit.mockImplementationOnce((number) => {
       // TODO: types (#22198)
       throw new Error(`process.exit: ${number}`);
diff --git a/lib/modules/datasource/deb/index.spec.ts b/lib/modules/datasource/deb/index.spec.ts
index a5d99419bc..069fe35067 100644
--- a/lib/modules/datasource/deb/index.spec.ts
+++ b/lib/modules/datasource/deb/index.spec.ts
@@ -31,7 +31,7 @@ describe('modules/datasource/deb/index', () => {
   let extractedPackageFile: string;
 
   beforeEach(async () => {
-    jest.resetAllMocks();
+    vi.resetAllMocks();
     debDatasource = new DebDatasource();
     cacheDir = await dir({ unsafeCleanup: true });
     GlobalConfig.set({ cacheDir: cacheDir.path });
@@ -393,7 +393,7 @@ describe('modules/datasource/deb/index', () => {
     });
 
     it('should throw error for when extracting fails', async () => {
-      jest.spyOn(fileUtils, 'extract').mockRejectedValueOnce(new Error());
+      vi.spyOn(fileUtils, 'extract').mockRejectedValueOnce(new Error());
 
       httpMock
         .scope(debBaseUrl)
diff --git a/lib/modules/datasource/docker/dockerhub-cache.spec.ts b/lib/modules/datasource/docker/dockerhub-cache.spec.ts
index 8c192c63ac..3c6d32ec53 100644
--- a/lib/modules/datasource/docker/dockerhub-cache.spec.ts
+++ b/lib/modules/datasource/docker/dockerhub-cache.spec.ts
@@ -60,7 +60,7 @@ function newCacheData(): DockerHubCacheData {
 
 describe('modules/datasource/docker/dockerhub-cache', () => {
   beforeEach(() => {
-    jest.resetAllMocks();
+    vi.resetAllMocks();
   });
 
   const dockerRepository = 'foo/bar';
diff --git a/lib/modules/datasource/docker/index.spec.ts b/lib/modules/datasource/docker/index.spec.ts
index b66dddbce4..0e45af066f 100644
--- a/lib/modules/datasource/docker/index.spec.ts
+++ b/lib/modules/datasource/docker/index.spec.ts
@@ -391,8 +391,8 @@ describe('modules/datasource/docker/index', () => {
         .reply(200, '', { 'docker-content-digest': 'some-digest' });
 
       googleAuth.GoogleAuth.mockImplementationOnce(
-        jest.fn().mockImplementationOnce(() => ({
-          getAccessToken: jest.fn().mockResolvedValue('some-token'),
+        vi.fn().mockImplementationOnce(() => ({
+          getAccessToken: vi.fn().mockResolvedValue('some-token'),
         })),
       );
 
@@ -423,8 +423,8 @@ describe('modules/datasource/docker/index', () => {
         .reply(200, '', { 'docker-content-digest': 'some-digest' });
 
       googleAuth.GoogleAuth.mockImplementationOnce(
-        jest.fn().mockImplementationOnce(() => ({
-          getAccessToken: jest.fn().mockResolvedValue('some-token'),
+        vi.fn().mockImplementationOnce(() => ({
+          getAccessToken: vi.fn().mockResolvedValue('some-token'),
         })),
       );
 
@@ -456,8 +456,8 @@ describe('modules/datasource/docker/index', () => {
         .reply(200, '', { 'docker-content-digest': 'some-digest' });
 
       googleAuth.GoogleAuth.mockImplementationOnce(
-        jest.fn().mockImplementationOnce(() => ({
-          getAccessToken: jest.fn().mockResolvedValue('some-token'),
+        vi.fn().mockImplementationOnce(() => ({
+          getAccessToken: vi.fn().mockResolvedValue('some-token'),
         })),
       );
 
@@ -487,8 +487,8 @@ describe('modules/datasource/docker/index', () => {
         .reply(200, '', { 'docker-content-digest': 'some-digest' });
 
       googleAuth.GoogleAuth.mockImplementationOnce(
-        jest.fn().mockImplementationOnce(() => ({
-          getAccessToken: jest.fn().mockResolvedValue('some-token'),
+        vi.fn().mockImplementationOnce(() => ({
+          getAccessToken: vi.fn().mockResolvedValue('some-token'),
         })),
       );
 
@@ -553,8 +553,8 @@ describe('modules/datasource/docker/index', () => {
         'www-authenticate': 'Basic realm="My Private Docker Registry Server"',
       });
       googleAuth.GoogleAuth.mockImplementationOnce(
-        jest.fn().mockImplementationOnce(() => ({
-          getAccessToken: jest.fn().mockResolvedValue(undefined),
+        vi.fn().mockImplementationOnce(() => ({
+          getAccessToken: vi.fn().mockResolvedValue(undefined),
         })),
       );
       const res = await getDigest(
@@ -574,8 +574,8 @@ describe('modules/datasource/docker/index', () => {
         'www-authenticate': 'Basic realm="My Private Docker Registry Server"',
       });
       googleAuth.GoogleAuth.mockImplementationOnce(
-        jest.fn().mockImplementationOnce(() => ({
-          getAccessToken: jest.fn().mockRejectedValue('some-error'),
+        vi.fn().mockImplementationOnce(() => ({
+          getAccessToken: vi.fn().mockRejectedValue('some-error'),
         })),
       );
       const res = await getDigest(
diff --git a/lib/modules/datasource/github-release-attachments/index.spec.ts b/lib/modules/datasource/github-release-attachments/index.spec.ts
index 8661db780d..24ea9ce477 100644
--- a/lib/modules/datasource/github-release-attachments/index.spec.ts
+++ b/lib/modules/datasource/github-release-attachments/index.spec.ts
@@ -22,7 +22,7 @@ describe('modules/datasource/github-release-attachments/index', () => {
 
   describe('getReleases', () => {
     it('returns releases', async () => {
-      jest.spyOn(githubGraphql, 'queryReleases').mockResolvedValueOnce([
+      vi.spyOn(githubGraphql, 'queryReleases').mockResolvedValueOnce([
         {
           id: 1,
           url: 'https://example.com',
diff --git a/lib/modules/datasource/github-releases/index.spec.ts b/lib/modules/datasource/github-releases/index.spec.ts
index 88a9246563..eb53476049 100644
--- a/lib/modules/datasource/github-releases/index.spec.ts
+++ b/lib/modules/datasource/github-releases/index.spec.ts
@@ -19,7 +19,7 @@ describe('modules/datasource/github-releases/index', () => {
 
   describe('getReleases', () => {
     it('returns releases', async () => {
-      jest.spyOn(githubGraphql, 'queryReleases').mockResolvedValueOnce([
+      vi.spyOn(githubGraphql, 'queryReleases').mockResolvedValueOnce([
         {
           id: 1,
           url: 'https://example.com',
@@ -98,7 +98,7 @@ describe('modules/datasource/github-releases/index', () => {
     const newDigest = 'sha-of-v15';
 
     beforeEach(() => {
-      jest.spyOn(githubGraphql, 'queryTags').mockResolvedValueOnce([
+      vi.spyOn(githubGraphql, 'queryTags').mockResolvedValueOnce([
         {
           version: 'v1.0.0',
           gitRef: 'v1.0.0',
diff --git a/lib/modules/datasource/github-tags/index.spec.ts b/lib/modules/datasource/github-tags/index.spec.ts
index 02b2d0b9dc..7b50cf012a 100644
--- a/lib/modules/datasource/github-tags/index.spec.ts
+++ b/lib/modules/datasource/github-tags/index.spec.ts
@@ -13,8 +13,8 @@ describe('modules/datasource/github-tags/index', () => {
   const github = new GithubTagsDatasource();
 
   beforeEach(() => {
-    jest.spyOn(hostRules, 'hosts').mockReturnValue([]);
-    jest.spyOn(hostRules, 'find').mockReturnValue({
+    vi.spyOn(hostRules, 'hosts').mockReturnValue([]);
+    vi.spyOn(hostRules, 'find').mockReturnValue({
       token: 'some-token',
     });
   });
@@ -52,7 +52,7 @@ describe('modules/datasource/github-tags/index', () => {
     });
 
     it('returns tagged commit digest', async () => {
-      jest.spyOn(githubGraphql, 'queryTags').mockResolvedValueOnce([
+      vi.spyOn(githubGraphql, 'queryTags').mockResolvedValueOnce([
         {
           version: 'v1.0.0',
           gitRef: 'v1.0.0',
@@ -71,7 +71,7 @@ describe('modules/datasource/github-tags/index', () => {
     });
 
     it('returns null for missing hash', async () => {
-      jest.spyOn(githubGraphql, 'queryTags').mockResolvedValueOnce([
+      vi.spyOn(githubGraphql, 'queryTags').mockResolvedValueOnce([
         {
           version: 'v1.0.0',
           gitRef: 'v1.0.0',
@@ -89,7 +89,7 @@ describe('modules/datasource/github-tags/index', () => {
     });
 
     it('returns null for missing tagged commit digest', async () => {
-      jest.spyOn(githubGraphql, 'queryTags').mockResolvedValueOnce([
+      vi.spyOn(githubGraphql, 'queryTags').mockResolvedValueOnce([
         {
           version: 'v1.0.0',
           gitRef: 'v1.0.0',
@@ -108,7 +108,7 @@ describe('modules/datasource/github-tags/index', () => {
     });
 
     it('returns null for error', async () => {
-      jest.spyOn(githubGraphql, 'queryTags').mockRejectedValueOnce('error');
+      vi.spyOn(githubGraphql, 'queryTags').mockRejectedValueOnce('error');
       const res = await github.getDigest({ packageName }, 'v3.0.0');
       expect(res).toBeNull();
     });
@@ -118,7 +118,7 @@ describe('modules/datasource/github-tags/index', () => {
     const packageName = 'some/dep2';
 
     it('returns tags', async () => {
-      jest.spyOn(githubGraphql, 'queryTags').mockResolvedValueOnce([
+      vi.spyOn(githubGraphql, 'queryTags').mockResolvedValueOnce([
         {
           version: 'v1.0.0',
           gitRef: 'v1.0.0',
@@ -132,7 +132,7 @@ describe('modules/datasource/github-tags/index', () => {
           hash: 'abc',
         },
       ]);
-      jest.spyOn(githubGraphql, 'queryReleases').mockResolvedValueOnce([
+      vi.spyOn(githubGraphql, 'queryReleases').mockResolvedValueOnce([
         {
           id: 1,
           version: 'v1.0.0',
diff --git a/lib/modules/datasource/go/index.spec.ts b/lib/modules/datasource/go/index.spec.ts
index 63bc29cacf..e700e6228f 100644
--- a/lib/modules/datasource/go/index.spec.ts
+++ b/lib/modules/datasource/go/index.spec.ts
@@ -8,16 +8,16 @@ import { GoDatasource } from '.';
 vi.mock('../../../util/host-rules', () => mockDeep());
 const hostRules = mocked(_hostRules);
 
-const getReleasesDirectMock = jest.fn();
+const getReleasesDirectMock = vi.fn();
 
-const getDigestGiteaMock = jest.fn();
-const getDigestGithubMock = jest.fn();
-const getDigestGitlabMock = jest.fn();
-const getDigestGitMock = jest.fn();
-const getDigestBitbucketMock = jest.fn();
+const getDigestGiteaMock = vi.fn();
+const getDigestGithubMock = vi.fn();
+const getDigestGitlabMock = vi.fn();
+const getDigestGitMock = vi.fn();
+const getDigestBitbucketMock = vi.fn();
 vi.mock('./releases-direct', () => {
   return {
-    GoDirectDatasource: jest.fn().mockImplementation(() => {
+    GoDirectDatasource: vi.fn().mockImplementation(() => {
       return {
         git: { getDigest: (...args: any[]) => getDigestGitMock(...args) },
         gitea: { getDigest: (...args: any[]) => getDigestGiteaMock(...args) },
@@ -32,10 +32,10 @@ vi.mock('./releases-direct', () => {
   };
 });
 
-const getReleasesProxyMock = jest.fn();
+const getReleasesProxyMock = vi.fn();
 vi.mock('./releases-goproxy', () => {
   return {
-    GoProxyDatasource: jest.fn().mockImplementation(() => {
+    GoProxyDatasource: vi.fn().mockImplementation(() => {
       return {
         getReleases: () => getReleasesProxyMock(),
       };
diff --git a/lib/modules/datasource/go/releases-direct.spec.ts b/lib/modules/datasource/go/releases-direct.spec.ts
index 7332a8a1f5..7c19c875bf 100644
--- a/lib/modules/datasource/go/releases-direct.spec.ts
+++ b/lib/modules/datasource/go/releases-direct.spec.ts
@@ -11,15 +11,12 @@ vi.mock('../../../util/host-rules', () => mockDeep());
 vi.mock('./base');
 
 const datasource = new GoDirectDatasource();
-const getDatasourceSpy = jest.spyOn(BaseGoDatasource, 'getDatasource');
+const getDatasourceSpy = vi.spyOn(BaseGoDatasource, 'getDatasource');
 const hostRules = mocked(_hostRules);
 
 describe('modules/datasource/go/releases-direct', () => {
-  const gitGetTags = jest.spyOn(GitTagsDatasource.prototype, 'getReleases');
-  const githubGetTags = jest.spyOn(
-    GithubTagsDatasource.prototype,
-    'getReleases',
-  );
+  const gitGetTags = vi.spyOn(GitTagsDatasource.prototype, 'getReleases');
+  const githubGetTags = vi.spyOn(GithubTagsDatasource.prototype, 'getReleases');
 
   beforeEach(() => {
     hostRules.find.mockReturnValue({});
diff --git a/lib/modules/datasource/go/releases-goproxy.spec.ts b/lib/modules/datasource/go/releases-goproxy.spec.ts
index 4ec469adc8..e37bea56da 100644
--- a/lib/modules/datasource/go/releases-goproxy.spec.ts
+++ b/lib/modules/datasource/go/releases-goproxy.spec.ts
@@ -14,15 +14,12 @@ vi.mock('../../../util/host-rules', () => mockDeep());
 const datasource = new GoProxyDatasource();
 
 describe('modules/datasource/go/releases-goproxy', () => {
-  const githubGetReleases = jest.spyOn(
+  const githubGetReleases = vi.spyOn(
     GithubReleasesDatasource.prototype,
     'getReleases',
   );
 
-  const githubGetTags = jest.spyOn(
-    GithubTagsDatasource.prototype,
-    'getReleases',
-  );
+  const githubGetTags = vi.spyOn(GithubTagsDatasource.prototype, 'getReleases');
 
   beforeEach(() => {
     hostRules.find.mockReturnValue({});
diff --git a/lib/modules/datasource/maven/index.spec.ts b/lib/modules/datasource/maven/index.spec.ts
index fa8b39580c..dc90eebd63 100644
--- a/lib/modules/datasource/maven/index.spec.ts
+++ b/lib/modules/datasource/maven/index.spec.ts
@@ -445,8 +445,8 @@ describe('modules/datasource/maven/index', () => {
       .reply(200, Fixtures.get('pom.xml'));
 
     googleAuth.mockImplementation(
-      jest.fn().mockImplementation(() => ({
-        getAccessToken: jest.fn().mockResolvedValue('some-token'),
+      vi.fn().mockImplementation(() => ({
+        getAccessToken: vi.fn().mockResolvedValue('some-token'),
       })),
     );
 
@@ -490,8 +490,8 @@ describe('modules/datasource/maven/index', () => {
       .reply(200, Fixtures.get('pom.xml'));
 
     googleAuth.mockImplementation(
-      jest.fn().mockImplementation(() => ({
-        getAccessToken: jest.fn().mockResolvedValue(undefined),
+      vi.fn().mockImplementation(() => ({
+        getAccessToken: vi.fn().mockResolvedValue(undefined),
       })),
     );
 
diff --git a/lib/modules/datasource/packagist/index.spec.ts b/lib/modules/datasource/packagist/index.spec.ts
index 1e61e01f6e..2aaf5c7f54 100644
--- a/lib/modules/datasource/packagist/index.spec.ts
+++ b/lib/modules/datasource/packagist/index.spec.ts
@@ -25,8 +25,8 @@ describe('modules/datasource/packagist/index', () => {
     let config: any;
 
     beforeEach(() => {
-      hostRules.find = jest.fn((input: HostRule) => input);
-      hostRules.hosts = jest.fn(() => []);
+      hostRules.find = vi.fn((input: HostRule) => input);
+      hostRules.hosts = vi.fn(() => []);
       config = {
         versioning: composerVersioning.id,
         registryUrls: [
diff --git a/lib/modules/datasource/pypi/index.spec.ts b/lib/modules/datasource/pypi/index.spec.ts
index 873dff6ad5..f557e0d40d 100644
--- a/lib/modules/datasource/pypi/index.spec.ts
+++ b/lib/modules/datasource/pypi/index.spec.ts
@@ -205,8 +205,8 @@ describe('modules/datasource/pypi/index', () => {
         ],
       };
       googleAuth.mockImplementationOnce(
-        jest.fn().mockImplementationOnce(() => ({
-          getAccessToken: jest.fn().mockResolvedValue('some-token'),
+        vi.fn().mockImplementationOnce(() => ({
+          getAccessToken: vi.fn().mockResolvedValue('some-token'),
         })),
       );
       const res = await getPkgReleases({
@@ -229,8 +229,8 @@ describe('modules/datasource/pypi/index', () => {
         ],
       };
       googleAuth.mockImplementation(
-        jest.fn().mockImplementation(() => ({
-          getAccessToken: jest.fn().mockResolvedValue(undefined),
+        vi.fn().mockImplementation(() => ({
+          getAccessToken: vi.fn().mockResolvedValue(undefined),
         })),
       );
       const res = await getPkgReleases({
@@ -779,8 +779,8 @@ describe('modules/datasource/pypi/index', () => {
       ],
     };
     googleAuth.mockImplementationOnce(
-      jest.fn().mockImplementationOnce(() => ({
-        getAccessToken: jest.fn().mockResolvedValue('some-token'),
+      vi.fn().mockImplementationOnce(() => ({
+        getAccessToken: vi.fn().mockResolvedValue('some-token'),
       })),
     );
     expect(
diff --git a/lib/modules/datasource/python-version/index.spec.ts b/lib/modules/datasource/python-version/index.spec.ts
index dea8e2d351..a0f45aba72 100644
--- a/lib/modules/datasource/python-version/index.spec.ts
+++ b/lib/modules/datasource/python-version/index.spec.ts
@@ -32,7 +32,7 @@ describe('modules/datasource/python-version/index', () => {
         .get('/api/python.json')
         .reply(200, Fixtures.get('eol.json'));
 
-      jest.spyOn(githubGraphql, 'queryReleases').mockResolvedValueOnce([
+      vi.spyOn(githubGraphql, 'queryReleases').mockResolvedValueOnce([
         {
           id: 1,
           url: 'https://example.com',
diff --git a/lib/modules/datasource/utils.spec.ts b/lib/modules/datasource/utils.spec.ts
index 69c10432b4..c0389d0796 100644
--- a/lib/modules/datasource/utils.spec.ts
+++ b/lib/modules/datasource/utils.spec.ts
@@ -27,8 +27,8 @@ describe('modules/datasource/utils', () => {
 
   it('retrieves a Google Access token', async () => {
     googleAuth.mockImplementationOnce(
-      jest.fn().mockImplementationOnce(() => ({
-        getAccessToken: jest.fn().mockResolvedValue('some-token'),
+      vi.fn().mockImplementationOnce(() => ({
+        getAccessToken: vi.fn().mockResolvedValue('some-token'),
       })),
     );
 
@@ -38,8 +38,8 @@ describe('modules/datasource/utils', () => {
 
   it('no Google Access token results in null', async () => {
     googleAuth.mockImplementationOnce(
-      jest.fn().mockImplementationOnce(() => ({
-        getAccessToken: jest.fn().mockReturnValue(''),
+      vi.fn().mockImplementationOnce(() => ({
+        getAccessToken: vi.fn().mockReturnValue(''),
       })),
     );
 
@@ -50,8 +50,8 @@ describe('modules/datasource/utils', () => {
   it('Google Access token error throws an exception', async () => {
     const err = 'some-error';
     googleAuth.mockImplementationOnce(
-      jest.fn().mockImplementationOnce(() => ({
-        getAccessToken: jest.fn().mockRejectedValue(new Error(err)),
+      vi.fn().mockImplementationOnce(() => ({
+        getAccessToken: vi.fn().mockRejectedValue(new Error(err)),
       })),
     );
 
@@ -60,8 +60,8 @@ describe('modules/datasource/utils', () => {
 
   it('Google Access token could not load default credentials', async () => {
     googleAuth.mockImplementationOnce(
-      jest.fn().mockImplementationOnce(() => ({
-        getAccessToken: jest.fn().mockRejectedValue({
+      vi.fn().mockImplementationOnce(() => ({
+        getAccessToken: vi.fn().mockRejectedValue({
           message: 'Could not load the default credentials',
         }),
       })),
diff --git a/lib/modules/manager/bazel-module/extract.spec.ts b/lib/modules/manager/bazel-module/extract.spec.ts
index 794286d4bb..16c621586d 100644
--- a/lib/modules/manager/bazel-module/extract.spec.ts
+++ b/lib/modules/manager/bazel-module/extract.spec.ts
@@ -18,7 +18,7 @@ describe('modules/manager/bazel-module/extract', () => {
   describe('extractPackageFile()', () => {
     beforeEach(() => {
       GlobalConfig.set(adminConfig);
-      jest.restoreAllMocks();
+      vi.restoreAllMocks();
     });
 
     it('returns null if fails to parse', async () => {
@@ -30,7 +30,7 @@ describe('modules/manager/bazel-module/extract', () => {
     });
 
     it('returns null if something throws an error', async () => {
-      jest.spyOn(parser, 'parse').mockImplementationOnce(() => {
+      vi.spyOn(parser, 'parse').mockImplementationOnce(() => {
         throw new Error('Test error');
       });
       const result = await extractPackageFile('content', 'MODULE.bazel');
diff --git a/lib/modules/manager/bundler/update-locked.spec.ts b/lib/modules/manager/bundler/update-locked.spec.ts
index a0566ef66b..c062859c0b 100644
--- a/lib/modules/manager/bundler/update-locked.spec.ts
+++ b/lib/modules/manager/bundler/update-locked.spec.ts
@@ -62,9 +62,9 @@ describe('modules/manager/bundler/update-locked', () => {
       newVersion: '5.2.0',
       currentVersion: '5.1.9',
     };
-    jest
-      .spyOn(lockedVersion, 'extractLockFileEntries')
-      .mockReturnValueOnce(new Error() as never);
+    vi.spyOn(lockedVersion, 'extractLockFileEntries').mockReturnValueOnce(
+      new Error() as never,
+    );
     expect(updateLockedDependency(config).status).toBe('update-failed');
   });
 });
diff --git a/lib/modules/manager/cargo/update-locked.spec.ts b/lib/modules/manager/cargo/update-locked.spec.ts
index c3ba15d26b..5747e4828b 100644
--- a/lib/modules/manager/cargo/update-locked.spec.ts
+++ b/lib/modules/manager/cargo/update-locked.spec.ts
@@ -62,9 +62,10 @@ describe('modules/manager/cargo/update-locked', () => {
       newVersion: '1.0.3',
       currentVersion: '1.0.0',
     };
-    jest
-      .spyOn(lockedVersion, 'extractLockFileContentVersions')
-      .mockReturnValueOnce(new Error() as never);
+    vi.spyOn(
+      lockedVersion,
+      'extractLockFileContentVersions',
+    ).mockReturnValueOnce(new Error() as never);
     expect(updateLockedDependency(config).status).toBe('update-failed');
   });
 });
diff --git a/lib/modules/manager/cocoapods/artifacts.spec.ts b/lib/modules/manager/cocoapods/artifacts.spec.ts
index 54ae7e7c48..4c5a9ff7cd 100644
--- a/lib/modules/manager/cocoapods/artifacts.spec.ts
+++ b/lib/modules/manager/cocoapods/artifacts.spec.ts
@@ -32,7 +32,7 @@ const adminConfig: RepoGlobalConfig = {
 describe('modules/manager/cocoapods/artifacts', () => {
   beforeEach(() => {
     env.getChildProcessEnv.mockReturnValue(envMock.basic);
-    jest.spyOn(docker, 'removeDockerContainer').mockResolvedValue();
+    vi.spyOn(docker, 'removeDockerContainer').mockResolvedValue();
     // can't be mocked
     docker.resetPrefetchedImages();
 
diff --git a/lib/modules/manager/copier/artifacts.spec.ts b/lib/modules/manager/copier/artifacts.spec.ts
index 1c3ffff417..f378aa79c9 100644
--- a/lib/modules/manager/copier/artifacts.spec.ts
+++ b/lib/modules/manager/copier/artifacts.spec.ts
@@ -1,7 +1,7 @@
 import { mockDeep } from 'jest-mock-extended';
 import { join } from 'upath';
 import { mockExecAll } from '../../../../test/exec-util';
-import { fs, git, hostRules, mocked, partial } from '../../../../test/util';
+import { fs, git, hostRules, partial } from '../../../../test/util';
 import { GlobalConfig } from '../../../config/global';
 import type { RepoGlobalConfig } from '../../../config/types';
 import { logger } from '../../../logger';
@@ -10,7 +10,7 @@ import * as _datasource from '../../datasource';
 import type { UpdateArtifactsConfig, Upgrade } from '../types';
 import { updateArtifacts } from '.';
 
-const datasource = mocked(_datasource);
+const datasource = vi.mocked(_datasource);
 
 vi.mock('../../../util/git');
 vi.mock('../../../util/fs');
diff --git a/lib/modules/manager/fleet/extract.spec.ts b/lib/modules/manager/fleet/extract.spec.ts
index 100cada8ee..bf820af95f 100644
--- a/lib/modules/manager/fleet/extract.spec.ts
+++ b/lib/modules/manager/fleet/extract.spec.ts
@@ -14,7 +14,7 @@ const configMapYaml = Fixtures.get('configmap.yaml', '../kubernetes');
 
 describe('modules/manager/fleet/extract', () => {
   afterEach(() => {
-    jest.restoreAllMocks();
+    vi.restoreAllMocks();
   });
 
   describe('extractPackageFile()', () => {
diff --git a/lib/modules/manager/gradle-wrapper/artifacts.spec.ts b/lib/modules/manager/gradle-wrapper/artifacts.spec.ts
index f362aa6875..89b7092c23 100644
--- a/lib/modules/manager/gradle-wrapper/artifacts.spec.ts
+++ b/lib/modules/manager/gradle-wrapper/artifacts.spec.ts
@@ -42,7 +42,7 @@ const config: UpdateArtifactsConfig = {
   newValue: '5.6.4',
 };
 
-const osPlatformSpy = jest.spyOn(os, 'platform');
+const osPlatformSpy = vi.spyOn(os, 'platform');
 
 describe('modules/manager/gradle-wrapper/artifacts', () => {
   beforeEach(() => {
diff --git a/lib/modules/manager/gradle-wrapper/util.spec.ts b/lib/modules/manager/gradle-wrapper/util.spec.ts
index 3160f8f1de..2782c0d8e6 100644
--- a/lib/modules/manager/gradle-wrapper/util.spec.ts
+++ b/lib/modules/manager/gradle-wrapper/util.spec.ts
@@ -11,7 +11,7 @@ import {
   prepareGradleCommand,
 } from './utils';
 
-const platform = jest.spyOn(os, 'platform');
+const platform = vi.spyOn(os, 'platform');
 vi.mock('../../../util/fs');
 
 describe('modules/manager/gradle-wrapper/util', () => {
diff --git a/lib/modules/manager/gradle/artifacts.spec.ts b/lib/modules/manager/gradle/artifacts.spec.ts
index dc96f38f4d..a8c6372dc9 100644
--- a/lib/modules/manager/gradle/artifacts.spec.ts
+++ b/lib/modules/manager/gradle/artifacts.spec.ts
@@ -39,7 +39,7 @@ const adminConfig: RepoGlobalConfig = {
   dockerSidecarImage: 'ghcr.io/containerbase/sidecar',
 };
 
-const osPlatformSpy = jest.spyOn(os, 'platform');
+const osPlatformSpy = vi.spyOn(os, 'platform');
 
 describe('modules/manager/gradle/artifacts', () => {
   beforeEach(() => {
diff --git a/lib/modules/manager/gradle/extract.spec.ts b/lib/modules/manager/gradle/extract.spec.ts
index 49476cf9d4..2a8f5d0a0e 100644
--- a/lib/modules/manager/gradle/extract.spec.ts
+++ b/lib/modules/manager/gradle/extract.spec.ts
@@ -31,7 +31,7 @@ function mockFs(files: Record<string, string>): void {
 
 describe('modules/manager/gradle/extract', () => {
   beforeEach(() => {
-    jest.restoreAllMocks();
+    vi.restoreAllMocks();
   });
 
   it('returns null', async () => {
@@ -57,7 +57,7 @@ describe('modules/manager/gradle/extract', () => {
     };
     mockFs(fsMock);
 
-    jest.spyOn(parser, 'parseGradle').mockImplementationOnce(() => {
+    vi.spyOn(parser, 'parseGradle').mockImplementationOnce(() => {
       throw err;
     });
     await extractAllPackageFiles(partial<ExtractConfig>(), [filename]);
diff --git a/lib/modules/manager/maven-wrapper/artifacts.spec.ts b/lib/modules/manager/maven-wrapper/artifacts.spec.ts
index 2f8a691441..7c548640e1 100644
--- a/lib/modules/manager/maven-wrapper/artifacts.spec.ts
+++ b/lib/modules/manager/maven-wrapper/artifacts.spec.ts
@@ -17,7 +17,7 @@ vi.mock('../../datasource', () => mockDeep());
 
 process.env.CONTAINERBASE = 'true';
 
-const osPlatformSpy = jest.spyOn(os, 'platform');
+const osPlatformSpy = vi.spyOn(os, 'platform');
 
 function mockMavenFileChangedInGit(fileName = 'maven-wrapper.properties') {
   git.getRepoStatus.mockResolvedValueOnce(
diff --git a/lib/modules/manager/mix/artifacts.spec.ts b/lib/modules/manager/mix/artifacts.spec.ts
index f0c6f59896..7f133a3293 100644
--- a/lib/modules/manager/mix/artifacts.spec.ts
+++ b/lib/modules/manager/mix/artifacts.spec.ts
@@ -89,7 +89,7 @@ describe('modules/manager/mix/artifacts', () => {
   });
 
   it('returns updated mix.lock', async () => {
-    jest.spyOn(docker, 'removeDanglingContainers').mockResolvedValueOnce();
+    vi.spyOn(docker, 'removeDanglingContainers').mockResolvedValueOnce();
     GlobalConfig.set({
       ...adminConfig,
       binarySource: 'docker',
@@ -164,7 +164,7 @@ describe('modules/manager/mix/artifacts', () => {
   });
 
   it('authenticates to private repositories in updated dependecies', async () => {
-    jest.spyOn(docker, 'removeDanglingContainers').mockResolvedValueOnce();
+    vi.spyOn(docker, 'removeDanglingContainers').mockResolvedValueOnce();
     GlobalConfig.set({
       ...adminConfig,
       binarySource: 'docker',
diff --git a/lib/modules/manager/npm/artifacts.spec.ts b/lib/modules/manager/npm/artifacts.spec.ts
index 3fef88de7c..e2672ae091 100644
--- a/lib/modules/manager/npm/artifacts.spec.ts
+++ b/lib/modules/manager/npm/artifacts.spec.ts
@@ -39,7 +39,7 @@ const validDepUpdate = {
 } satisfies Upgrade<Record<string, unknown>>;
 
 describe('modules/manager/npm/artifacts', () => {
-  const spyProcessHostRules = jest.spyOn(rules, 'processHostRules');
+  const spyProcessHostRules = vi.spyOn(rules, 'processHostRules');
 
   beforeEach(() => {
     env.getChildProcessEnv.mockReturnValue({
diff --git a/lib/modules/manager/npm/extract/pnpm.spec.ts b/lib/modules/manager/npm/extract/pnpm.spec.ts
index 17c57f4920..d1352c0c15 100644
--- a/lib/modules/manager/npm/extract/pnpm.spec.ts
+++ b/lib/modules/manager/npm/extract/pnpm.spec.ts
@@ -21,7 +21,7 @@ describe('modules/manager/npm/extract/pnpm', () => {
   });
 
   beforeEach(() => {
-    jest.restoreAllMocks();
+    vi.restoreAllMocks();
   });
 
   describe('.extractPnpmFilters()', () => {
@@ -43,7 +43,7 @@ describe('modules/manager/npm/extract/pnpm', () => {
     });
 
     it('detects errors when opening pnpm-workspace.yml file', async () => {
-      jest.spyOn(yaml, 'parseSingleYaml').mockImplementationOnce(() => {
+      vi.spyOn(yaml, 'parseSingleYaml').mockImplementationOnce(() => {
         throw new Error();
       });
 
diff --git a/lib/modules/manager/npm/post-update/index.spec.ts b/lib/modules/manager/npm/post-update/index.spec.ts
index 10b15d8ca6..9fe1a6ac06 100644
--- a/lib/modules/manager/npm/post-update/index.spec.ts
+++ b/lib/modules/manager/npm/post-update/index.spec.ts
@@ -374,10 +374,10 @@ describe('modules/manager/npm/post-update/index', () => {
   });
 
   describe('getAdditionalFiles()', () => {
-    const spyNpm = jest.spyOn(npm, 'generateLockFile');
-    const spyYarn = jest.spyOn(yarn, 'generateLockFile');
-    const spyPnpm = jest.spyOn(pnpm, 'generateLockFile');
-    const spyProcessHostRules = jest.spyOn(rules, 'processHostRules');
+    const spyNpm = vi.spyOn(npm, 'generateLockFile');
+    const spyYarn = vi.spyOn(yarn, 'generateLockFile');
+    const spyPnpm = vi.spyOn(pnpm, 'generateLockFile');
+    const spyProcessHostRules = vi.spyOn(rules, 'processHostRules');
 
     beforeEach(() => {
       spyNpm.mockResolvedValue({});
diff --git a/lib/modules/manager/npm/post-update/yarn.spec.ts b/lib/modules/manager/npm/post-update/yarn.spec.ts
index 9dd1414108..141b36e13e 100644
--- a/lib/modules/manager/npm/post-update/yarn.spec.ts
+++ b/lib/modules/manager/npm/post-update/yarn.spec.ts
@@ -42,7 +42,7 @@ const plocktest1YarnLockV1 = Fixtures.get('plocktest1/yarn.lock', '..');
 env.getChildProcessEnv.mockReturnValue(envMock.basic);
 
 describe('modules/manager/npm/post-update/yarn', () => {
-  const removeDockerContainer = jest.spyOn(docker, 'removeDockerContainer');
+  const removeDockerContainer = vi.spyOn(docker, 'removeDockerContainer');
 
   beforeEach(() => {
     delete process.env.BUILDPACK;
diff --git a/lib/modules/manager/npm/update/package-version/index.spec.ts b/lib/modules/manager/npm/update/package-version/index.spec.ts
index 155228c5ab..b18f568cad 100644
--- a/lib/modules/manager/npm/update/package-version/index.spec.ts
+++ b/lib/modules/manager/npm/update/package-version/index.spec.ts
@@ -57,7 +57,7 @@ describe('modules/manager/npm/update/package-version/index', () => {
     });
 
     it('returns content if bumping errors', async () => {
-      jest.doMock('semver', () => ({
+      vi.doMock('semver', () => ({
         inc: () => {
           throw new Error('semver inc');
         },
diff --git a/lib/modules/manager/pep621/processors/uv.spec.ts b/lib/modules/manager/pep621/processors/uv.spec.ts
index f407eb9e48..d413e20804 100644
--- a/lib/modules/manager/pep621/processors/uv.spec.ts
+++ b/lib/modules/manager/pep621/processors/uv.spec.ts
@@ -480,8 +480,8 @@ describe('modules/manager/pep621/processors/uv', () => {
         password: 'pass',
       });
       googleAuth.mockImplementationOnce(
-        jest.fn().mockImplementationOnce(() => ({
-          getAccessToken: jest.fn().mockResolvedValue('some-token'),
+        vi.fn().mockImplementationOnce(() => ({
+          getAccessToken: vi.fn().mockResolvedValue('some-token'),
         })),
       );
       fs.getSiblingFileName.mockReturnValueOnce('uv.lock');
@@ -611,8 +611,8 @@ describe('modules/manager/pep621/processors/uv', () => {
         password: 'pass',
       });
       googleAuth.mockImplementation(
-        jest.fn().mockImplementation(() => ({
-          getAccessToken: jest.fn().mockResolvedValue(undefined),
+        vi.fn().mockImplementation(() => ({
+          getAccessToken: vi.fn().mockResolvedValue(undefined),
         })),
       );
       fs.getSiblingFileName.mockReturnValueOnce('uv.lock');
@@ -710,8 +710,8 @@ describe('modules/manager/pep621/processors/uv', () => {
       const execSnapshots = mockExecAll();
       GlobalConfig.set(adminConfig);
       googleAuth.mockImplementation(
-        jest.fn().mockImplementation(() => ({
-          getAccessToken: jest.fn().mockResolvedValue(undefined),
+        vi.fn().mockImplementation(() => ({
+          getAccessToken: vi.fn().mockResolvedValue(undefined),
         })),
       );
       fs.getSiblingFileName.mockReturnValueOnce('uv.lock');
diff --git a/lib/modules/manager/poetry/artifacts.spec.ts b/lib/modules/manager/poetry/artifacts.spec.ts
index 9946674197..978a8d34bc 100644
--- a/lib/modules/manager/poetry/artifacts.spec.ts
+++ b/lib/modules/manager/poetry/artifacts.spec.ts
@@ -235,8 +235,8 @@ describe('modules/manager/poetry/artifacts', () => {
       const execSnapshots = mockExecAll();
       fs.readLocalFile.mockResolvedValueOnce('New poetry.lock');
       googleAuth.mockImplementationOnce(
-        jest.fn().mockImplementationOnce(() => ({
-          getAccessToken: jest.fn().mockResolvedValue('some-token'),
+        vi.fn().mockImplementationOnce(() => ({
+          getAccessToken: vi.fn().mockResolvedValue('some-token'),
         })),
       );
       hostRules.find.mockReturnValue({});
@@ -281,8 +281,8 @@ describe('modules/manager/poetry/artifacts', () => {
       const execSnapshots = mockExecAll();
       fs.readLocalFile.mockResolvedValueOnce('New poetry.lock');
       googleAuth.mockImplementation(
-        jest.fn().mockImplementation(() => ({
-          getAccessToken: jest.fn().mockResolvedValue(undefined),
+        vi.fn().mockImplementation(() => ({
+          getAccessToken: vi.fn().mockResolvedValue(undefined),
         })),
       );
       const updatedDeps = [{ depName: 'dep1' }];
diff --git a/lib/modules/manager/terraform/lockfile/index.spec.ts b/lib/modules/manager/terraform/lockfile/index.spec.ts
index a630b257d7..5093b0b99d 100644
--- a/lib/modules/manager/terraform/lockfile/index.spec.ts
+++ b/lib/modules/manager/terraform/lockfile/index.spec.ts
@@ -1,7 +1,7 @@
 import { codeBlock } from 'common-tags';
 import { mockDeep } from 'jest-mock-extended';
 import { join } from 'upath';
-import { fs, mocked } from '../../../../../test/util';
+import { fs } from '../../../../../test/util';
 import { GlobalConfig } from '../../../../config/global';
 import { getPkgReleases } from '../../../datasource';
 import type { UpdateArtifactsConfig } from '../../types';
@@ -25,10 +25,8 @@ const adminConfig = {
   containerbaseDir: join('/tmp/renovate/cache/containerbase'),
 };
 
-const mockHash = mocked(TerraformProviderHash).createHashes;
-const mockGetPkgReleases = getPkgReleases as jest.MockedFunction<
-  typeof getPkgReleases
->;
+const mockHash = vi.mocked(TerraformProviderHash).createHashes;
+const mockGetPkgReleases = vi.mocked(getPkgReleases);
 
 describe('modules/manager/terraform/lockfile/index', () => {
   beforeEach(() => {
diff --git a/lib/modules/manager/terraform/lockfile/update-locked.spec.ts b/lib/modules/manager/terraform/lockfile/update-locked.spec.ts
index 0c69b74692..95f8100fa7 100644
--- a/lib/modules/manager/terraform/lockfile/update-locked.spec.ts
+++ b/lib/modules/manager/terraform/lockfile/update-locked.spec.ts
@@ -88,9 +88,7 @@ describe('modules/manager/terraform/lockfile/update-locked', () => {
       newVersion: '3.1.0',
       currentVersion: '3.0.0',
     };
-    jest
-      .spyOn(utilFns, 'extractLocks')
-      .mockReturnValueOnce(new Error() as never);
+    vi.spyOn(utilFns, 'extractLocks').mockReturnValueOnce(new Error() as never);
     expect(updateLockedDependency(config).status).toBe('update-failed');
   });
 });
diff --git a/lib/modules/platform/azure/azure-got-wrapper.spec.ts b/lib/modules/platform/azure/azure-got-wrapper.spec.ts
index 57c21e0a0d..0c9522619d 100644
--- a/lib/modules/platform/azure/azure-got-wrapper.spec.ts
+++ b/lib/modules/platform/azure/azure-got-wrapper.spec.ts
@@ -6,7 +6,7 @@ describe('modules/platform/azure/azure-got-wrapper', () => {
 
   beforeEach(async () => {
     // reset module
-    jest.resetModules();
+    vi.resetModules();
     hostRules = await import('../../../util/host-rules');
     azure = await import('./azure-got-wrapper');
   });
diff --git a/lib/modules/platform/azure/azure-helper.spec.ts b/lib/modules/platform/azure/azure-helper.spec.ts
index 2abae10362..5bb19fb44d 100644
--- a/lib/modules/platform/azure/azure-helper.spec.ts
+++ b/lib/modules/platform/azure/azure-helper.spec.ts
@@ -14,7 +14,7 @@ describe('modules/platform/azure/azure-helper', () => {
 
   beforeEach(async () => {
     // reset module
-    jest.resetModules();
+    vi.resetModules();
     azureHelper = await import('./azure-helper');
     azureApi = await vi.importMock('./azure-got-wrapper');
   });
@@ -24,7 +24,7 @@ describe('modules/platform/azure/azure-helper', () => {
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            getRefs: jest.fn(() => [{ objectId: 132 }]),
+            getRefs: vi.fn(() => [{ objectId: 132 }]),
           }) as any,
       );
       const res = await azureHelper.getRefs('123', 'branch');
@@ -35,7 +35,7 @@ describe('modules/platform/azure/azure-helper', () => {
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            getRefs: jest.fn(() => []),
+            getRefs: vi.fn(() => []),
           }) as any,
       );
       const res = await azureHelper.getRefs('123');
@@ -46,7 +46,7 @@ describe('modules/platform/azure/azure-helper', () => {
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            getRefs: jest.fn(() => [{ objectId: '132' }]),
+            getRefs: vi.fn(() => [{ objectId: '132' }]),
           }) as any,
       );
       const res = await azureHelper.getRefs('123', 'refs/head/branch1');
@@ -59,7 +59,7 @@ describe('modules/platform/azure/azure-helper', () => {
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            getRefs: jest.fn(() => [{ objectId: '132' }]),
+            getRefs: vi.fn(() => [{ objectId: '132' }]),
           }) as any,
       );
       const res = await azureHelper.getAzureBranchObj(
@@ -74,7 +74,7 @@ describe('modules/platform/azure/azure-helper', () => {
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            getRefs: jest.fn(() => []),
+            getRefs: vi.fn(() => []),
           }) as any,
       );
       const res = await azureHelper.getAzureBranchObj('123', 'branchName');
@@ -100,7 +100,7 @@ describe('modules/platform/azure/azure-helper', () => {
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            getItemText: jest.fn(() => mockEventStream),
+            getItemText: vi.fn(() => mockEventStream),
           }) as any,
       );
 
@@ -129,7 +129,7 @@ describe('modules/platform/azure/azure-helper', () => {
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            getItemText: jest.fn(() => mockEventStream),
+            getItemText: vi.fn(() => mockEventStream),
           }) as any,
       );
 
@@ -158,7 +158,7 @@ describe('modules/platform/azure/azure-helper', () => {
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            getItemText: jest.fn(() => mockEventStream),
+            getItemText: vi.fn(() => mockEventStream),
           }) as any,
       );
 
@@ -174,7 +174,7 @@ describe('modules/platform/azure/azure-helper', () => {
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            getItemText: jest.fn(() => ({
+            getItemText: vi.fn(() => ({
               readable: false,
             })),
           }) as any,
@@ -194,7 +194,7 @@ describe('modules/platform/azure/azure-helper', () => {
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            getCommit: jest.fn(() => ({
+            getCommit: vi.fn(() => ({
               parents: ['123456'],
             })),
           }) as any,
@@ -209,7 +209,7 @@ describe('modules/platform/azure/azure-helper', () => {
       azureApi.policyApi.mockImplementationOnce(
         () =>
           ({
-            getPolicyConfigurations: jest.fn(() => []),
+            getPolicyConfigurations: vi.fn(() => []),
           }) as any,
       );
       expect(await azureHelper.getMergeMethod('', '')).toEqual(
@@ -221,7 +221,7 @@ describe('modules/platform/azure/azure-helper', () => {
       azureApi.policyApi.mockImplementationOnce(
         () =>
           ({
-            getPolicyConfigurations: jest.fn(() => [
+            getPolicyConfigurations: vi.fn(() => [
               {
                 settings: {
                   allowSquash: true,
@@ -248,7 +248,7 @@ describe('modules/platform/azure/azure-helper', () => {
 
       azureApi.policyApi.mockResolvedValueOnce(
         partial<IPolicyApi>({
-          getPolicyConfigurations: jest.fn(() =>
+          getPolicyConfigurations: vi.fn(() =>
             Promise.resolve([
               partial<PolicyConfiguration>({
                 settings: {
@@ -276,7 +276,7 @@ describe('modules/platform/azure/azure-helper', () => {
       azureApi.policyApi.mockImplementationOnce(
         () =>
           ({
-            getPolicyConfigurations: jest.fn(() => [
+            getPolicyConfigurations: vi.fn(() => [
               {
                 settings: {
                   allowSquash: true,
@@ -317,7 +317,7 @@ describe('modules/platform/azure/azure-helper', () => {
       azureApi.policyApi.mockImplementationOnce(
         () =>
           ({
-            getPolicyConfigurations: jest.fn(() => [
+            getPolicyConfigurations: vi.fn(() => [
               {
                 settings: {
                   allowSquash: true,
@@ -386,7 +386,7 @@ describe('modules/platform/azure/azure-helper', () => {
       azureApi.policyApi.mockImplementationOnce(
         () =>
           ({
-            getPolicyConfigurations: jest.fn(() => [
+            getPolicyConfigurations: vi.fn(() => [
               {
                 settings: {
                   allowSquash: true,
@@ -449,7 +449,7 @@ describe('modules/platform/azure/azure-helper', () => {
       azureApi.coreApi.mockImplementationOnce(
         () =>
           ({
-            getTeams: jest
+            getTeams: vi
               .fn()
               .mockResolvedValueOnce(team1)
               .mockResolvedValueOnce(team2),
diff --git a/lib/modules/platform/azure/index.spec.ts b/lib/modules/platform/azure/index.spec.ts
index 42fc899387..953aaca777 100644
--- a/lib/modules/platform/azure/index.spec.ts
+++ b/lib/modules/platform/azure/index.spec.ts
@@ -8,6 +8,8 @@ import {
   PullRequestStatus,
 } from 'azure-devops-node-api/interfaces/GitInterfaces.js';
 import { mockDeep } from 'jest-mock-extended';
+import type { Mocked, MockedObject } from 'vitest';
+import { vi } from 'vitest';
 import { partial } from '../../../../test/util';
 import {
   REPOSITORY_ARCHIVED,
@@ -29,16 +31,16 @@ vi.mock('../../../util/sanitize', () =>
 vi.mock('timers/promises');
 
 describe('modules/platform/azure/index', () => {
-  let hostRules: jest.Mocked<typeof _hostRules>;
+  let hostRules: Mocked<typeof _hostRules>;
   let azure: Platform;
-  let azureApi: jest.Mocked<typeof import('./azure-got-wrapper')>;
-  let azureHelper: jest.Mocked<typeof import('./azure-helper')>;
-  let git: jest.Mocked<typeof _git>;
-  let logger: jest.MockedObject<typeof _logger>;
+  let azureApi: Mocked<typeof import('./azure-got-wrapper')>;
+  let azureHelper: Mocked<typeof import('./azure-helper')>;
+  let git: Mocked<typeof _git>;
+  let logger: MockedObject<typeof _logger>;
 
   beforeEach(async () => {
     // reset module
-    jest.resetModules();
+    vi.resetModules();
     hostRules = await vi.importMock('../../../util/host-rules');
     azure = await import('.');
     azureApi = await vi.importMock('./azure-got-wrapper');
@@ -62,7 +64,7 @@ describe('modules/platform/azure/index', () => {
     azureApi.gitApi.mockImplementationOnce(
       () =>
         ({
-          getRepositories: jest.fn(() => [
+          getRepositories: vi.fn(() => [
             {
               name: 'repo1',
               project: {
@@ -148,7 +150,7 @@ describe('modules/platform/azure/index', () => {
   function initRepo(args?: Partial<RepoParams> | string) {
     azureApi.gitApi.mockResolvedValueOnce(
       partial<IGitApi>({
-        getRepositories: jest.fn().mockResolvedValue([
+        getRepositories: vi.fn().mockResolvedValue([
           {
             name: 'repo',
             id: '1',
@@ -219,7 +221,7 @@ describe('modules/platform/azure/index', () => {
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            getPullRequests: jest
+            getPullRequests: vi
               .fn()
               .mockReturnValue([])
               .mockReturnValueOnce([
@@ -231,7 +233,7 @@ describe('modules/platform/azure/index', () => {
                   status: PullRequestStatus.Active,
                 },
               ]),
-            getPullRequestCommits: jest.fn().mockReturnValue([]),
+            getPullRequestCommits: vi.fn().mockReturnValue([]),
           }) as any,
       );
       const res = await azure.findPr({
@@ -260,7 +262,7 @@ describe('modules/platform/azure/index', () => {
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            getPullRequests: jest
+            getPullRequests: vi
               .fn()
               .mockReturnValue([])
               .mockReturnValueOnce([
@@ -272,7 +274,7 @@ describe('modules/platform/azure/index', () => {
                   status: PullRequestStatus.Completed,
                 },
               ]),
-            getPullRequestCommits: jest.fn().mockReturnValue([]),
+            getPullRequestCommits: vi.fn().mockReturnValue([]),
           }) as any,
       );
       const res = await azure.findPr({
@@ -301,7 +303,7 @@ describe('modules/platform/azure/index', () => {
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            getPullRequests: jest
+            getPullRequests: vi
               .fn()
               .mockReturnValue([])
               .mockReturnValueOnce([
@@ -313,7 +315,7 @@ describe('modules/platform/azure/index', () => {
                   status: PullRequestStatus.Abandoned,
                 },
               ]),
-            getPullRequestCommits: jest.fn().mockReturnValue([]),
+            getPullRequestCommits: vi.fn().mockReturnValue([]),
           }) as any,
       );
       const res = await azure.findPr({
@@ -342,7 +344,7 @@ describe('modules/platform/azure/index', () => {
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            getPullRequests: jest
+            getPullRequests: vi
               .fn()
               .mockReturnValue([])
               .mockReturnValueOnce([
@@ -354,7 +356,7 @@ describe('modules/platform/azure/index', () => {
                   status: PullRequestStatus.Abandoned,
                 },
               ]),
-            getPullRequestCommits: jest.fn().mockReturnValue([]),
+            getPullRequestCommits: vi.fn().mockReturnValue([]),
           }) as any,
       );
       const res = await azure.findPr({
@@ -381,7 +383,7 @@ describe('modules/platform/azure/index', () => {
     it('returns pr if found matches targetBranch', async () => {
       azureApi.gitApi.mockResolvedValueOnce(
         partial<IGitApi>({
-          getPullRequests: jest
+          getPullRequests: vi
             .fn()
             .mockReturnValue([])
             .mockReturnValueOnce([
@@ -400,7 +402,7 @@ describe('modules/platform/azure/index', () => {
                 status: PullRequestStatus.Active,
               },
             ]),
-          getPullRequestCommits: jest.fn().mockReturnValue([]),
+          getPullRequestCommits: vi.fn().mockReturnValue([]),
         }),
       );
       const res = await azure.findPr({
@@ -429,7 +431,7 @@ describe('modules/platform/azure/index', () => {
     it('returns first pr if found does not match targetBranch', async () => {
       azureApi.gitApi.mockResolvedValueOnce(
         partial<IGitApi>({
-          getPullRequests: jest
+          getPullRequests: vi
             .fn()
             .mockReturnValue([])
             .mockReturnValueOnce([
@@ -448,7 +450,7 @@ describe('modules/platform/azure/index', () => {
                 status: PullRequestStatus.Active,
               },
             ]),
-          getPullRequestCommits: jest.fn().mockReturnValue([]),
+          getPullRequestCommits: vi.fn().mockReturnValue([]),
         }),
       );
       const res = await azure.findPr({
@@ -477,7 +479,7 @@ describe('modules/platform/azure/index', () => {
     it('catches errors', async () => {
       azureApi.gitApi.mockResolvedValueOnce(
         partial<IGitApi>({
-          getPullRequests: jest.fn().mockRejectedValueOnce(new Error()),
+          getPullRequests: vi.fn().mockRejectedValueOnce(new Error()),
         }),
       );
       const res = await azure.findPr({
@@ -493,7 +495,7 @@ describe('modules/platform/azure/index', () => {
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            getPullRequests: jest.fn(() => []),
+            getPullRequests: vi.fn(() => []),
           }) as any,
       );
       expect(await azure.getPrList()).toEqual([]);
@@ -505,7 +507,7 @@ describe('modules/platform/azure/index', () => {
       await initRepo({ repository: 'some/repo' });
       azureApi.gitApi.mockResolvedValue(
         partial<IGitApi>({
-          getPullRequests: jest.fn().mockResolvedValueOnce([]),
+          getPullRequests: vi.fn().mockResolvedValueOnce([]),
         }),
       );
       const pr = await azure.getBranchPr('somebranch');
@@ -516,7 +518,7 @@ describe('modules/platform/azure/index', () => {
       await initRepo({ repository: 'some/repo' });
       azureApi.gitApi.mockResolvedValue(
         partial<IGitApi>({
-          getPullRequests: jest
+          getPullRequests: vi
             .fn()
             .mockResolvedValueOnce([
               {
@@ -528,7 +530,7 @@ describe('modules/platform/azure/index', () => {
               },
             ])
             .mockResolvedValueOnce([]),
-          getPullRequestLabels: jest.fn().mockResolvedValue([]),
+          getPullRequestLabels: vi.fn().mockResolvedValue([]),
         }),
       );
       const pr = await azure.getBranchPr('branch-a', 'branch-b');
@@ -557,8 +559,8 @@ describe('modules/platform/azure/index', () => {
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            getBranch: jest.fn(() => ({ commit: { commitId: 'abcd1234' } })),
-            getStatuses: jest.fn(() => [
+            getBranch: vi.fn(() => ({ commit: { commitId: 'abcd1234' } })),
+            getStatuses: vi.fn(() => [
               {
                 state: GitStatusState.Succeeded,
                 context: { genre: 'a-genre', name: 'a-name' },
@@ -578,8 +580,8 @@ describe('modules/platform/azure/index', () => {
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            getBranch: jest.fn(() => ({ commit: { commitId: 'abcd1234' } })),
-            getStatuses: jest.fn(() => [
+            getBranch: vi.fn(() => ({ commit: { commitId: 'abcd1234' } })),
+            getStatuses: vi.fn(() => [
               {
                 state: GitStatusState.NotApplicable,
                 context: { genre: 'a-genre', name: 'a-name' },
@@ -599,8 +601,8 @@ describe('modules/platform/azure/index', () => {
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            getBranch: jest.fn(() => ({ commit: { commitId: 'abcd1234' } })),
-            getStatuses: jest.fn(() => [
+            getBranch: vi.fn(() => ({ commit: { commitId: 'abcd1234' } })),
+            getStatuses: vi.fn(() => [
               {
                 state: GitStatusState.Failed,
                 context: { genre: 'a-genre', name: 'a-name' },
@@ -620,8 +622,8 @@ describe('modules/platform/azure/index', () => {
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            getBranch: jest.fn(() => ({ commit: { commitId: 'abcd1234' } })),
-            getStatuses: jest.fn(() => [
+            getBranch: vi.fn(() => ({ commit: { commitId: 'abcd1234' } })),
+            getStatuses: vi.fn(() => [
               {
                 state: GitStatusState.Error,
                 context: { genre: 'a-genre', name: 'a-name' },
@@ -641,8 +643,8 @@ describe('modules/platform/azure/index', () => {
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            getBranch: jest.fn(() => ({ commit: { commitId: 'abcd1234' } })),
-            getStatuses: jest.fn(() => [
+            getBranch: vi.fn(() => ({ commit: { commitId: 'abcd1234' } })),
+            getStatuses: vi.fn(() => [
               {
                 state: GitStatusState.Pending,
                 context: { genre: 'a-genre', name: 'a-name' },
@@ -662,8 +664,8 @@ describe('modules/platform/azure/index', () => {
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            getBranch: jest.fn(() => ({ commit: { commitId: 'abcd1234' } })),
-            getStatuses: jest.fn(() => [
+            getBranch: vi.fn(() => ({ commit: { commitId: 'abcd1234' } })),
+            getStatuses: vi.fn(() => [
               {
                 state: GitStatusState.NotSet,
                 context: { genre: 'a-genre', name: 'a-name' },
@@ -682,10 +684,10 @@ describe('modules/platform/azure/index', () => {
       await initRepo({ repository: 'some/repo' });
       azureApi.gitApi.mockResolvedValueOnce(
         partial<IGitApi>({
-          getBranch: jest
+          getBranch: vi
             .fn()
             .mockResolvedValue({ commit: { commitId: 'abcd1234' } }),
-          getStatuses: jest.fn().mockResolvedValue([
+          getStatuses: vi.fn().mockResolvedValue([
             {
               state: -1,
               context: { genre: 'a-genre', name: 'a-name' },
@@ -705,8 +707,8 @@ describe('modules/platform/azure/index', () => {
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            getBranch: jest.fn(() => ({ commit: { commitId: 'abcd1234' } })),
-            getStatuses: jest.fn(() => [
+            getBranch: vi.fn(() => ({ commit: { commitId: 'abcd1234' } })),
+            getStatuses: vi.fn(() => [
               {
                 state: GitStatusState.Pending,
                 context: { genre: 'another-genre', name: 'a-name' },
@@ -728,8 +730,8 @@ describe('modules/platform/azure/index', () => {
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            getBranch: jest.fn(() => ({ commit: { commitId: 'abcd1234' } })),
-            getStatuses: jest.fn(() => [
+            getBranch: vi.fn(() => ({ commit: { commitId: 'abcd1234' } })),
+            getStatuses: vi.fn(() => [
               {
                 state: GitStatusState.Succeeded,
                 context: { genre: 'renovate' },
@@ -746,8 +748,8 @@ describe('modules/platform/azure/index', () => {
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            getBranch: jest.fn(() => ({ commit: { commitId: 'abcd1234' } })),
-            getStatuses: jest.fn(() => [
+            getBranch: vi.fn(() => ({ commit: { commitId: 'abcd1234' } })),
+            getStatuses: vi.fn(() => [
               {
                 state: GitStatusState.Succeeded,
                 context: { genre: 'renovate' },
@@ -764,8 +766,8 @@ describe('modules/platform/azure/index', () => {
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            getBranch: jest.fn(() => ({ commit: { commitId: 'abcd1234' } })),
-            getStatuses: jest.fn(() => [{ state: GitStatusState.Error }]),
+            getBranch: vi.fn(() => ({ commit: { commitId: 'abcd1234' } })),
+            getStatuses: vi.fn(() => [{ state: GitStatusState.Error }]),
           }) as any,
       );
       const res = await azure.getBranchStatus('somebranch', true);
@@ -777,8 +779,8 @@ describe('modules/platform/azure/index', () => {
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            getBranch: jest.fn(() => ({ commit: { commitId: 'abcd1234' } })),
-            getStatuses: jest.fn(() => [{ state: GitStatusState.Pending }]),
+            getBranch: vi.fn(() => ({ commit: { commitId: 'abcd1234' } })),
+            getStatuses: vi.fn(() => [{ state: GitStatusState.Pending }]),
           }) as any,
       );
       const res = await azure.getBranchStatus('somebranch', true);
@@ -790,8 +792,8 @@ describe('modules/platform/azure/index', () => {
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            getBranch: jest.fn(() => ({ commit: { commitId: 'abcd1234' } })),
-            getStatuses: jest.fn(() => []),
+            getBranch: vi.fn(() => ({ commit: { commitId: 'abcd1234' } })),
+            getStatuses: vi.fn(() => []),
           }) as any,
       );
       const res = await azure.getBranchStatus('somebranch', true);
@@ -810,7 +812,7 @@ describe('modules/platform/azure/index', () => {
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            getPullRequests: jest.fn(() => []),
+            getPullRequests: vi.fn(() => []),
           }) as any,
       );
       const pr = await azure.getPr(1234);
@@ -822,7 +824,7 @@ describe('modules/platform/azure/index', () => {
       azureApi.gitApi.mockImplementation(
         () =>
           ({
-            getPullRequests: jest
+            getPullRequests: vi
               .fn()
               .mockReturnValue([])
               .mockReturnValueOnce([
@@ -830,10 +832,10 @@ describe('modules/platform/azure/index', () => {
                   pullRequestId: 1234,
                 },
               ]),
-            getPullRequestLabels: jest
+            getPullRequestLabels: vi
               .fn()
               .mockReturnValue([{ active: true, name: 'renovate' }]),
-            getPullRequestCommits: jest.fn().mockReturnValue([
+            getPullRequestCommits: vi.fn().mockReturnValue([
               {
                 author: {
                   name: 'renovate',
@@ -853,10 +855,10 @@ describe('modules/platform/azure/index', () => {
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            createPullRequest: jest.fn(() => ({
+            createPullRequest: vi.fn(() => ({
               pullRequestId: 456,
             })),
-            createPullRequestLabel: jest.fn(() => ({})),
+            createPullRequestLabel: vi.fn(() => ({})),
           }) as any,
       );
       const pr = await azure.createPr({
@@ -874,10 +876,10 @@ describe('modules/platform/azure/index', () => {
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            createPullRequest: jest.fn(() => ({
+            createPullRequest: vi.fn(() => ({
               pullRequestId: 456,
             })),
-            createPullRequestLabel: jest.fn(() => ({})),
+            createPullRequestLabel: vi.fn(() => ({})),
           }) as any,
       );
       const pr = await azure.createPr({
@@ -911,11 +913,11 @@ describe('modules/platform/azure/index', () => {
             mergeCommitMessage: 'The Title',
           },
         };
-        const updateFn = jest.fn().mockResolvedValue(prUpdateResult);
+        const updateFn = vi.fn().mockResolvedValue(prUpdateResult);
         azureApi.gitApi.mockResolvedValueOnce(
           partial<IGitApi>({
-            createPullRequest: jest.fn().mockResolvedValue(prResult),
-            createPullRequestLabel: jest.fn().mockResolvedValue({}),
+            createPullRequest: vi.fn().mockResolvedValue(prResult),
+            createPullRequestLabel: vi.fn().mockResolvedValue({}),
             updatePullRequest: updateFn,
           }),
         );
@@ -973,9 +975,7 @@ describe('modules/platform/azure/index', () => {
             },
           },
         ];
-        const updateFn = jest.fn(() =>
-          Promise.resolve(prUpdateResults.shift()!),
-        );
+        const updateFn = vi.fn(() => Promise.resolve(prUpdateResults.shift()!));
 
         azureHelper.getMergeMethod.mockResolvedValueOnce(
           GitPullRequestMergeStrategy.Squash,
@@ -983,10 +983,8 @@ describe('modules/platform/azure/index', () => {
 
         azureApi.gitApi.mockResolvedValue(
           partial<IGitApi>({
-            createPullRequest: jest.fn(() =>
-              Promise.resolve(prResult.shift()!),
-            ),
-            createPullRequestLabel: jest.fn().mockResolvedValue({}),
+            createPullRequest: vi.fn(() => Promise.resolve(prResult.shift()!)),
+            createPullRequestLabel: vi.fn().mockResolvedValue({}),
             updatePullRequest: updateFn,
           }),
         );
@@ -1046,12 +1044,12 @@ describe('modules/platform/azure/index', () => {
               mergeCommitMessage: 'The Title',
             },
           };
-          const updateFn = jest.fn(() => Promise.resolve(prUpdateResults));
+          const updateFn = vi.fn(() => Promise.resolve(prUpdateResults));
 
           azureApi.gitApi.mockResolvedValue(
             partial<IGitApi>({
-              createPullRequest: jest.fn(() => Promise.resolve(prResult)),
-              createPullRequestLabel: jest.fn().mockResolvedValue({}),
+              createPullRequest: vi.fn(() => Promise.resolve(prResult)),
+              createPullRequestLabel: vi.fn().mockResolvedValue({}),
               updatePullRequest: updateFn,
             }),
           );
@@ -1099,11 +1097,11 @@ describe('modules/platform/azure/index', () => {
               mergeCommitMessage: 'The Title',
             },
           };
-          const updateFn = jest.fn().mockResolvedValue(prUpdateResult);
+          const updateFn = vi.fn().mockResolvedValue(prUpdateResult);
           azureApi.gitApi.mockResolvedValueOnce(
             partial<IGitApi>({
-              createPullRequest: jest.fn().mockResolvedValue(prResult),
-              createPullRequestLabel: jest.fn().mockResolvedValue({}),
+              createPullRequest: vi.fn().mockResolvedValue(prResult),
+              createPullRequestLabel: vi.fn().mockResolvedValue({}),
               updatePullRequest: updateFn,
             }),
           );
@@ -1146,14 +1144,14 @@ describe('modules/platform/azure/index', () => {
         isFlagged: false,
         isRequired: false,
       };
-      const updateFn = jest
+      const updateFn = vi
         .fn(() => prUpdateResult)
         .mockName('createPullRequestReviewer');
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            createPullRequest: jest.fn(() => prResult),
-            createPullRequestLabel: jest.fn(() => ({})),
+            createPullRequest: vi.fn(() => prResult),
+            createPullRequestLabel: vi.fn(() => ({})),
             createPullRequestReviewer: updateFn,
           }) as any,
       );
@@ -1173,7 +1171,7 @@ describe('modules/platform/azure/index', () => {
   describe('updatePr(prNo, title, body, platformPrOptions)', () => {
     it('should update the PR', async () => {
       await initRepo({ repository: 'some/repo' });
-      const updatePullRequest = jest.fn(() => ({}));
+      const updatePullRequest = vi.fn(() => ({}));
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
@@ -1194,13 +1192,13 @@ describe('modules/platform/azure/index', () => {
       azureApi.gitApi.mockImplementation(
         () =>
           ({
-            createPullRequest: jest.fn(() => ({
+            createPullRequest: vi.fn(() => ({
               pullRequestId: 456,
               title: 'Title 1',
             })),
-            createPullRequestLabel: jest.fn(() => ({})),
-            getPullRequests: jest.fn(() => []),
-            updatePullRequest: jest.fn(() => ({
+            createPullRequestLabel: vi.fn(() => ({})),
+            getPullRequests: vi.fn(() => []),
+            updatePullRequest: vi.fn(() => ({
               pullRequestId: 456,
               title: 'Title 2',
             })),
@@ -1227,7 +1225,7 @@ describe('modules/platform/azure/index', () => {
 
     it('should update the PR without description', async () => {
       await initRepo({ repository: 'some/repo' });
-      const updatePullRequest = jest.fn(() => ({}));
+      const updatePullRequest = vi.fn(() => ({}));
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
@@ -1243,7 +1241,7 @@ describe('modules/platform/azure/index', () => {
 
     it('should close the PR', async () => {
       await initRepo({ repository: 'some/repo' });
-      const updatePullRequest = jest.fn(() => ({}));
+      const updatePullRequest = vi.fn(() => ({}));
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
@@ -1261,7 +1259,7 @@ describe('modules/platform/azure/index', () => {
 
     it('should reopen the PR', async () => {
       await initRepo({ repository: 'some/repo' });
-      const updatePullRequest = jest.fn(() => ({}));
+      const updatePullRequest = vi.fn(() => ({}));
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
@@ -1292,13 +1290,13 @@ describe('modules/platform/azure/index', () => {
         isFlagged: false,
         isRequired: false,
       };
-      const updateFn = jest.fn(() => prUpdateResult);
+      const updateFn = vi.fn(() => prUpdateResult);
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            updatePullRequest: jest.fn(() => prResult),
+            updatePullRequest: vi.fn(() => prResult),
             createPullRequestReviewer: updateFn,
-            getPullRequestById: jest.fn(() => ({
+            getPullRequestById: vi.fn(() => ({
               pullRequestId: prResult.pullRequestId,
               createdBy: prResult.createdBy,
             })),
@@ -1319,14 +1317,14 @@ describe('modules/platform/azure/index', () => {
     it('adds comment if missing', async () => {
       await initRepo({ repository: 'some/repo' });
       const gitApiMock = {
-        createThread: jest.fn(() => [{ id: 123 }]),
-        getThreads: jest.fn().mockReturnValue([
+        createThread: vi.fn(() => [{ id: 123 }]),
+        getThreads: vi.fn().mockReturnValue([
           {
             comments: [{ content: 'end-user comment', id: 1 }],
             id: 2,
           },
         ]),
-        updateComment: jest.fn(() => ({ id: 123 })),
+        updateComment: vi.fn(() => ({ id: 123 })),
       };
       azureApi.gitApi.mockImplementation(() => gitApiMock as any);
       await azure.ensureComment({
@@ -1341,8 +1339,8 @@ describe('modules/platform/azure/index', () => {
     it('updates comment if missing', async () => {
       await initRepo({ repository: 'some/repo' });
       const gitApiMock = {
-        createThread: jest.fn(() => [{ id: 123 }]),
-        getThreads: jest.fn().mockReturnValue([
+        createThread: vi.fn(() => [{ id: 123 }]),
+        getThreads: vi.fn().mockReturnValue([
           {
             comments: [{ content: 'end-user comment', id: 1 }],
             id: 3,
@@ -1352,7 +1350,7 @@ describe('modules/platform/azure/index', () => {
             id: 4,
           },
         ]),
-        updateComment: jest.fn(() => ({ id: 123 })),
+        updateComment: vi.fn(() => ({ id: 123 })),
       };
       azureApi.gitApi.mockImplementation(() => gitApiMock as any);
       await azure.ensureComment({
@@ -1367,8 +1365,8 @@ describe('modules/platform/azure/index', () => {
     it('does nothing if comment exists and is the same', async () => {
       await initRepo({ repository: 'some/repo' });
       const gitApiMock = {
-        createThread: jest.fn(() => [{ id: 123 }]),
-        getThreads: jest.fn().mockReturnValue([
+        createThread: vi.fn(() => [{ id: 123 }]),
+        getThreads: vi.fn().mockReturnValue([
           {
             comments: [{ content: 'end-user comment', id: 1 }],
             id: 3,
@@ -1378,7 +1376,7 @@ describe('modules/platform/azure/index', () => {
             id: 4,
           },
         ]),
-        updateComment: jest.fn(() => ({ id: 123 })),
+        updateComment: vi.fn(() => ({ id: 123 })),
       };
       azureApi.gitApi.mockImplementation(() => gitApiMock as any);
       await azure.ensureComment({
@@ -1393,14 +1391,14 @@ describe('modules/platform/azure/index', () => {
     it('does nothing if comment exists and is the same when there is no topic', async () => {
       await initRepo({ repository: 'some/repo' });
       const gitApiMock = {
-        createThread: jest.fn(() => [{ id: 123 }]),
-        getThreads: jest.fn().mockReturnValue([
+        createThread: vi.fn(() => [{ id: 123 }]),
+        getThreads: vi.fn().mockReturnValue([
           {
             comments: [{ content: 'some\ncontent', id: 2 }],
             id: 4,
           },
         ]),
-        updateComment: jest.fn(() => ({ id: 123 })),
+        updateComment: vi.fn(() => ({ id: 123 })),
       };
       azureApi.gitApi.mockImplementation(() => gitApiMock as any);
       await azure.ensureComment({
@@ -1415,14 +1413,14 @@ describe('modules/platform/azure/index', () => {
     it('passes comment through massageMarkdown', async () => {
       await initRepo({ repository: 'some/repo' });
       const gitApiMock = {
-        createThread: jest.fn().mockResolvedValue([{ id: 123 }]),
-        getThreads: jest.fn().mockResolvedValue([
+        createThread: vi.fn().mockResolvedValue([{ id: 123 }]),
+        getThreads: vi.fn().mockResolvedValue([
           {
             comments: [{ content: 'end-user comment', id: 1 }],
             id: 2,
           },
         ]),
-        updateComment: jest.fn().mockResolvedValue({ id: 123 }),
+        updateComment: vi.fn().mockResolvedValue({ id: 123 }),
       };
       azureApi.gitApi.mockResolvedValue(partial<IGitApi>(gitApiMock));
 
@@ -1449,7 +1447,7 @@ describe('modules/platform/azure/index', () => {
 
     beforeEach(() => {
       gitApiMock = {
-        getThreads: jest.fn(() => [
+        getThreads: vi.fn(() => [
           {
             comments: [{ content: '### some-subject\n\nblabla' }],
             id: 123,
@@ -1459,7 +1457,7 @@ describe('modules/platform/azure/index', () => {
             id: 124,
           },
         ]),
-        updateThread: jest.fn(),
+        updateThread: vi.fn(),
       };
       azureApi.gitApi.mockImplementation(() => gitApiMock);
     });
@@ -1514,20 +1512,20 @@ describe('modules/platform/azure/index', () => {
       azureApi.gitApi.mockImplementation(
         () =>
           ({
-            getRepositories: jest.fn(() => [{ id: '1', project: { id: 2 } }]),
-            createThread: jest.fn(() => [{ id: 123 }]),
-            getThreads: jest.fn(() => []),
+            getRepositories: vi.fn(() => [{ id: '1', project: { id: 2 } }]),
+            createThread: vi.fn(() => [{ id: 123 }]),
+            getThreads: vi.fn(() => []),
           }) as any,
       );
       azureApi.coreApi.mockImplementation(
         () =>
           ({
-            getTeamMembersWithExtendedProperties: jest.fn(() => [
+            getTeamMembersWithExtendedProperties: vi.fn(() => [
               { identity: { displayName: 'jyc', uniqueName: 'jyc', id: 123 } },
             ]),
           }) as any,
       );
-      azureHelper.getAllProjectTeams = jest.fn().mockReturnValue([
+      azureHelper.getAllProjectTeams = vi.fn().mockReturnValue([
         { id: 3, name: 'abc' },
         { id: 4, name: 'def' },
       ]);
@@ -1542,19 +1540,19 @@ describe('modules/platform/azure/index', () => {
       azureApi.gitApi.mockImplementation(
         () =>
           ({
-            getRepositories: jest.fn(() => [{ id: '1', project: { id: 2 } }]),
-            createPullRequestReviewer: jest.fn(),
+            getRepositories: vi.fn(() => [{ id: '1', project: { id: 2 } }]),
+            createPullRequestReviewer: vi.fn(),
           }) as any,
       );
       azureApi.coreApi.mockImplementation(
         () =>
           ({
-            getTeamMembersWithExtendedProperties: jest.fn(() => [
+            getTeamMembersWithExtendedProperties: vi.fn(() => [
               { identity: { displayName: 'jyc', uniqueName: 'jyc', id: 123 } },
             ]),
           }) as any,
       );
-      azureHelper.getAllProjectTeams = jest.fn().mockReturnValue([
+      azureHelper.getAllProjectTeams = vi.fn().mockReturnValue([
         { id: 3, name: 'abc' },
         { id: 4, name: 'def' },
       ]);
@@ -1568,19 +1566,19 @@ describe('modules/platform/azure/index', () => {
       azureApi.gitApi.mockImplementation(
         () =>
           ({
-            getRepositories: jest.fn(() => [{ id: '1', project: { id: 2 } }]),
-            createPullRequestReviewer: jest.fn(),
+            getRepositories: vi.fn(() => [{ id: '1', project: { id: 2 } }]),
+            createPullRequestReviewer: vi.fn(),
           }) as any,
       );
       azureApi.coreApi.mockImplementation(
         () =>
           ({
-            getTeamMembersWithExtendedProperties: jest.fn(() => [
+            getTeamMembersWithExtendedProperties: vi.fn(() => [
               { identity: { displayName: 'jyc', uniqueName: 'jyc', id: 123 } },
             ]),
           }) as any,
       );
-      azureHelper.getAllProjectTeams = jest.fn().mockReturnValue([
+      azureHelper.getAllProjectTeams = vi.fn().mockReturnValue([
         { id: 3, name: 'abc' },
         { id: 4, name: 'def' },
       ]);
@@ -1613,11 +1611,11 @@ describe('modules/platform/azure/index', () => {
   describe('setBranchStatus', () => {
     it('should build and call the create status api properly', async () => {
       await initRepo({ repository: 'some/repo' });
-      const createCommitStatusMock = jest.fn();
+      const createCommitStatusMock = vi.fn();
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            getBranch: jest.fn(() => ({ commit: { commitId: 'abcd1234' } })),
+            getBranch: vi.fn(() => ({ commit: { commitId: 'abcd1234' } })),
             createCommitStatus: createCommitStatusMock,
           }) as any,
       );
@@ -1645,11 +1643,11 @@ describe('modules/platform/azure/index', () => {
 
     it('should build and call the create status api properly with a complex context', async () => {
       await initRepo({ repository: 'some/repo' });
-      const createCommitStatusMock = jest.fn();
+      const createCommitStatusMock = vi.fn();
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            getBranch: jest.fn(() => ({ commit: { commitId: 'abcd1234' } })),
+            getBranch: vi.fn(() => ({ commit: { commitId: 'abcd1234' } })),
             createCommitStatus: createCommitStatusMock,
           }) as any,
       );
@@ -1682,13 +1680,13 @@ describe('modules/platform/azure/index', () => {
       const pullRequestIdMock = 12345;
       const branchNameMock = 'test';
       const lastMergeSourceCommitMock = { commitId: 'abcd1234' };
-      const updatePullRequestMock = jest.fn(() => ({
+      const updatePullRequestMock = vi.fn(() => ({
         status: 3,
       }));
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            getPullRequestById: jest.fn(() => ({
+            getPullRequestById: vi.fn(() => ({
               lastMergeSourceCommit: lastMergeSourceCommitMock,
               targetRefName: 'refs/heads/ding',
               title: 'title',
@@ -1697,7 +1695,7 @@ describe('modules/platform/azure/index', () => {
           }) as any,
       );
 
-      azureHelper.getMergeMethod = jest
+      azureHelper.getMergeMethod = vi
         .fn()
         .mockReturnValue(GitPullRequestMergeStrategy.Squash);
 
@@ -1736,13 +1734,13 @@ describe('modules/platform/azure/index', () => {
         const pullRequestIdMock = 12345;
         const branchNameMock = 'test';
         const lastMergeSourceCommitMock = { commitId: 'abcd1234' };
-        const updatePullRequestMock = jest.fn(() => ({
+        const updatePullRequestMock = vi.fn(() => ({
           status: 3,
         }));
         azureApi.gitApi.mockImplementationOnce(
           () =>
             ({
-              getPullRequestById: jest.fn(() => ({
+              getPullRequestById: vi.fn(() => ({
                 lastMergeSourceCommit: lastMergeSourceCommitMock,
                 targetRefName: 'refs/heads/ding',
                 title: 'title',
@@ -1751,7 +1749,7 @@ describe('modules/platform/azure/index', () => {
             }) as any,
         );
 
-        azureHelper.getMergeMethod = jest.fn().mockReturnValue(prMergeStrategy);
+        azureHelper.getMergeMethod = vi.fn().mockReturnValue(prMergeStrategy);
 
         const res = await azure.mergePr({
           branchName: branchNameMock,
@@ -1784,16 +1782,16 @@ describe('modules/platform/azure/index', () => {
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            getPullRequestById: jest.fn(() => ({
+            getPullRequestById: vi.fn(() => ({
               lastMergeSourceCommit: lastMergeSourceCommitMock,
             })),
-            updatePullRequest: jest
+            updatePullRequest: vi
               .fn()
               .mockRejectedValue(new Error(`oh no pr couldn't be updated`)),
           }) as any,
       );
 
-      azureHelper.getMergeMethod = jest
+      azureHelper.getMergeMethod = vi
         .fn()
         .mockReturnValue(GitPullRequestMergeStrategy.Squash);
 
@@ -1809,14 +1807,14 @@ describe('modules/platform/azure/index', () => {
       azureApi.gitApi.mockImplementation(
         () =>
           ({
-            getPullRequestById: jest.fn(() => ({
+            getPullRequestById: vi.fn(() => ({
               lastMergeSourceCommit: { commitId: 'abcd1234' },
               targetRefName: 'refs/heads/ding',
             })),
-            updatePullRequest: jest.fn(),
+            updatePullRequest: vi.fn(),
           }) as any,
       );
-      azureHelper.getMergeMethod = jest
+      azureHelper.getMergeMethod = vi
         .fn()
         .mockReturnValue(GitPullRequestMergeStrategy.Squash);
 
@@ -1839,7 +1837,7 @@ describe('modules/platform/azure/index', () => {
       const pullRequestIdMock = 12345;
       const branchNameMock = 'test';
       const lastMergeSourceCommitMock = { commitId: 'abcd1234' };
-      const getPullRequestByIdMock = jest.fn(() => ({
+      const getPullRequestByIdMock = vi.fn(() => ({
         lastMergeSourceCommit: lastMergeSourceCommitMock,
         targetRefName: 'refs/heads/ding',
         status: 3,
@@ -1848,12 +1846,12 @@ describe('modules/platform/azure/index', () => {
         () =>
           ({
             getPullRequestById: getPullRequestByIdMock,
-            updatePullRequest: jest.fn(() => ({
+            updatePullRequest: vi.fn(() => ({
               status: 1,
             })),
           }) as any,
       );
-      azureHelper.getMergeMethod = jest
+      azureHelper.getMergeMethod = vi
         .fn()
         .mockReturnValue(GitPullRequestMergeStrategy.Squash);
 
@@ -1871,7 +1869,7 @@ describe('modules/platform/azure/index', () => {
       const branchNameMock = 'test';
       const lastMergeSourceCommitMock = { commitId: 'abcd1234' };
       const expectedNumRetries = 5;
-      const getPullRequestByIdMock = jest.fn(() => ({
+      const getPullRequestByIdMock = vi.fn(() => ({
         lastMergeSourceCommit: lastMergeSourceCommitMock,
         targetRefName: 'refs/heads/ding',
         status: 1,
@@ -1880,12 +1878,12 @@ describe('modules/platform/azure/index', () => {
         () =>
           ({
             getPullRequestById: getPullRequestByIdMock,
-            updatePullRequest: jest.fn(() => ({
+            updatePullRequest: vi.fn(() => ({
               status: 1,
             })),
           }) as any,
       );
-      azureHelper.getMergeMethod = jest
+      azureHelper.getMergeMethod = vi
         .fn()
         .mockReturnValue(GitPullRequestMergeStrategy.Squash);
       const res = await azure.mergePr({
@@ -1906,7 +1904,7 @@ describe('modules/platform/azure/index', () => {
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            deletePullRequestLabels: jest.fn(),
+            deletePullRequestLabels: vi.fn(),
           }) as any,
       );
       await azure.deleteLabel(1234, 'rebase');
@@ -1922,8 +1920,8 @@ describe('modules/platform/azure/index', () => {
     it('returns file content', async () => {
       const data = { foo: 'bar' };
       azureApi.gitApi.mockImplementationOnce(
-        jest.fn().mockImplementationOnce(() => ({
-          getItem: jest.fn(() =>
+        vi.fn().mockImplementationOnce(() => ({
+          getItem: vi.fn(() =>
             Promise.resolve({ content: JSON.stringify(data) }),
           ),
         })),
@@ -1934,8 +1932,8 @@ describe('modules/platform/azure/index', () => {
 
     it('returns null when file not found', async () => {
       azureApi.gitApi.mockImplementationOnce(
-        jest.fn().mockImplementationOnce(() => ({
-          getItem: jest.fn(() => Promise.resolve(null)),
+        vi.fn().mockImplementationOnce(() => ({
+          getItem: vi.fn(() => Promise.resolve(null)),
         })),
       );
       const res = await azure.getJsonFile('file.json');
@@ -1950,8 +1948,8 @@ describe('modules/platform/azure/index', () => {
         }
       `;
       azureApi.gitApi.mockImplementationOnce(
-        jest.fn().mockImplementationOnce(() => ({
-          getItem: jest.fn(() => Promise.resolve({ content: json5Data })),
+        vi.fn().mockImplementationOnce(() => ({
+          getItem: vi.fn(() => Promise.resolve({ content: json5Data })),
         })),
       );
       const res = await azure.getJsonFile('file.json5');
@@ -1962,7 +1960,7 @@ describe('modules/platform/azure/index', () => {
       const data = { foo: 'bar' };
       azureApi.gitApi.mockResolvedValueOnce(
         partial<IGitApi>({
-          getItem: jest.fn(() =>
+          getItem: vi.fn(() =>
             Promise.resolve({ content: JSON.stringify(data) }),
           ),
         }),
@@ -1974,7 +1972,7 @@ describe('modules/platform/azure/index', () => {
     it('throws on malformed JSON', async () => {
       azureApi.gitApi.mockResolvedValueOnce(
         partial<IGitApi>({
-          getItemContent: jest.fn(() => Promise.resolve(Readable.from('!@#'))),
+          getItemContent: vi.fn(() => Promise.resolve(Readable.from('!@#'))),
         }),
       );
       await expect(azure.getJsonFile('file.json')).rejects.toThrow();
@@ -1983,7 +1981,7 @@ describe('modules/platform/azure/index', () => {
     it('throws on errors', async () => {
       azureApi.gitApi.mockResolvedValueOnce(
         partial<IGitApi>({
-          getItemContent: jest.fn(() => {
+          getItemContent: vi.fn(() => {
             throw new Error('some error');
           }),
         }),
@@ -1993,13 +1991,13 @@ describe('modules/platform/azure/index', () => {
 
     it('supports fetch from another repo', async () => {
       const data = { foo: 'bar' };
-      const getItemFn = jest
+      const getItemFn = vi
         .fn()
         .mockResolvedValueOnce({ content: JSON.stringify(data) });
       azureApi.gitApi.mockResolvedValueOnce(
         partial<IGitApi>({
           getItem: getItemFn,
-          getRepositories: jest
+          getRepositories: vi
             .fn()
             .mockResolvedValue([
               { id: '123456', name: 'bar', project: { name: 'foo' } },
@@ -2014,7 +2012,7 @@ describe('modules/platform/azure/index', () => {
     it('returns null', async () => {
       azureApi.gitApi.mockResolvedValueOnce(
         partial<IGitApi>({
-          getRepositories: jest.fn(() => Promise.resolve([])),
+          getRepositories: vi.fn(() => Promise.resolve([])),
         }),
       );
       const res = await azure.getJsonFile('file.json', 'foo/bar');
diff --git a/lib/modules/platform/codecommit/index.spec.ts b/lib/modules/platform/codecommit/index.spec.ts
index 230ddea6e0..4c9fbc104c 100644
--- a/lib/modules/platform/codecommit/index.spec.ts
+++ b/lib/modules/platform/codecommit/index.spec.ts
@@ -52,7 +52,7 @@ describe('modules/platform/codecommit/index', () => {
     codeCommitClient.reset();
     config.prList = undefined;
     config.repository = undefined;
-    jest.useRealTimers();
+    vi.useRealTimers();
   });
 
   it('validates massageMarkdown functionality', () => {
@@ -110,7 +110,7 @@ describe('modules/platform/codecommit/index', () => {
 
   describe('initRepos()', () => {
     it('fails to git.initRepo', async () => {
-      jest.spyOn(git, 'initRepo').mockImplementationOnce(() => {
+      vi.spyOn(git, 'initRepo').mockImplementationOnce(() => {
         throw new Error('any error');
       });
       codeCommitClient.on(GetRepositoryCommand).resolvesOnce({
@@ -126,7 +126,7 @@ describe('modules/platform/codecommit/index', () => {
     });
 
     it('fails on getRepositoryInfo', async () => {
-      jest.spyOn(git, 'initRepo').mockReturnValueOnce(Promise.resolve());
+      vi.spyOn(git, 'initRepo').mockReturnValueOnce(Promise.resolve());
       codeCommitClient
         .on(GetRepositoryCommand)
         .rejectsOnce(new Error('Could not find repository'));
@@ -136,7 +136,7 @@ describe('modules/platform/codecommit/index', () => {
     });
 
     it('getRepositoryInfo returns bad results', async () => {
-      jest.spyOn(git, 'initRepo').mockReturnValueOnce(Promise.resolve());
+      vi.spyOn(git, 'initRepo').mockReturnValueOnce(Promise.resolve());
       codeCommitClient.on(GetRepositoryCommand).resolvesOnce({});
       await expect(
         codeCommit.initRepo({ repository: 'repositoryName' }),
@@ -144,7 +144,7 @@ describe('modules/platform/codecommit/index', () => {
     });
 
     it('getRepositoryInfo returns bad results 2', async () => {
-      jest.spyOn(git, 'initRepo').mockReturnValueOnce(Promise.resolve());
+      vi.spyOn(git, 'initRepo').mockReturnValueOnce(Promise.resolve());
       codeCommitClient.on(GetRepositoryCommand).resolvesOnce({
         repositoryMetadata: {
           repositoryId: 'id',
@@ -156,7 +156,7 @@ describe('modules/platform/codecommit/index', () => {
     });
 
     it('initiates repo successfully', async () => {
-      jest.spyOn(git, 'initRepo').mockReturnValueOnce(Promise.resolve());
+      vi.spyOn(git, 'initRepo').mockReturnValueOnce(Promise.resolve());
       codeCommitClient.on(GetRepositoryCommand).resolvesOnce({
         repositoryMetadata: {
           defaultBranch: 'main',
@@ -207,7 +207,7 @@ describe('modules/platform/codecommit/index', () => {
     });
 
     it('gets url with username and token', () => {
-      jest.useFakeTimers().setSystemTime(new Date('2020-01-01'));
+      vi.useFakeTimers().setSystemTime(new Date('2020-01-01'));
       process.env.AWS_ACCESS_KEY_ID = 'access-key-id';
       process.env.AWS_SECRET_ACCESS_KEY = 'secret-access-key';
       process.env.AWS_REGION = 'eu-central-1';
diff --git a/lib/modules/platform/gitea/index.spec.ts b/lib/modules/platform/gitea/index.spec.ts
index c5c95e15c6..0d7224b8eb 100644
--- a/lib/modules/platform/gitea/index.spec.ts
+++ b/lib/modules/platform/gitea/index.spec.ts
@@ -1474,7 +1474,7 @@ describe('modules/platform/gitea/index', () => {
 
   describe('createPr', () => {
     beforeEach(() => {
-      jest.restoreAllMocks();
+      vi.restoreAllMocks();
       memCache.set('gitea-pr-cache-synced', true);
     });
 
@@ -1662,7 +1662,7 @@ describe('modules/platform/gitea/index', () => {
     });
 
     it('should use platform automerge', async () => {
-      const mergePR = jest.spyOn(helper, 'mergePR');
+      const mergePR = vi.spyOn(helper, 'mergePR');
       const scope = httpMock
         .scope('https://gitea.com/api/v1')
         .post('/repos/some/repo/pulls')
@@ -1688,7 +1688,7 @@ describe('modules/platform/gitea/index', () => {
     });
 
     it('should not use platform automerge on forgejo v7', async () => {
-      const mergePR = jest.spyOn(helper, 'mergePR');
+      const mergePR = vi.spyOn(helper, 'mergePR');
       const scope = httpMock
         .scope('https://gitea.com/api/v1')
         .post('/repos/some/repo/pulls')
@@ -1712,7 +1712,7 @@ describe('modules/platform/gitea/index', () => {
     });
 
     it('should not use platform automerge on forgejo v7 LTS', async () => {
-      const mergePR = jest.spyOn(helper, 'mergePR');
+      const mergePR = vi.spyOn(helper, 'mergePR');
       const scope = httpMock
         .scope('https://gitea.com/api/v1')
         .post('/repos/some/repo/pulls')
diff --git a/lib/modules/platform/github/index.spec.ts b/lib/modules/platform/github/index.spec.ts
index 32f56d291f..7ad88a8a95 100644
--- a/lib/modules/platform/github/index.spec.ts
+++ b/lib/modules/platform/github/index.spec.ts
@@ -1156,7 +1156,7 @@ describe('modules/platform/github/index', () => {
           updated_at: '01-09-2022',
         });
       await github.initRepo({ repository: 'some/repo' });
-      jest.spyOn(branch, 'remoteBranchExists').mockResolvedValueOnce(false);
+      vi.spyOn(branch, 'remoteBranchExists').mockResolvedValueOnce(false);
 
       const pr = await github.tryReuseAutoclosedPr({
         number: 91,
@@ -1180,7 +1180,7 @@ describe('modules/platform/github/index', () => {
         .reply(201)
         .patch('/repos/some/repo/pulls/91')
         .reply(422);
-      jest.spyOn(branch, 'remoteBranchExists').mockResolvedValueOnce(false);
+      vi.spyOn(branch, 'remoteBranchExists').mockResolvedValueOnce(false);
 
       await github.initRepo({ repository: 'some/repo' });
 
@@ -4130,7 +4130,7 @@ describe('modules/platform/github/index', () => {
         .reply(200)
         .post('/repos/some/repo/git/refs')
         .reply(200);
-      jest.spyOn(branch, 'remoteBranchExists').mockResolvedValueOnce(false);
+      vi.spyOn(branch, 'remoteBranchExists').mockResolvedValueOnce(false);
 
       const res = await github.commitFiles({
         branchName: 'foo/bar',
@@ -4159,7 +4159,7 @@ describe('modules/platform/github/index', () => {
         .reply(200)
         .patch('/repos/some/repo/git/refs/heads/foo/bar')
         .reply(200);
-      jest.spyOn(branch, 'remoteBranchExists').mockResolvedValueOnce(true);
+      vi.spyOn(branch, 'remoteBranchExists').mockResolvedValueOnce(true);
 
       const res = await github.commitFiles({
         branchName: 'foo/bar',
@@ -4190,7 +4190,7 @@ describe('modules/platform/github/index', () => {
         .reply(422)
         .post('/repos/some/repo/git/refs')
         .reply(200);
-      jest.spyOn(branch, 'remoteBranchExists').mockResolvedValueOnce(true);
+      vi.spyOn(branch, 'remoteBranchExists').mockResolvedValueOnce(true);
 
       const res = await github.commitFiles({
         branchName: 'foo/bar',
@@ -4219,7 +4219,7 @@ describe('modules/platform/github/index', () => {
         .reply(200)
         .patch('/repos/some/repo/git/refs/heads/foo/bar')
         .reply(404);
-      jest.spyOn(branch, 'remoteBranchExists').mockResolvedValueOnce(true);
+      vi.spyOn(branch, 'remoteBranchExists').mockResolvedValueOnce(true);
 
       const res = await github.commitFiles({
         branchName: 'foo/bar',
diff --git a/lib/modules/platform/github/scm.spec.ts b/lib/modules/platform/github/scm.spec.ts
index 7a5f4ad3d1..1cbd4a54ef 100644
--- a/lib/modules/platform/github/scm.spec.ts
+++ b/lib/modules/platform/github/scm.spec.ts
@@ -8,7 +8,7 @@ const github = mocked(_github);
 
 describe('modules/platform/github/scm', () => {
   beforeEach(() => {
-    jest.spyOn(git, 'commitFiles').mockResolvedValue('sha' as LongCommitSha);
+    vi.spyOn(git, 'commitFiles').mockResolvedValue('sha' as LongCommitSha);
   });
 
   const githubScm = new GithubScm();
diff --git a/lib/renovate.spec.ts b/lib/renovate.spec.ts
index 58efd7dcff..b0d3129daa 100644
--- a/lib/renovate.spec.ts
+++ b/lib/renovate.spec.ts
@@ -1,6 +1,6 @@
 import * as renovateWorker from './workers/global';
 
-Object.defineProperty(renovateWorker, 'start', { value: jest.fn() });
+Object.defineProperty(renovateWorker, 'start', { value: vi.fn() });
 
 describe('renovate', () => {
   it('starts', async () => {
diff --git a/lib/util/cache/package/decorator.spec.ts b/lib/util/cache/package/decorator.spec.ts
index 101bcdd7a8..5d5802f01d 100644
--- a/lib/util/cache/package/decorator.spec.ts
+++ b/lib/util/cache/package/decorator.spec.ts
@@ -8,11 +8,11 @@ vi.mock('./file');
 
 describe('util/cache/package/decorator', () => {
   const setCache = file.set;
-  const getValue = jest.fn();
+  const getValue = vi.fn();
   let count = 1;
 
   beforeEach(async () => {
-    jest.useRealTimers();
+    vi.useRealTimers();
     GlobalConfig.reset();
     memCache.init();
     await packageCache.init({ cacheDir: 'some-dir' });
@@ -198,7 +198,7 @@ describe('util/cache/package/decorator', () => {
     }
 
     beforeEach(() => {
-      jest.useFakeTimers();
+      vi.useFakeTimers();
       GlobalConfig.set({ cacheHardTtlMinutes: 2 });
     });
 
@@ -208,7 +208,7 @@ describe('util/cache/package/decorator', () => {
       expect(await obj.getReleases()).toBe('111');
       expect(getValue).toHaveBeenCalledTimes(1);
 
-      jest.advanceTimersByTime(60 * 1000 - 1);
+      vi.advanceTimersByTime(60 * 1000 - 1);
       expect(await obj.getReleases()).toBe('111');
       expect(getValue).toHaveBeenCalledTimes(1);
       expect(setCache).toHaveBeenLastCalledWith(
@@ -218,7 +218,7 @@ describe('util/cache/package/decorator', () => {
         2,
       );
 
-      jest.advanceTimersByTime(1);
+      vi.advanceTimersByTime(1);
       expect(await obj.getReleases()).toBe('222');
       expect(getValue).toHaveBeenCalledTimes(2);
       expect(setCache).toHaveBeenLastCalledWith(
@@ -245,12 +245,12 @@ describe('util/cache/package/decorator', () => {
         3,
       );
 
-      jest.advanceTimersByTime(120 * 1000 - 1); // namespace default ttl is 1min
+      vi.advanceTimersByTime(120 * 1000 - 1); // namespace default ttl is 1min
       expect(await obj.getReleases()).toBe('111');
       expect(getValue).toHaveBeenCalledTimes(1);
       expect(setCache).toHaveBeenCalledTimes(1);
 
-      jest.advanceTimersByTime(1);
+      vi.advanceTimersByTime(1);
       expect(await obj.getReleases()).toBe('222');
       expect(getValue).toHaveBeenCalledTimes(2);
       expect(setCache).toHaveBeenLastCalledWith(
@@ -273,7 +273,7 @@ describe('util/cache/package/decorator', () => {
         2,
       );
 
-      jest.advanceTimersByTime(60 * 1000);
+      vi.advanceTimersByTime(60 * 1000);
       getValue.mockRejectedValueOnce(new Error('test'));
       expect(await obj.getReleases()).toBe('111');
       expect(getValue).toHaveBeenCalledTimes(2);
@@ -292,11 +292,11 @@ describe('util/cache/package/decorator', () => {
         2,
       );
 
-      jest.advanceTimersByTime(2 * 60 * 1000 - 1);
+      vi.advanceTimersByTime(2 * 60 * 1000 - 1);
       getValue.mockRejectedValueOnce(new Error('test'));
       expect(await obj.getReleases()).toBe('111');
 
-      jest.advanceTimersByTime(1);
+      vi.advanceTimersByTime(1);
       getValue.mockRejectedValueOnce(new Error('test'));
       await expect(obj.getReleases()).rejects.toThrow('test');
     });
diff --git a/lib/util/date.spec.ts b/lib/util/date.spec.ts
index b68966f57f..dc9659cc82 100644
--- a/lib/util/date.spec.ts
+++ b/lib/util/date.spec.ts
@@ -10,11 +10,11 @@ describe('util/date', () => {
   const t0 = DateTime.fromISO('2020-10-10', { zone: 'utc' });
 
   beforeAll(() => {
-    jest.useFakeTimers();
+    vi.useFakeTimers();
   });
 
   beforeEach(() => {
-    jest.setSystemTime(t0.toMillis());
+    vi.setSystemTime(t0.toMillis());
   });
 
   describe('getElapsedDays', () => {
diff --git a/lib/util/decorator/index.spec.ts b/lib/util/decorator/index.spec.ts
index 8ad1ac623f..62f8d07c35 100644
--- a/lib/util/decorator/index.spec.ts
+++ b/lib/util/decorator/index.spec.ts
@@ -2,7 +2,7 @@ import type { Decorator } from '.';
 import { decorate } from '.';
 
 interface WrapParameters {
-  mock: jest.Mock;
+  mock: (_: string) => string;
 }
 
 function wrap<T>({ mock }: WrapParameters): Decorator<T> {
@@ -15,7 +15,7 @@ function wrap<T>({ mock }: WrapParameters): Decorator<T> {
 
 describe('util/decorator/index', () => {
   it('wraps a function', async () => {
-    const mock = jest.fn();
+    const mock = vi.fn();
     class MyClass {
       @wrap({ mock })
       async underTest() {
diff --git a/lib/util/exec/common.spec.ts b/lib/util/exec/common.spec.ts
index fc880c675e..4ae7e60c75 100644
--- a/lib/util/exec/common.spec.ts
+++ b/lib/util/exec/common.spec.ts
@@ -330,11 +330,11 @@ describe('util/exec/common', () => {
   });
 
   describe('handle gpid', () => {
-    const killSpy = jest.spyOn(process, 'kill');
+    const killSpy = vi.spyOn(process, 'kill');
 
     afterEach(() => {
       delete process.env.RENOVATE_X_EXEC_GPID_HANDLE;
-      jest.restoreAllMocks();
+      vi.restoreAllMocks();
     });
 
     it('calls process.kill on the gpid', async () => {
diff --git a/lib/util/exec/docker/index.spec.ts b/lib/util/exec/docker/index.spec.ts
index 28dc102ac3..f7ba7c09bb 100644
--- a/lib/util/exec/docker/index.spec.ts
+++ b/lib/util/exec/docker/index.spec.ts
@@ -51,8 +51,7 @@ describe('util/exec/docker/index', () => {
     });
 
     it('returns "latest" for bad release results', async () => {
-      jest
-        .spyOn(modulesDatasource, 'getPkgReleases')
+      vi.spyOn(modulesDatasource, 'getPkgReleases')
         .mockResolvedValueOnce(undefined as never)
         .mockResolvedValueOnce(partial<modulesDatasource.ReleaseResult>())
         .mockResolvedValueOnce(
@@ -84,11 +83,9 @@ describe('util/exec/docker/index', () => {
         { version: '2.1.1' },
         { version: '2.1.2' },
       ];
-      jest
-        .spyOn(modulesDatasource, 'getPkgReleases')
-        .mockResolvedValueOnce(
-          partial<modulesDatasource.ReleaseResult>({ releases }),
-        );
+      vi.spyOn(modulesDatasource, 'getPkgReleases').mockResolvedValueOnce(
+        partial<modulesDatasource.ReleaseResult>({ releases }),
+      );
       expect(await getDockerTag('foo', '^1.2.3', 'npm')).toBe('1.9.9');
     });
 
@@ -99,11 +96,9 @@ describe('util/exec/docker/index', () => {
         { version: '14.0.2' },
         { version: '15.0.2' },
       ];
-      jest
-        .spyOn(modulesDatasource, 'getPkgReleases')
-        .mockResolvedValueOnce(
-          partial<modulesDatasource.ReleaseResult>({ releases }),
-        );
+      vi.spyOn(modulesDatasource, 'getPkgReleases').mockResolvedValueOnce(
+        partial<modulesDatasource.ReleaseResult>({ releases }),
+      );
       expect(await getDockerTag('foo', '>=12', 'node')).toBe('14.0.2');
     });
   });
@@ -315,7 +310,7 @@ describe('util/exec/docker/index', () => {
 
     // TODO: it('handles tag constraint', async () => {
     //   mockExecAll();
-    // jest
+    // vi
     // .spyOn(modulesDatasource, 'getPkgReleases')
     // .mockResolvedValue(
     //   partial<modulesDatasource.ReleaseResult>({
diff --git a/lib/util/git/index.spec.ts b/lib/util/git/index.spec.ts
index 8b8effd3ae..1095ca07e1 100644
--- a/lib/util/git/index.spec.ts
+++ b/lib/util/git/index.spec.ts
@@ -125,7 +125,7 @@ describe('util/git/index', { timeout: 10000 }, () => {
   afterEach(async () => {
     await tmpDir?.cleanup();
     await origin?.cleanup();
-    jest.restoreAllMocks();
+    vi.restoreAllMocks();
   });
 
   afterAll(async () => {
@@ -135,7 +135,7 @@ describe('util/git/index', { timeout: 10000 }, () => {
 
   describe('gitRetry', () => {
     it('returns result if git returns successfully', async () => {
-      const gitFunc = jest.fn().mockImplementation((args) => {
+      const gitFunc = vi.fn().mockImplementation((args) => {
         if (args === undefined) {
           return 'some result';
         } else {
@@ -149,7 +149,7 @@ describe('util/git/index', { timeout: 10000 }, () => {
 
     it('retries the func call if ExternalHostError thrown', async () => {
       process.env.NODE_ENV = '';
-      const gitFunc = jest
+      const gitFunc = vi
         .fn()
         .mockImplementationOnce(() => {
           throw new Error('The remote end hung up unexpectedly');
@@ -164,7 +164,7 @@ describe('util/git/index', { timeout: 10000 }, () => {
 
     it('retries the func call up to retry count if ExternalHostError thrown', async () => {
       process.env.NODE_ENV = '';
-      const gitFunc = jest.fn().mockImplementation(() => {
+      const gitFunc = vi.fn().mockImplementation(() => {
         throw new Error('The remote end hung up unexpectedly');
       });
       await expect(git.gitRetry(() => gitFunc())).rejects.toThrow(
@@ -174,7 +174,7 @@ describe('util/git/index', { timeout: 10000 }, () => {
     });
 
     it("doesn't retry and throws an Error if non-ExternalHostError thrown by git", async () => {
-      const gitFunc = jest.fn().mockImplementationOnce(() => {
+      const gitFunc = vi.fn().mockImplementationOnce(() => {
         throw new Error('some error');
       });
       await expect(git.gitRetry(() => gitFunc())).rejects.toThrow('some error');
@@ -449,7 +449,7 @@ describe('util/git/index', { timeout: 10000 }, () => {
   describe('mergeToLocal(branchName)', () => {
     it('should perform a branch merge without push', async () => {
       expect(fs.existsSync(`${tmpDir.path}/future_file`)).toBeFalse();
-      const pushSpy = jest.spyOn(SimpleGit.prototype, 'push');
+      const pushSpy = vi.spyOn(SimpleGit.prototype, 'push');
 
       await git.mergeToLocal('renovate/future_branch');
 
@@ -470,7 +470,7 @@ describe('util/git/index', { timeout: 10000 }, () => {
     });
 
     it('should add no verify flag', async () => {
-      const rawSpy = jest.spyOn(SimpleGit.prototype, 'raw');
+      const rawSpy = vi.spyOn(SimpleGit.prototype, 'raw');
       await git.deleteBranch('renovate/something');
       expect(rawSpy).toHaveBeenCalledWith([
         'push',
@@ -481,7 +481,7 @@ describe('util/git/index', { timeout: 10000 }, () => {
     });
 
     it('should not add no verify flag', async () => {
-      const rawSpy = jest.spyOn(SimpleGit.prototype, 'raw');
+      const rawSpy = vi.spyOn(SimpleGit.prototype, 'raw');
       setNoVerify(['push']);
       await git.deleteBranch('renovate/something');
       expect(rawSpy).toHaveBeenCalledWith([
@@ -674,8 +674,8 @@ describe('util/git/index', { timeout: 10000 }, () => {
     });
 
     it('does not pass --no-verify', async () => {
-      const commitSpy = jest.spyOn(SimpleGit.prototype, 'commit');
-      const pushSpy = jest.spyOn(SimpleGit.prototype, 'push');
+      const commitSpy = vi.spyOn(SimpleGit.prototype, 'commit');
+      const pushSpy = vi.spyOn(SimpleGit.prototype, 'push');
 
       const files: FileChange[] = [
         {
@@ -704,8 +704,8 @@ describe('util/git/index', { timeout: 10000 }, () => {
     });
 
     it('passes --no-verify to commit', async () => {
-      const commitSpy = jest.spyOn(SimpleGit.prototype, 'commit');
-      const pushSpy = jest.spyOn(SimpleGit.prototype, 'push');
+      const commitSpy = vi.spyOn(SimpleGit.prototype, 'commit');
+      const pushSpy = vi.spyOn(SimpleGit.prototype, 'push');
 
       const files: FileChange[] = [
         {
@@ -735,8 +735,8 @@ describe('util/git/index', { timeout: 10000 }, () => {
     });
 
     it('passes --no-verify to push', async () => {
-      const commitSpy = jest.spyOn(SimpleGit.prototype, 'commit');
-      const pushSpy = jest.spyOn(SimpleGit.prototype, 'push');
+      const commitSpy = vi.spyOn(SimpleGit.prototype, 'commit');
+      const pushSpy = vi.spyOn(SimpleGit.prototype, 'push');
 
       const files: FileChange[] = [
         {
@@ -1113,7 +1113,7 @@ describe('util/git/index', { timeout: 10000 }, () => {
       await git.pushCommitToRenovateRef(commit, 'bbb');
       await git.pushCommitToRenovateRef(commit, 'ccc');
 
-      const pushSpy = jest.spyOn(SimpleGit.prototype, 'push');
+      const pushSpy = vi.spyOn(SimpleGit.prototype, 'push');
 
       expect(await lsRenovateRefs()).not.toBeEmpty();
       await git.clearRenovateRefs();
@@ -1136,7 +1136,7 @@ describe('util/git/index', { timeout: 10000 }, () => {
       await git.pushCommitToRenovateRef(commit, 'bar');
       await git.pushCommitToRenovateRef(commit, 'baz');
 
-      const pushSpy = jest.spyOn(SimpleGit.prototype, 'push');
+      const pushSpy = vi.spyOn(SimpleGit.prototype, 'push');
       pushSpy.mockImplementationOnce(() => {
         throw new Error(
           'remote: Repository policies do not allow pushes that update more than 2 branches or tags.',
diff --git a/lib/util/github/graphql/cache-strategies/package-cache-strategy.spec.ts b/lib/util/github/graphql/cache-strategies/package-cache-strategy.spec.ts
index 4208ff1bb5..00cdd15d4a 100644
--- a/lib/util/github/graphql/cache-strategies/package-cache-strategy.spec.ts
+++ b/lib/util/github/graphql/cache-strategies/package-cache-strategy.spec.ts
@@ -15,8 +15,8 @@ const mockTime = (input: string): void => {
 type CacheRecord = GithubGraphqlCacheRecord<GithubDatasourceItem>;
 
 describe('util/github/graphql/cache-strategies/package-cache-strategy', () => {
-  const cacheGet = jest.spyOn(packageCache, 'get');
-  const cacheSet = jest.spyOn(packageCache, 'set');
+  const cacheGet = vi.spyOn(packageCache, 'get');
+  const cacheSet = vi.spyOn(packageCache, 'set');
 
   it('reconciles old cache record with new items', async () => {
     const item1 = { version: '1', releaseTimestamp: isoTs('2020-01-01 10:00') };
diff --git a/lib/util/github/tags.spec.ts b/lib/util/github/tags.spec.ts
index ff811d09ea..e5ba4afd67 100644
--- a/lib/util/github/tags.spec.ts
+++ b/lib/util/github/tags.spec.ts
@@ -6,7 +6,7 @@ import { findCommitOfTag } from './tags';
 describe('util/github/tags', () => {
   describe('findCommitOfTag', () => {
     const http = new GithubHttp();
-    const queryTagsSpy = jest.spyOn(githubGraphql, 'queryTags');
+    const queryTagsSpy = vi.spyOn(githubGraphql, 'queryTags');
 
     it('should be able to find the hash of a Git tag', async () => {
       queryTagsSpy.mockResolvedValueOnce([
diff --git a/lib/util/http/cache/package-http-cache-provider.spec.ts b/lib/util/http/cache/package-http-cache-provider.spec.ts
index bd9921c116..57108aca5c 100644
--- a/lib/util/http/cache/package-http-cache-provider.spec.ts
+++ b/lib/util/http/cache/package-http-cache-provider.spec.ts
@@ -18,7 +18,7 @@ describe('util/http/cache/package-http-cache-provider', () => {
   let cache: Record<string, HttpCache> = {};
 
   beforeEach(() => {
-    jest.resetAllMocks();
+    vi.resetAllMocks();
     cache = {};
 
     packageCache.get.mockImplementation((_ns, k) => {
diff --git a/lib/util/http/hooks.spec.ts b/lib/util/http/hooks.spec.ts
index d9b0584cf7..47fde6c826 100644
--- a/lib/util/http/hooks.spec.ts
+++ b/lib/util/http/hooks.spec.ts
@@ -15,7 +15,7 @@ describe('util/http/hooks', () => {
   `(
     `returns $expected for status code $statusCode and followRedirect $followRedirect`,
     ({ statusCode, followRedirect, expected }) => {
-      const destroy = jest.fn();
+      const destroy = vi.fn();
       const response = {
         statusCode,
         request: {
diff --git a/lib/util/http/retry-after.spec.ts b/lib/util/http/retry-after.spec.ts
index 9535cfabb3..418f3437c6 100644
--- a/lib/util/http/retry-after.spec.ts
+++ b/lib/util/http/retry-after.spec.ts
@@ -16,23 +16,23 @@ function requestError(
 
 describe('util/http/retry-after', () => {
   beforeEach(() => {
-    jest.useFakeTimers();
+    vi.useFakeTimers();
   });
 
   afterEach(() => {
-    jest.useRealTimers();
+    vi.useRealTimers();
   });
 
   describe('wrapWithRetry', () => {
     it('works', async () => {
-      const task = jest.fn(() => Promise.resolve(42));
+      const task = vi.fn(() => Promise.resolve(42));
       const res = await wrapWithRetry(task, 'foobar', () => null, 60);
       expect(res).toBe(42);
       expect(task).toHaveBeenCalledTimes(1);
     });
 
     it('throws', async () => {
-      const task = jest.fn(() => Promise.reject(new Error('error')));
+      const task = vi.fn(() => Promise.reject(new Error('error')));
 
       await expect(
         wrapWithRetry(task, 'http://example.com', () => null, 60),
@@ -42,14 +42,14 @@ describe('util/http/retry-after', () => {
     });
 
     it('retries', async () => {
-      const task = jest
+      const task = vi
         .fn()
         .mockRejectedValueOnce(new Error('error-1'))
         .mockRejectedValueOnce(new Error('error-2'))
         .mockResolvedValueOnce(42);
 
       const p = wrapWithRetry(task, 'http://example.com', () => 1, 60);
-      await jest.advanceTimersByTimeAsync(2000);
+      await vi.advanceTimersByTimeAsync(2000);
 
       const res = await p;
       expect(res).toBe(42);
@@ -57,7 +57,7 @@ describe('util/http/retry-after', () => {
     });
 
     it('gives up after max retries', async () => {
-      const task = jest
+      const task = vi
         .fn()
         .mockRejectedValueOnce('error-1')
         .mockRejectedValueOnce('error-2')
@@ -67,14 +67,14 @@ describe('util/http/retry-after', () => {
       const p = wrapWithRetry(task, 'http://example.com', () => 1, 60).catch(
         (err) => err,
       );
-      await jest.advanceTimersByTimeAsync(2000);
+      await vi.advanceTimersByTimeAsync(2000);
 
       await expect(p).resolves.toBe('error-3');
       expect(task).toHaveBeenCalledTimes(3);
     });
 
     it('gives up when delay exceeds maxRetryAfter', async () => {
-      const task = jest.fn().mockRejectedValue('error');
+      const task = vi.fn().mockRejectedValue('error');
 
       const p = wrapWithRetry(task, 'http://example.com', () => 61, 60).catch(
         (err) => err,
@@ -120,7 +120,7 @@ describe('util/http/retry-after', () => {
     });
 
     it('returns delay in seconds from date', () => {
-      jest.setSystemTime(new Date('2020-01-01T00:00:00Z'));
+      vi.setSystemTime(new Date('2020-01-01T00:00:00Z'));
       expect(
         getRetryAfter(
           requestError({
diff --git a/lib/util/json-writer/editor-config.spec.ts b/lib/util/json-writer/editor-config.spec.ts
index 8fb0b0c684..b1c2d83f56 100644
--- a/lib/util/json-writer/editor-config.spec.ts
+++ b/lib/util/json-writer/editor-config.spec.ts
@@ -62,9 +62,9 @@ describe('util/json-writer/editor-config', () => {
       '.editorconfig': Fixtures.get('.global_editorconfig'),
     });
     const editorconf = await import('editorconfig');
-    jest
-      .spyOn(editorconf, 'parse')
-      .mockImplementationOnce(new Error('something') as never);
+    vi.spyOn(editorconf, 'parse').mockImplementationOnce(
+      new Error('something') as never,
+    );
 
     const format = await EditorConfig.getCodeFormat(defaultConfigFile);
 
diff --git a/lib/util/lazy.spec.ts b/lib/util/lazy.spec.ts
index c6ed34cd26..c4c2bdf7d1 100644
--- a/lib/util/lazy.spec.ts
+++ b/lib/util/lazy.spec.ts
@@ -3,7 +3,7 @@ import { Lazy } from './lazy';
 describe('util/lazy', () => {
   describe('.getValue()', () => {
     it('gets a value', () => {
-      const spy = jest.fn().mockReturnValue(0);
+      const spy = vi.fn().mockReturnValue(0);
       const lazy = new Lazy(() => spy());
       const value = lazy.getValue();
       expect(value).toBe(0);
@@ -11,7 +11,7 @@ describe('util/lazy', () => {
     });
 
     it('caches the value', () => {
-      const spy = jest.fn().mockReturnValue(0);
+      const spy = vi.fn().mockReturnValue(0);
       const lazy = new Lazy(() => spy());
       lazy.getValue();
       lazy.getValue();
@@ -19,7 +19,7 @@ describe('util/lazy', () => {
     });
 
     it('throws an error', () => {
-      const spy = jest.fn().mockImplementation(() => {
+      const spy = vi.fn().mockImplementation(() => {
         throw new Error();
       });
       const lazy = new Lazy(() => spy());
@@ -28,7 +28,7 @@ describe('util/lazy', () => {
     });
 
     it('caches the error', () => {
-      const spy = jest.fn().mockImplementation(() => {
+      const spy = vi.fn().mockImplementation(() => {
         throw new Error();
       });
       const lazy = new Lazy(() => spy());
@@ -40,7 +40,7 @@ describe('util/lazy', () => {
 
   describe('.hasValue()', () => {
     it('has a value', () => {
-      const spy = jest.fn().mockReturnValue(0);
+      const spy = vi.fn().mockReturnValue(0);
       const lazy = new Lazy(() => spy());
       lazy.getValue();
       const hasValue = lazy.hasValue();
@@ -49,7 +49,7 @@ describe('util/lazy', () => {
     });
 
     it('does not have a value', () => {
-      const spy = jest.fn().mockReturnValue(0);
+      const spy = vi.fn().mockReturnValue(0);
       const lazy = new Lazy(() => spy());
       const hasValue = lazy.hasValue();
       expect(hasValue).toBeFalse();
diff --git a/lib/util/package-rules/current-age.spec.ts b/lib/util/package-rules/current-age.spec.ts
index 36389dccc6..948ed9a90c 100644
--- a/lib/util/package-rules/current-age.spec.ts
+++ b/lib/util/package-rules/current-age.spec.ts
@@ -8,11 +8,11 @@ describe('util/package-rules/current-age', () => {
     const t0 = DateTime.fromISO('2023-07-07', { zone: 'utc' });
 
     beforeAll(() => {
-      jest.useFakeTimers();
+      vi.useFakeTimers();
     });
 
     beforeEach(() => {
-      jest.setSystemTime(t0.toMillis());
+      vi.setSystemTime(t0.toMillis());
     });
 
     it('returns false if release is older', () => {
diff --git a/lib/util/package-rules/current-version.spec.ts b/lib/util/package-rules/current-version.spec.ts
index c4fce08fb4..dc00a836bf 100644
--- a/lib/util/package-rules/current-version.spec.ts
+++ b/lib/util/package-rules/current-version.spec.ts
@@ -20,7 +20,7 @@ describe('util/package-rules/current-version', () => {
     });
 
     it('return false on version exception', () => {
-      const spy = jest.spyOn(pep440, 'isValid').mockImplementationOnce(() => {
+      const spy = vi.spyOn(pep440, 'isValid').mockImplementationOnce(() => {
         throw new Error();
       });
       const result = matcher.matches(
diff --git a/lib/util/pretty-time.spec.ts b/lib/util/pretty-time.spec.ts
index 4a1017f1c1..ca44988a06 100644
--- a/lib/util/pretty-time.spec.ts
+++ b/lib/util/pretty-time.spec.ts
@@ -50,11 +50,11 @@ describe('util/pretty-time', () => {
     const t0 = DateTime.fromISO('2023-07-07T12:00:00Z');
 
     beforeAll(() => {
-      jest.useFakeTimers();
+      vi.useFakeTimers();
     });
 
     beforeEach(() => {
-      jest.setSystemTime(t0.toMillis());
+      vi.setSystemTime(t0.toMillis());
     });
 
     it.each`
diff --git a/lib/util/result.spec.ts b/lib/util/result.spec.ts
index 4a22eec2ee..fceee03d65 100644
--- a/lib/util/result.spec.ts
+++ b/lib/util/result.spec.ts
@@ -212,7 +212,7 @@ describe('util/result', () => {
 
       it('skips transform for error Result', () => {
         const res: Result<number, string> = Result.err('oops');
-        const fn = jest.fn((x: number) => x + 1);
+        const fn = vi.fn((x: number) => x + 1);
         expect(res.transform(fn)).toEqual(Result.err('oops'));
         expect(fn).not.toHaveBeenCalled();
       });
@@ -316,13 +316,13 @@ describe('util/result', () => {
 
     describe('Handlers', () => {
       it('supports value handlers', () => {
-        const cb = jest.fn();
+        const cb = vi.fn();
         Result.ok(42).onValue(cb);
         expect(cb).toHaveBeenCalledWith(42);
       });
 
       it('supports error handlers', () => {
-        const cb = jest.fn();
+        const cb = vi.fn();
         Result.err('oops').onError(cb);
         expect(cb).toHaveBeenCalledWith('oops');
       });
@@ -479,7 +479,7 @@ describe('util/result', () => {
 
       it('skips transform for failed promises', async () => {
         const res = AsyncResult.err('oops');
-        const fn = jest.fn((x: number) => x + 1);
+        const fn = vi.fn((x: number) => x + 1);
         await expect(res.transform(fn)).resolves.toEqual(Result.err('oops'));
         expect(fn).not.toHaveBeenCalled();
       });
@@ -514,7 +514,7 @@ describe('util/result', () => {
 
       it('skips async transform for error Result', async () => {
         const input: Result<number, string> = Result.err('oops');
-        const fn = jest.fn((x: number) => Promise.resolve(x + 1));
+        const fn = vi.fn((x: number) => Promise.resolve(x + 1));
         const res = await input.transform(fn);
         expect(res).toEqual(Result.err('oops'));
         expect(fn).not.toHaveBeenCalled();
@@ -522,7 +522,7 @@ describe('util/result', () => {
 
       it('skips async transform for rejected promise', async () => {
         const res: AsyncResult<number, string> = AsyncResult.err('oops');
-        const fn = jest.fn((x: number) => Promise.resolve(x + 1));
+        const fn = vi.fn((x: number) => Promise.resolve(x + 1));
         await expect(res.transform(fn)).resolves.toEqual(Result.err('oops'));
         expect(fn).not.toHaveBeenCalled();
       });
@@ -666,13 +666,13 @@ describe('util/result', () => {
 
   describe('Handlers', () => {
     it('supports value handlers', async () => {
-      const cb = jest.fn();
+      const cb = vi.fn();
       await AsyncResult.ok(42).onValue(cb);
       expect(cb).toHaveBeenCalledWith(42);
     });
 
     it('supports error handlers', async () => {
-      const cb = jest.fn();
+      const cb = vi.fn();
       await AsyncResult.err('oops').onError(cb);
       expect(cb).toHaveBeenCalledWith('oops');
     });
diff --git a/lib/util/s3.spec.ts b/lib/util/s3.spec.ts
index d1bb369824..9695747b49 100644
--- a/lib/util/s3.spec.ts
+++ b/lib/util/s3.spec.ts
@@ -2,7 +2,7 @@ import { getS3Client, parseS3Url } from './s3';
 
 describe('util/s3', () => {
   afterEach(() => {
-    jest.resetModules();
+    vi.resetModules();
   });
 
   it('parses S3 URLs', () => {
diff --git a/lib/util/stats.spec.ts b/lib/util/stats.spec.ts
index d479ea48e4..65e4be0206 100644
--- a/lib/util/stats.spec.ts
+++ b/lib/util/stats.spec.ts
@@ -51,11 +51,11 @@ describe('util/stats', () => {
 
   describe('LookupStats', () => {
     beforeEach(() => {
-      jest.useFakeTimers();
+      vi.useFakeTimers();
     });
 
     afterEach(() => {
-      jest.useRealTimers();
+      vi.useRealTimers();
     });
 
     it('returns empty report', () => {
@@ -91,7 +91,7 @@ describe('util/stats', () => {
 
     it('wraps a function', async () => {
       const res = await LookupStats.wrap('npm', () => {
-        jest.advanceTimersByTime(100);
+        vi.advanceTimersByTime(100);
         return Promise.resolve('foo');
       });
 
@@ -139,7 +139,7 @@ describe('util/stats', () => {
 
   describe('PackageCacheStats', () => {
     beforeEach(() => {
-      jest.useFakeTimers();
+      vi.useFakeTimers();
     });
 
     it('returns empty report', () => {
@@ -178,7 +178,7 @@ describe('util/stats', () => {
 
     it('wraps get function', async () => {
       const res = await PackageCacheStats.wrapGet(() => {
-        jest.advanceTimersByTime(100);
+        vi.advanceTimersByTime(100);
         return Promise.resolve('foo');
       });
 
@@ -191,7 +191,7 @@ describe('util/stats', () => {
 
     it('wraps set function', async () => {
       await PackageCacheStats.wrapSet(() => {
-        jest.advanceTimersByTime(100);
+        vi.advanceTimersByTime(100);
         return Promise.resolve();
       });
 
diff --git a/lib/workers/global/config/parse/env.spec.ts b/lib/workers/global/config/parse/env.spec.ts
index 26a39ea460..ab80bd8497 100644
--- a/lib/workers/global/config/parse/env.spec.ts
+++ b/lib/workers/global/config/parse/env.spec.ts
@@ -1,3 +1,4 @@
+import type { MockInstance } from 'vitest';
 import type { RequiredConfig } from '../../../../config/types';
 import { logger } from '../../../../logger';
 import * as env from './env';
@@ -292,10 +293,10 @@ describe('workers/global/config/parse/env', () => {
     });
 
     describe('RENOVATE_CONFIG tests', () => {
-      let processExit: jest.SpyInstance<never, [code?: number]>;
+      let processExit: MockInstance<(code?: number | string | null) => never>;
 
       beforeAll(() => {
-        processExit = jest
+        processExit = vi
           .spyOn(process, 'exit')
           .mockImplementation((() => void 0) as never);
       });
diff --git a/lib/workers/global/config/parse/file.spec.ts b/lib/workers/global/config/parse/file.spec.ts
index f6801ce407..5dd1dcbbfa 100644
--- a/lib/workers/global/config/parse/file.spec.ts
+++ b/lib/workers/global/config/parse/file.spec.ts
@@ -8,9 +8,9 @@ import customConfig from './__fixtures__/config';
 import * as file from './file';
 
 describe('workers/global/config/parse/file', () => {
-  const processExitSpy = jest.spyOn(process, 'exit');
-  const fsPathExistsSpy = jest.spyOn(fsExtra, 'pathExists');
-  const fsRemoveSpy = jest.spyOn(fsExtra, 'remove');
+  const processExitSpy = vi.spyOn(process, 'exit');
+  const fsPathExistsSpy = vi.spyOn(fsExtra, 'pathExists');
+  const fsRemoveSpy = vi.spyOn(fsExtra, 'remove');
 
   let tmp: DirectoryResult;
 
diff --git a/lib/workers/global/index.spec.ts b/lib/workers/global/index.spec.ts
index b088284ac6..f0cf57b62e 100644
--- a/lib/workers/global/index.spec.ts
+++ b/lib/workers/global/index.spec.ts
@@ -38,9 +38,9 @@ vi.mock('fs-extra', async () => {
 // imports are readonly
 const presets = mocked(_presets);
 
-const addSecretForSanitizing = jest.spyOn(secrets, 'addSecretForSanitizing');
-const parseConfigs = jest.spyOn(configParser, 'parseConfigs');
-const initPlatform = jest.spyOn(platform, 'initPlatform');
+const addSecretForSanitizing = vi.spyOn(secrets, 'addSecretForSanitizing');
+const parseConfigs = vi.spyOn(configParser, 'parseConfigs');
+const initPlatform = vi.spyOn(platform, 'initPlatform');
 
 describe('workers/global/index', () => {
   beforeEach(() => {
@@ -155,7 +155,7 @@ describe('workers/global/index', () => {
   });
 
   it('processes repositories break', async () => {
-    const isLimitReached = jest.spyOn(limits, 'isLimitReached');
+    const isLimitReached = vi.spyOn(limits, 'isLimitReached');
     isLimitReached.mockReturnValue(true);
     parseConfigs.mockResolvedValueOnce({
       gitAuthor: 'a@b.com',
diff --git a/lib/workers/repository/config-migration/branch/create.spec.ts b/lib/workers/repository/config-migration/branch/create.spec.ts
index e7e2536bfe..49768a25cd 100644
--- a/lib/workers/repository/config-migration/branch/create.spec.ts
+++ b/lib/workers/repository/config-migration/branch/create.spec.ts
@@ -16,10 +16,7 @@ describe('workers/repository/config-migration/branch/create', () => {
   const indent = '  ';
   const renovateConfig = JSON.stringify(raw, undefined, indent) + '\n';
   const filename = 'renovate.json';
-  const prettierSpy = jest.spyOn(
-    MigratedDataFactory,
-    'applyPrettierFormatting',
-  );
+  const prettierSpy = vi.spyOn(MigratedDataFactory, 'applyPrettierFormatting');
 
   let config: RenovateConfig;
   let migratedConfigData: MigratedData;
diff --git a/lib/workers/repository/config-migration/branch/index.spec.ts b/lib/workers/repository/config-migration/branch/index.spec.ts
index 4ab6f6b79a..1da179081f 100644
--- a/lib/workers/repository/config-migration/branch/index.spec.ts
+++ b/lib/workers/repository/config-migration/branch/index.spec.ts
@@ -113,7 +113,7 @@ describe('workers/repository/config-migration/branch/index', () => {
           number: 1,
         }),
       );
-      platform.refreshPr = jest.fn().mockResolvedValueOnce(null);
+      platform.refreshPr = vi.fn().mockResolvedValueOnce(null);
       mockedFunction(rebaseMigrationBranch).mockResolvedValueOnce('committed');
       const res = await checkConfigMigrationBranch(
         {
@@ -164,7 +164,7 @@ describe('workers/repository/config-migration/branch/index', () => {
 
     it('updates migration branch & refresh PR when migration enabled and open pr exists', async () => {
       platform.getBranchPr.mockResolvedValue(mock<Pr>());
-      platform.refreshPr = jest.fn().mockResolvedValueOnce(null);
+      platform.refreshPr = vi.fn().mockResolvedValueOnce(null);
       mockedFunction(rebaseMigrationBranch).mockResolvedValueOnce('committed');
       const res = await checkConfigMigrationBranch(
         {
diff --git a/lib/workers/repository/config-migration/branch/rebase.spec.ts b/lib/workers/repository/config-migration/branch/rebase.spec.ts
index fdaa102373..e77402f36a 100644
--- a/lib/workers/repository/config-migration/branch/rebase.spec.ts
+++ b/lib/workers/repository/config-migration/branch/rebase.spec.ts
@@ -16,10 +16,7 @@ const formattedMigratedData = Fixtures.getJson(
 );
 
 describe('workers/repository/config-migration/branch/rebase', () => {
-  const prettierSpy = jest.spyOn(
-    MigratedDataFactory,
-    'applyPrettierFormatting',
-  );
+  const prettierSpy = vi.spyOn(MigratedDataFactory, 'applyPrettierFormatting');
 
   beforeEach(() => {
     GlobalConfig.set({
diff --git a/lib/workers/repository/dependency-dashboard.spec.ts b/lib/workers/repository/dependency-dashboard.spec.ts
index 458974dd1c..ff98fe3fb8 100644
--- a/lib/workers/repository/dependency-dashboard.spec.ts
+++ b/lib/workers/repository/dependency-dashboard.spec.ts
@@ -1,6 +1,8 @@
 import { ERROR, WARN } from 'bunyan';
 import { codeBlock } from 'common-tags';
 import { mock } from 'jest-mock-extended';
+import type { MockedObject } from 'vitest';
+import { vi } from 'vitest';
 import { Fixtures } from '../../../test/fixtures';
 import type { RenovateConfig } from '../../../test/util';
 import { logger, mockedFunction, platform } from '../../../test/util';
@@ -19,7 +21,7 @@ import * as dependencyDashboard from './dependency-dashboard';
 import { getDashboardMarkdownVulnerabilities } from './dependency-dashboard';
 import { PackageFiles } from './package-files';
 
-const createVulnerabilitiesMock = jest.fn();
+const createVulnerabilitiesMock = vi.fn();
 vi.mock('./process/vulnerabilities', () => {
   return {
     __esModule: true,
@@ -73,7 +75,7 @@ function genRandPackageFile(
 
 async function dryRun(
   branches: BranchConfig[],
-  platform: jest.MockedObject<Platform>,
+  platform: MockedObject<Platform>,
   ensureIssueClosingCalls: number,
   ensureIssueCalls: number,
 ) {
@@ -1509,7 +1511,7 @@ None detected
     });
 
     it('return no data section if summary is set to all and no vulnerabilities', async () => {
-      const fetchVulnerabilitiesMock = jest.fn();
+      const fetchVulnerabilitiesMock = vi.fn();
       createVulnerabilitiesMock.mockResolvedValueOnce({
         fetchVulnerabilities: fetchVulnerabilitiesMock,
       });
@@ -1528,7 +1530,7 @@ None detected
     });
 
     it('return all vulnerabilities if set to all and disabled osvVulnerabilities', async () => {
-      const fetchVulnerabilitiesMock = jest.fn();
+      const fetchVulnerabilitiesMock = vi.fn();
       createVulnerabilitiesMock.mockResolvedValueOnce({
         fetchVulnerabilities: fetchVulnerabilitiesMock,
       });
@@ -1595,7 +1597,7 @@ None detected
     });
 
     it('return unresolved vulnerabilities if set to "unresolved"', async () => {
-      const fetchVulnerabilitiesMock = jest.fn();
+      const fetchVulnerabilitiesMock = vi.fn();
       createVulnerabilitiesMock.mockResolvedValueOnce({
         fetchVulnerabilities: fetchVulnerabilitiesMock,
       });
diff --git a/lib/workers/repository/extract/manager-files.spec.ts b/lib/workers/repository/extract/manager-files.spec.ts
index d578c4f8de..d3ac34e23b 100644
--- a/lib/workers/repository/extract/manager-files.spec.ts
+++ b/lib/workers/repository/extract/manager-files.spec.ts
@@ -51,7 +51,7 @@ describe('workers/repository/extract/manager-files', () => {
       };
       fileMatch.getMatchingFiles.mockReturnValue(['Dockerfile']);
       fs.readLocalFile.mockResolvedValueOnce('some content');
-      html.extractPackageFile = jest.fn(() => ({
+      html.extractPackageFile = vi.fn(() => ({
         deps: [{}, { replaceString: 'abc', packageName: 'p' }],
       })) as never;
       const res = await getManagerPackageFiles(managerConfig);
diff --git a/lib/workers/repository/finalize/repository-statistics.spec.ts b/lib/workers/repository/finalize/repository-statistics.spec.ts
index 37e49e9ad3..ad7476e222 100644
--- a/lib/workers/repository/finalize/repository-statistics.spec.ts
+++ b/lib/workers/repository/finalize/repository-statistics.spec.ts
@@ -54,8 +54,8 @@ describe('workers/repository/finalize/repository-statistics', () => {
   });
 
   describe('runBranchSummary', () => {
-    const getCacheSpy = jest.spyOn(cache, 'getCache');
-    const isCacheModifiedSpy = jest.spyOn(cache, 'isCacheModified');
+    const getCacheSpy = vi.spyOn(cache, 'getCache');
+    const isCacheModifiedSpy = vi.spyOn(cache, 'isCacheModified');
     const config: RenovateConfig = {};
 
     it('processes cache with baseBranches only', () => {
diff --git a/lib/workers/repository/init/inherited.spec.ts b/lib/workers/repository/init/inherited.spec.ts
index b870c910a5..202c116454 100644
--- a/lib/workers/repository/init/inherited.spec.ts
+++ b/lib/workers/repository/init/inherited.spec.ts
@@ -159,8 +159,7 @@ describe('workers/repository/init/inherited', () => {
     platform.getRawFile.mockResolvedValue(
       '{"onboarding":false,"labels":["test"],"extends":[":automergeAll"]}',
     );
-    jest
-      .spyOn(validation, 'validateConfig')
+    vi.spyOn(validation, 'validateConfig')
       .mockResolvedValueOnce({
         warnings: [],
         errors: [],
@@ -198,8 +197,7 @@ describe('workers/repository/init/inherited', () => {
     platform.getRawFile.mockResolvedValue(
       '{"labels":["test"],"extends":[":automergeAll"]}',
     );
-    jest
-      .spyOn(validation, 'validateConfig')
+    vi.spyOn(validation, 'validateConfig')
       .mockResolvedValueOnce({
         warnings: [],
         errors: [],
@@ -237,7 +235,7 @@ describe('workers/repository/init/inherited', () => {
     platform.getRawFile.mockResolvedValue(
       '{"labels":["test"],"extends":[":automergeAll"]}',
     );
-    jest.spyOn(validation, 'validateConfig').mockResolvedValue({
+    vi.spyOn(validation, 'validateConfig').mockResolvedValue({
       warnings: [],
       errors: [],
     });
diff --git a/lib/workers/repository/init/merge.spec.ts b/lib/workers/repository/init/merge.spec.ts
index 97f2b46411..c1daeac8eb 100644
--- a/lib/workers/repository/init/merge.spec.ts
+++ b/lib/workers/repository/init/merge.spec.ts
@@ -48,7 +48,7 @@ vi.mock('../../../config/migrate-validate');
 
 describe('workers/repository/init/merge', () => {
   afterEach(() => {
-    jest.restoreAllMocks();
+    vi.restoreAllMocks();
   });
 
   describe('detectRepoFileConfig()', () => {
@@ -63,11 +63,9 @@ describe('workers/repository/init/merge', () => {
     });
 
     it('returns config if not found - uses cache', async () => {
-      jest
-        .spyOn(repoCache, 'getCache')
-        .mockReturnValueOnce(
-          partial<RepoCacheData>({ configFileName: 'renovate.json' }),
-        );
+      vi.spyOn(repoCache, 'getCache').mockReturnValueOnce(
+        partial<RepoCacheData>({ configFileName: 'renovate.json' }),
+      );
       platform.getRawFile.mockRejectedValueOnce(new Error());
       scm.getFileList.mockResolvedValue(['package.json']);
       fs.readLocalFile.mockResolvedValue('{}');
@@ -434,7 +432,7 @@ describe('workers/repository/init/merge', () => {
         isMigrated: true,
         migratedConfig: c,
       }));
-      jest.spyOn(decrypt, 'decryptConfig').mockResolvedValueOnce({
+      vi.spyOn(decrypt, 'decryptConfig').mockResolvedValueOnce({
         ...config,
         npmrc: 'something_authToken=${NPM_TOKEN}',
         npmToken: 'token',
diff --git a/lib/workers/repository/process/extract-update.spec.ts b/lib/workers/repository/process/extract-update.spec.ts
index fe47bec130..1275ffa1b6 100644
--- a/lib/workers/repository/process/extract-update.spec.ts
+++ b/lib/workers/repository/process/extract-update.spec.ts
@@ -14,7 +14,7 @@ import {
   update,
 } from './extract-update';
 
-const createVulnerabilitiesMock = jest.fn();
+const createVulnerabilitiesMock = vi.fn();
 
 vi.mock('./write');
 vi.mock('./sort');
@@ -122,7 +122,7 @@ describe('workers/repository/process/extract-update', () => {
         repoIsOnboarded: true,
         osvVulnerabilityAlerts: true,
       };
-      const appendVulnerabilityPackageRulesMock = jest.fn();
+      const appendVulnerabilityPackageRulesMock = vi.fn();
       createVulnerabilitiesMock.mockResolvedValueOnce({
         appendVulnerabilityPackageRules: appendVulnerabilityPackageRulesMock,
       });
diff --git a/lib/workers/repository/process/index.spec.ts b/lib/workers/repository/process/index.spec.ts
index 990b5b31c1..818175b72a 100644
--- a/lib/workers/repository/process/index.spec.ts
+++ b/lib/workers/repository/process/index.spec.ts
@@ -64,7 +64,7 @@ describe('workers/repository/process/index', () => {
 
     it('reads config from branches in baseBranches if useBaseBranchConfig specified', async () => {
       scm.branchExists.mockResolvedValue(true);
-      platform.getJsonFile = jest
+      platform.getJsonFile = vi
         .fn()
         .mockResolvedValue({ extends: [':approveMajorUpdates'] });
       config.baseBranches = ['master', 'dev'];
@@ -87,7 +87,7 @@ describe('workers/repository/process/index', () => {
 
     it('handles config name mismatch between baseBranches if useBaseBranchConfig specified', async () => {
       scm.branchExists.mockResolvedValue(true);
-      platform.getJsonFile = jest
+      platform.getJsonFile = vi
         .fn()
         .mockImplementation((fileName, repoName, branchName) => {
           if (branchName === 'dev') {
diff --git a/lib/workers/repository/process/lookup/index.spec.ts b/lib/workers/repository/process/lookup/index.spec.ts
index 5148a225dc..2074bd589e 100644
--- a/lib/workers/repository/process/lookup/index.spec.ts
+++ b/lib/workers/repository/process/lookup/index.spec.ts
@@ -50,33 +50,27 @@ const webpackJson = Fixtures.get('webpack.json');
 let config: LookupUpdateConfig;
 
 describe('workers/repository/process/lookup/index', () => {
-  const getGithubReleases = jest.spyOn(
+  const getGithubReleases = vi.spyOn(
     GithubReleasesDatasource.prototype,
     'getReleases',
   );
 
-  const getGithubTags = jest.spyOn(
-    GithubTagsDatasource.prototype,
-    'getReleases',
-  );
+  const getGithubTags = vi.spyOn(GithubTagsDatasource.prototype, 'getReleases');
 
-  const getDockerReleases = jest.spyOn(
-    DockerDatasource.prototype,
-    'getReleases',
-  );
+  const getDockerReleases = vi.spyOn(DockerDatasource.prototype, 'getReleases');
 
-  const getMavenReleases = jest.spyOn(MavenDatasource.prototype, 'getReleases');
-  const postprocessMavenRelease = jest.spyOn(
+  const getMavenReleases = vi.spyOn(MavenDatasource.prototype, 'getReleases');
+  const postprocessMavenRelease = vi.spyOn(
     MavenDatasource.prototype,
     'postprocessRelease',
   );
 
-  const getCustomDatasourceReleases = jest.spyOn(
+  const getCustomDatasourceReleases = vi.spyOn(
     CustomDatasource.prototype,
     'getReleases',
   );
 
-  const getDockerDigest = jest.spyOn(DockerDatasource.prototype, 'getDigest');
+  const getDockerDigest = vi.spyOn(DockerDatasource.prototype, 'getDigest');
 
   beforeEach(() => {
     // TODO: fix types #22198
@@ -84,14 +78,12 @@ describe('workers/repository/process/lookup/index', () => {
     config.manager = 'npm';
     config.versioning = npmVersioningId;
     config.rangeStrategy = 'replace';
-    jest
-      .spyOn(GitRefsDatasource.prototype, 'getReleases')
-      .mockResolvedValueOnce({
-        releases: [{ version: 'master' }],
-      });
-    jest
-      .spyOn(GitRefsDatasource.prototype, 'getDigest')
-      .mockResolvedValueOnce('4b825dc642cb6eb9a060e54bf8d69288fbee4904');
+    vi.spyOn(GitRefsDatasource.prototype, 'getReleases').mockResolvedValueOnce({
+      releases: [{ version: 'master' }],
+    });
+    vi.spyOn(GitRefsDatasource.prototype, 'getDigest').mockResolvedValueOnce(
+      '4b825dc642cb6eb9a060e54bf8d69288fbee4904',
+    );
   });
 
   // TODO: fix mocks
@@ -2989,7 +2981,7 @@ describe('workers/repository/process/lookup/index', () => {
           },
         ],
       });
-      const getGithubTagsDigest = jest
+      const getGithubTagsDigest = vi
         .spyOn(GithubTagsDatasource.prototype, 'getDigest')
         .mockResolvedValueOnce('digest1234');
 
@@ -5000,10 +4992,7 @@ describe('workers/repository/process/lookup/index', () => {
         mergeConfidenceEndpoint: defaultApiBaseUrl,
         mergeConfidenceDatasources: presetSupportedDatasources,
       };
-      const getMergeConfidenceSpy = jest.spyOn(
-        McApi,
-        'getMergeConfidenceLevel',
-      );
+      const getMergeConfidenceSpy = vi.spyOn(McApi, 'getMergeConfidenceLevel');
       const hostRule: HostRule = {
         hostType: 'merge-confidence',
         token: 'some-token',
diff --git a/lib/workers/repository/process/vulnerabilities.spec.ts b/lib/workers/repository/process/vulnerabilities.spec.ts
index f42fd4e6eb..fafc0d2d5b 100644
--- a/lib/workers/repository/process/vulnerabilities.spec.ts
+++ b/lib/workers/repository/process/vulnerabilities.spec.ts
@@ -9,7 +9,7 @@ import { Vulnerabilities } from './vulnerabilities';
 
 const getVulnerabilitiesMock =
   mockFn<typeof OsvOffline.prototype.getVulnerabilities>();
-const createMock = jest.fn();
+const createMock = vi.fn();
 
 vi.mock('@renovatebot/osv-offline', () => {
   return {
diff --git a/lib/workers/repository/update/branch/automerge.spec.ts b/lib/workers/repository/update/branch/automerge.spec.ts
index cf5ef50e3f..cde57452ec 100644
--- a/lib/workers/repository/update/branch/automerge.spec.ts
+++ b/lib/workers/repository/update/branch/automerge.spec.ts
@@ -9,7 +9,7 @@ vi.mock('../../../../util/git');
 
 describe('workers/repository/update/branch/automerge', () => {
   describe('tryBranchAutomerge', () => {
-    const isScheduledSpy = jest.spyOn(schedule, 'isScheduledNow');
+    const isScheduledSpy = vi.spyOn(schedule, 'isScheduledNow');
     let config: RenovateConfig;
 
     beforeEach(() => {
diff --git a/lib/workers/repository/update/branch/get-updated.spec.ts b/lib/workers/repository/update/branch/get-updated.spec.ts
index 009aaa264b..a08e1d8347 100644
--- a/lib/workers/repository/update/branch/get-updated.spec.ts
+++ b/lib/workers/repository/update/branch/get-updated.spec.ts
@@ -52,7 +52,7 @@ describe('workers/repository/update/branch/get-updated', () => {
         branchName: 'renovate/pin',
         upgrades: [],
       } satisfies BranchConfig;
-      npm.updateDependency = jest.fn();
+      npm.updateDependency = vi.fn();
       git.getFile.mockResolvedValueOnce('existing content');
     });
 
diff --git a/lib/workers/repository/update/branch/index.spec.ts b/lib/workers/repository/update/branch/index.spec.ts
index c910e7e66b..b4e73b201e 100644
--- a/lib/workers/repository/update/branch/index.spec.ts
+++ b/lib/workers/repository/update/branch/index.spec.ts
@@ -114,9 +114,9 @@ describe('workers/repository/update/branch/index', () => {
         // eslint-disable-next-line require-await, @typescript-eslint/require-await
         async (config) => config,
       );
-      prWorker.ensurePr = jest.fn();
-      prWorker.getPlatformPrOptions = jest.fn();
-      prAutomerge.checkAutoMerge = jest.fn();
+      prWorker.ensurePr = vi.fn();
+      prWorker.getPlatformPrOptions = vi.fn();
+      prAutomerge.checkAutoMerge = vi.fn();
       // TODO: incompatible types (#22198)
       config = {
         ...getConfig(),
@@ -2321,7 +2321,7 @@ describe('workers/repository/update/branch/index', () => {
     });
 
     it('Dependency Dashboard All Pending approval', async () => {
-      jest.spyOn(getUpdated, 'getUpdatedPackageFiles').mockResolvedValueOnce(
+      vi.spyOn(getUpdated, 'getUpdatedPackageFiles').mockResolvedValueOnce(
         partial<PackageFilesResult>({
           updatedPackageFiles: [partial<FileChange>()],
           artifactErrors: [{}],
@@ -2358,7 +2358,7 @@ describe('workers/repository/update/branch/index', () => {
     });
 
     it('Dependency Dashboard open all rate-limited', async () => {
-      jest.spyOn(getUpdated, 'getUpdatedPackageFiles').mockResolvedValueOnce(
+      vi.spyOn(getUpdated, 'getUpdatedPackageFiles').mockResolvedValueOnce(
         partial<PackageFilesResult>({
           updatedPackageFiles: [partial<FileChange>()],
           artifactErrors: [{}],
@@ -2395,7 +2395,7 @@ describe('workers/repository/update/branch/index', () => {
     });
 
     it('continues branch, skips automerge if there are artifact errors', async () => {
-      jest.spyOn(getUpdated, 'getUpdatedPackageFiles').mockResolvedValueOnce(
+      vi.spyOn(getUpdated, 'getUpdatedPackageFiles').mockResolvedValueOnce(
         partial<PackageFilesResult>({
           updatedPackageFiles: [partial<FileChange>()],
           artifactErrors: [{}],
@@ -2434,7 +2434,7 @@ describe('workers/repository/update/branch/index', () => {
           state: 'open',
         }),
       );
-      jest.spyOn(getUpdated, 'getUpdatedPackageFiles').mockResolvedValueOnce(
+      vi.spyOn(getUpdated, 'getUpdatedPackageFiles').mockResolvedValueOnce(
         partial<PackageFilesResult>({
           updatedPackageFiles: [partial<FileChange>()],
         }),
diff --git a/lib/workers/repository/update/branch/lock-files/index.spec.ts b/lib/workers/repository/update/branch/lock-files/index.spec.ts
index b8ff010863..9bf7992748 100644
--- a/lib/workers/repository/update/branch/lock-files/index.spec.ts
+++ b/lib/workers/repository/update/branch/lock-files/index.spec.ts
@@ -79,16 +79,16 @@ describe('workers/repository/update/branch/lock-files/index', () => {
         localDir: 'some-tmp-dir',
       });
       git.getFile.mockResolvedValueOnce('some lock file contents');
-      jest.spyOn(npm, 'generateLockFile').mockResolvedValueOnce({
+      vi.spyOn(npm, 'generateLockFile').mockResolvedValueOnce({
         lockFile: 'some lock file contents',
       });
-      jest.spyOn(yarn, 'generateLockFile').mockResolvedValueOnce({
+      vi.spyOn(yarn, 'generateLockFile').mockResolvedValueOnce({
         lockFile: 'some lock file contents',
       });
-      jest.spyOn(pnpm, 'generateLockFile').mockResolvedValueOnce({
+      vi.spyOn(pnpm, 'generateLockFile').mockResolvedValueOnce({
         lockFile: 'some lock file contents',
       });
-      jest.spyOn(lockFiles, 'determineLockFileDirs');
+      vi.spyOn(lockFiles, 'determineLockFileDirs');
     });
 
     it('returns no error and empty lockfiles if updateLockFiles false', async () => {
diff --git a/lib/workers/repository/update/branch/schedule.spec.ts b/lib/workers/repository/update/branch/schedule.spec.ts
index 4dacb99da8..596927b15e 100644
--- a/lib/workers/repository/update/branch/schedule.spec.ts
+++ b/lib/workers/repository/update/branch/schedule.spec.ts
@@ -142,11 +142,11 @@ describe('workers/repository/update/branch/schedule', () => {
     let config: RenovateConfig;
 
     beforeAll(() => {
-      jest.useFakeTimers();
+      vi.useFakeTimers();
     });
 
     beforeEach(() => {
-      jest.setSystemTime(new Date('2017-06-30T10:50:00.000')); // Locally 2017-06-30 10:50am
+      vi.setSystemTime(new Date('2017-06-30T10:50:00.000')); // Locally 2017-06-30 10:50am
 
       config = {};
     });
@@ -247,7 +247,7 @@ describe('workers/repository/update/branch/schedule', () => {
 
     describe('supports cron syntax on Sundays', () => {
       beforeEach(() => {
-        jest.setSystemTime(new Date('2023-01-08T10:50:00.000')); // Locally Sunday 8 January 2023 10:50am
+        vi.setSystemTime(new Date('2023-01-08T10:50:00.000')); // Locally Sunday 8 January 2023 10:50am
       });
 
       it('approves if the weekday is *', () => {
@@ -271,7 +271,7 @@ describe('workers/repository/update/branch/schedule', () => {
 
     describe('supports L syntax in cron schedules', () => {
       beforeEach(() => {
-        jest.setSystemTime(new Date('2024-10-31T10:50:00.000'));
+        vi.setSystemTime(new Date('2024-10-31T10:50:00.000'));
       });
 
       it('supports last day of month', () => {
@@ -291,7 +291,7 @@ describe('workers/repository/update/branch/schedule', () => {
 
     describe('supports # syntax in cron schedules', () => {
       it('supports first Monday of month', () => {
-        jest.setSystemTime(new Date('2024-10-07T10:50:00.000'));
+        vi.setSystemTime(new Date('2024-10-07T10:50:00.000'));
         config.schedule = ['* * * * 1#1'];
         expect(schedule.isScheduledNow(config)).toBeTrue();
         config.schedule = ['* * * * 1#2'];
@@ -310,7 +310,7 @@ describe('workers/repository/update/branch/schedule', () => {
         ${'2017-06-29T04:01:00.000'} | ${false}
       `('$sched, $tz, $datetime', ({ datetime, expected }) => {
         config.schedule = ['* 0-5 1-7,15-22 * 4'];
-        jest.setSystemTime(new Date(datetime));
+        vi.setSystemTime(new Date(datetime));
         expect(schedule.isScheduledNow(config)).toBe(expected);
       });
     });
@@ -329,7 +329,7 @@ describe('workers/repository/update/branch/schedule', () => {
       `('$sched, $tz, $datetime', ({ sched, tz, datetime, expected }) => {
         config.schedule = [sched];
         config.timezone = tz;
-        jest.setSystemTime(new Date(datetime));
+        vi.setSystemTime(new Date(datetime));
         expect(schedule.isScheduledNow(config)).toBe(expected);
       });
     });
@@ -402,63 +402,63 @@ describe('workers/repository/update/branch/schedule', () => {
 
     it('approves first day of the month', () => {
       config.schedule = ['before 11am on the first day of the month'];
-      jest.setSystemTime(new Date('2017-10-01T05:26:06.000')); // Locally Sunday, 1 October 2017 05:26:06
+      vi.setSystemTime(new Date('2017-10-01T05:26:06.000')); // Locally Sunday, 1 October 2017 05:26:06
       const res = schedule.isScheduledNow(config);
       expect(res).toBeTrue();
     });
 
     it('approves valid weeks of year', () => {
       config.schedule = ['every 2 weeks of the year before 08:00 on Monday'];
-      jest.setSystemTime(new Date('2017-01-02T06:00:00.000')); // Locally Monday, 2 January 2017 6am (first Monday of the year)
+      vi.setSystemTime(new Date('2017-01-02T06:00:00.000')); // Locally Monday, 2 January 2017 6am (first Monday of the year)
       const res = schedule.isScheduledNow(config);
       expect(res).toBeTrue();
     });
 
     it('rejects on weeks of year', () => {
       config.schedule = ['every 2 weeks of the year before 08:00 on Monday'];
-      jest.setSystemTime(new Date('2017-01-09T06:00:00.000')); // Locally Monday, 2 January 2017 6am (second Monday of the year)
+      vi.setSystemTime(new Date('2017-01-09T06:00:00.000')); // Locally Monday, 2 January 2017 6am (second Monday of the year)
       const res = schedule.isScheduledNow(config);
       expect(res).toBeFalse();
     });
 
     it('approves on months of year', () => {
       config.schedule = ['of January'];
-      jest.setSystemTime(new Date('2017-01-02T06:00:00.000')); // Locally Monday, 2 January 2017 6am
+      vi.setSystemTime(new Date('2017-01-02T06:00:00.000')); // Locally Monday, 2 January 2017 6am
       const res = schedule.isScheduledNow(config);
       expect(res).toBeTrue();
     });
 
     it('rejects on months of year', () => {
       config.schedule = ['of January'];
-      jest.setSystemTime(new Date('2017-02-02T06:00:00.000')); // Locally Thursday, 2 February 2017 6am
+      vi.setSystemTime(new Date('2017-02-02T06:00:00.000')); // Locally Thursday, 2 February 2017 6am
       const res = schedule.isScheduledNow(config);
       expect(res).toBeFalse();
     });
 
     it('approves schedule longer than 1 month', () => {
       config.schedule = ['every 3 months'];
-      jest.setSystemTime(new Date('2017-07-01T06:00:00.000')); // Locally Saturday, 1 July 2017 6am
+      vi.setSystemTime(new Date('2017-07-01T06:00:00.000')); // Locally Saturday, 1 July 2017 6am
       const res = schedule.isScheduledNow(config);
       expect(res).toBeTrue();
     });
 
     it('rejects schedule longer than 1 month', () => {
       config.schedule = ['every 6 months'];
-      jest.setSystemTime(new Date('2017-02-01T06:00:00.000')); // Locally Thursday, 2 February 2017 6am
+      vi.setSystemTime(new Date('2017-02-01T06:00:00.000')); // Locally Thursday, 2 February 2017 6am
       const res = schedule.isScheduledNow(config);
       expect(res).toBeFalse();
     });
 
     it('approves schedule longer than 1 month with day of month', () => {
       config.schedule = ['every 3 months on the first day of the month'];
-      jest.setSystemTime(new Date('2017-07-01T06:00:00.000')); // Locally Saturday, 1 July 2017 6am
+      vi.setSystemTime(new Date('2017-07-01T06:00:00.000')); // Locally Saturday, 1 July 2017 6am
       const res = schedule.isScheduledNow(config);
       expect(res).toBeTrue();
     });
 
     it('rejects schedule longer than 1 month with day of month', () => {
       config.schedule = ['every 3 months on the first day of the month'];
-      jest.setSystemTime(new Date('2017-02-01T06:00:00.000')); // Locally Thursday, 2 February 2017 6am
+      vi.setSystemTime(new Date('2017-02-01T06:00:00.000')); // Locally Thursday, 2 February 2017 6am
       const res = schedule.isScheduledNow(config);
       expect(res).toBeFalse();
     });
@@ -473,7 +473,7 @@ describe('workers/repository/update/branch/schedule', () => {
       ];
 
       cases.forEach(([datetime, expected]) => {
-        jest.setSystemTime(new Date(datetime));
+        vi.setSystemTime(new Date(datetime));
         expect(schedule.isScheduledNow(config)).toBe(expected);
       });
     });
diff --git a/lib/workers/repository/update/pr/automerge.spec.ts b/lib/workers/repository/update/pr/automerge.spec.ts
index 71d389ad12..3f65a3ba92 100644
--- a/lib/workers/repository/update/pr/automerge.spec.ts
+++ b/lib/workers/repository/update/pr/automerge.spec.ts
@@ -7,7 +7,7 @@ import * as prAutomerge from './automerge';
 
 describe('workers/repository/update/pr/automerge', () => {
   describe('checkAutoMerge(pr, config)', () => {
-    const spy = jest.spyOn(schedule, 'isScheduledNow');
+    const spy = vi.spyOn(schedule, 'isScheduledNow');
     let config: BranchConfig;
     let pr: Pr;
 
diff --git a/lib/workers/repository/update/pr/changelog/github/index.spec.ts b/lib/workers/repository/update/pr/changelog/github/index.spec.ts
index 79b5b8219e..439f3003f6 100644
--- a/lib/workers/repository/update/pr/changelog/github/index.spec.ts
+++ b/lib/workers/repository/update/pr/changelog/github/index.spec.ts
@@ -313,7 +313,7 @@ describe('workers/repository/update/pr/changelog/github/index', () => {
     });
 
     it('works with same version releases but different prefix', async () => {
-      const githubTagsMock = jest.spyOn(githubGraphql, 'queryTags');
+      const githubTagsMock = vi.spyOn(githubGraphql, 'queryTags');
       githubTagsMock.mockResolvedValue(
         partial<GithubTagItem>([
           { version: 'v1.0.1' },
diff --git a/lib/workers/repository/update/pr/changelog/release-notes.spec.ts b/lib/workers/repository/update/pr/changelog/release-notes.spec.ts
index fc7091a85e..e431989554 100644
--- a/lib/workers/repository/update/pr/changelog/release-notes.spec.ts
+++ b/lib/workers/repository/update/pr/changelog/release-notes.spec.ts
@@ -113,7 +113,7 @@ const gitlabProject = partial<ChangeLogProject>({
 });
 
 describe('workers/repository/update/pr/changelog/release-notes', () => {
-  const githubReleasesMock = jest.spyOn(githubGraphql, 'queryReleases');
+  const githubReleasesMock = vi.spyOn(githubGraphql, 'queryReleases');
 
   beforeEach(() => {
     hostRules.find.mockReturnValue({});
diff --git a/lib/workers/repository/update/pr/changelog/releases.spec.ts b/lib/workers/repository/update/pr/changelog/releases.spec.ts
index a9ca341c0e..a140e95e9c 100644
--- a/lib/workers/repository/update/pr/changelog/releases.spec.ts
+++ b/lib/workers/repository/update/pr/changelog/releases.spec.ts
@@ -8,7 +8,7 @@ import * as releases from './releases';
 describe('workers/repository/update/pr/changelog/releases', () => {
   describe('getReleaseNotes()', () => {
     beforeEach(() => {
-      jest.spyOn(datasource, 'getPkgReleases').mockResolvedValueOnce({
+      vi.spyOn(datasource, 'getPkgReleases').mockResolvedValueOnce({
         releases: [
           {
             version: '1.0.0',
diff --git a/lib/workers/repository/update/pr/index.spec.ts b/lib/workers/repository/update/pr/index.spec.ts
index d43e09ec20..cb61b657e0 100644
--- a/lib/workers/repository/update/pr/index.spec.ts
+++ b/lib/workers/repository/update/pr/index.spec.ts
@@ -676,9 +676,9 @@ describe('workers/repository/update/pr/index', () => {
       it('comments on automerge failure', async () => {
         platform.createPr.mockResolvedValueOnce(pr);
         checks.resolveBranchStatus.mockResolvedValueOnce('red');
-        jest
-          .spyOn(platform, 'massageMarkdown')
-          .mockImplementation((prBody) => 'markdown content');
+        vi.spyOn(platform, 'massageMarkdown').mockImplementation(
+          (prBody) => 'markdown content',
+        );
         await ensurePr({
           ...config,
           automerge: true,
diff --git a/lib/workers/repository/update/pr/labels.spec.ts b/lib/workers/repository/update/pr/labels.spec.ts
index 480405997f..90fc07d6a5 100644
--- a/lib/workers/repository/update/pr/labels.spec.ts
+++ b/lib/workers/repository/update/pr/labels.spec.ts
@@ -101,7 +101,7 @@ describe('workers/repository/update/pr/labels', () => {
       });
 
       it('gitlab', () => {
-        jest.spyOn(platform, 'labelCharLimit').mockImplementationOnce(() => {
+        vi.spyOn(platform, 'labelCharLimit').mockImplementationOnce(() => {
           return 255;
         });
         // platform.labelCharLimit.mockReturnValueOnce(255);
diff --git a/lib/workers/repository/update/pr/participants.spec.ts b/lib/workers/repository/update/pr/participants.spec.ts
index f2a4435227..1acc525111 100644
--- a/lib/workers/repository/update/pr/participants.spec.ts
+++ b/lib/workers/repository/update/pr/participants.spec.ts
@@ -39,7 +39,7 @@ describe('workers/repository/update/pr/participants', () => {
     });
 
     it('filters assignees', async () => {
-      platform.filterUnavailableUsers = jest
+      platform.filterUnavailableUsers = vi
         .fn()
         .mockResolvedValueOnce(['a', 'b']);
       await addParticipants({ ...config, filterUnavailableUsers: true }, pr);
@@ -52,7 +52,7 @@ describe('workers/repository/update/pr/participants', () => {
         '@group',
         'u@email.com',
       ]);
-      platform.expandGroupMembers = jest
+      platform.expandGroupMembers = vi
         .fn()
         .mockResolvedValueOnce(['u@email.com', 'user', 'group.user']);
       await addParticipants(
@@ -81,7 +81,7 @@ describe('workers/repository/update/pr/participants', () => {
 
     it('does not expand group code owners assignees when assigneesFromCodeOwners disabled', async () => {
       codeOwners.codeOwnersForPr.mockResolvedValueOnce(['user', '@group']);
-      platform.expandGroupMembers = jest
+      platform.expandGroupMembers = vi
         .fn()
         .mockResolvedValueOnce(['user', 'group.user']);
       await addParticipants(config, pr);
@@ -92,7 +92,7 @@ describe('workers/repository/update/pr/participants', () => {
 
     it('does not expand group code owners assignees when expandCodeOwnersGroups disabled', async () => {
       codeOwners.codeOwnersForPr.mockResolvedValueOnce(['user', '@group']);
-      platform.expandGroupMembers = jest
+      platform.expandGroupMembers = vi
         .fn()
         .mockResolvedValueOnce(['user', 'group.user']);
       await addParticipants({ ...config, assigneesFromCodeOwners: true }, pr);
diff --git a/lib/workers/repository/update/pr/pr-cache.spec.ts b/lib/workers/repository/update/pr/pr-cache.spec.ts
index afbb116ad1..ea63074f75 100644
--- a/lib/workers/repository/update/pr/pr-cache.spec.ts
+++ b/lib/workers/repository/update/pr/pr-cache.spec.ts
@@ -59,7 +59,7 @@ describe('workers/repository/update/pr/pr-cache', () => {
 
     it('updates cache', () => {
       cache.getCache.mockReturnValue(dummyCache);
-      jest.useFakeTimers().setSystemTime(new Date('2020-01-01'));
+      vi.useFakeTimers().setSystemTime(new Date('2020-01-01'));
       setPrCache('branch_name', 'fingerprint_hash', true);
       expect(dummyCache).toStrictEqual({
         branches: [
@@ -87,7 +87,7 @@ describe('workers/repository/update/pr/pr-cache', () => {
         ],
       };
       cache.getCache.mockReturnValue(dummyCache);
-      jest.useFakeTimers().setSystemTime(new Date('2020-01-02'));
+      vi.useFakeTimers().setSystemTime(new Date('2020-01-02'));
       setPrCache('branch_name', 'fingerprint_hash', false);
       expect(dummyCache2).toStrictEqual({
         branches: [
diff --git a/test/jest-legacy.ts b/test/jest-legacy.ts
deleted file mode 100644
index 993c09667c..0000000000
--- a/test/jest-legacy.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-import { vi } from 'vitest';
-
-// TODO: remove when all tests are migrated to vitest
-Object.defineProperty(globalThis, 'jest', {
-  value: {
-    fn: vi.fn,
-    spyOn: vi.spyOn,
-    doMock: vi.doMock,
-    doUnmock: vi.doUnmock,
-    resetModules: vi.resetModules,
-    resetAllMocks: vi.resetAllMocks,
-    restoreAllMocks: vi.restoreAllMocks,
-    useFakeTimers: vi.useFakeTimers,
-    useRealTimers: vi.useRealTimers,
-    setSystemTime: vi.setSystemTime,
-    advanceTimersByTime: vi.advanceTimersByTime,
-    advanceTimersByTimeAsync: vi.advanceTimersByTimeAsync,
-  },
-});
-
-interface GlobalJest {
-  /** @deprecated */
-  fn: typeof vi.fn;
-  /** @deprecated */
-  spyOn: typeof vi.spyOn;
-
-  /** @deprecated */
-  doMock: typeof vi.doMock;
-  /** @deprecated */
-  doUnmock: typeof vi.doUnmock;
-
-  /** @deprecated */
-  resetModules: typeof vi.resetModules;
-
-  /** @deprecated */
-  resetAllMocks: typeof vi.resetAllMocks;
-  /** @deprecated */
-  restoreAllMocks: typeof vi.restoreAllMocks;
-
-  /** @deprecated */
-  useFakeTimers: typeof vi.useFakeTimers;
-  /** @deprecated */
-  useRealTimers: typeof vi.useRealTimers;
-  /** @deprecated */
-  setSystemTime: typeof vi.setSystemTime;
-  /** @deprecated */
-  advanceTimersByTime: typeof vi.advanceTimersByTime;
-  /** @deprecated */
-  advanceTimersByTimeAsync: typeof vi.advanceTimersByTimeAsync;
-}
-
-declare global {
-  /**
-   * @deprecated
-   */
-  const jest: GlobalJest;
-}
diff --git a/vitest.config.ts b/vitest.config.ts
index ae7716726c..7934396325 100644
--- a/vitest.config.ts
+++ b/vitest.config.ts
@@ -81,7 +81,6 @@ export default defineConfig(() =>
           'jest-extended/all',
           'expect-more-jest',
           './test/setup.ts',
-          './test/jest-legacy.ts',
           'test/to-migrate.ts',
         ],
         reporters: ci ? ['default', 'github-actions'] : ['default'],
@@ -89,6 +88,7 @@ export default defineConfig(() =>
         coverage: {
           provider: 'v8',
           ignoreEmptyLines: true,
+          skipFull: !ci,
           reporter: ci
             ? ['text-summary', 'lcovonly', 'json']
             : ['text-summary', 'html', 'json'],
-- 
GitLab