diff --git a/.circleci/config.yml b/.circleci/config.yml
index c55069c469..c54af3903d 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -14,20 +14,20 @@ commands:
     steps:
       - run: git config --global core.autocrlf input
       - node/install:
-          node-version: '18.20.3'
+          node-version: 20.17.0
       - checkout
   run-lint-and-build:
     steps:
       - node/install-packages
+      - run:
+          name: 'Build Electron Forge'
+          command: |
+            yarn build
       - run:
           name: 'Lint codebase'
           command: |
             yarn lint
             yarn syncpack
-      - run:
-          name: 'Build Electron Forge'
-          command: |
-            yarn build
   run-fast-tests:
     steps:
       - node/install-packages:
@@ -48,9 +48,7 @@ commands:
       - run:
           name: 'Run slow tests'
           command: |
-            echo $(circleci tests glob "packages/**/*_spec_slow.ts")
-            TEST_GLOB=$(circleci tests glob "packages/**/*_spec_slow.ts" | circleci tests split --split-by=timings)
-            yarn test $TEST_GLOB
+            yarn test:slow --reporter=junit --outputFile="./reports/out/test_output.xml"
 
 jobs:
   lint-and-build:
diff --git a/.eslintignore b/.eslintignore
index 4cbf23af1e..f7b1d78263 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -7,4 +7,3 @@ packages/*/*/index.ts
 packages/**/bad.js
 tmpl
 packages/api/core/helper/dynamic-import.js
-packages/plugin/webpack/spec/fixtures/**/*
diff --git a/.eslintrc.json b/.eslintrc.json
index fc145f0e74..9d63c7871a 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -1,8 +1,4 @@
 {
-  "plugins": ["mocha", "import"],
-  "env": {
-    "mocha": true
-  },
   "extends": ["@malept/eslint-config/src/common"],
   "globals": {
     "NodeJS": "readonly"
@@ -17,7 +13,6 @@
         "vars": "all"
       }
     ],
-    "mocha/no-exclusive-tests": "error",
     "import/order": [
       "error",
       {
@@ -69,7 +64,7 @@
       }
     },
     {
-      "files": ["packages/*/*/test/**/*_spec*.ts", "packages/*/*/test/fixture/**/*.ts"],
+      "files": ["packages/*/*/spec/**/*.spec.ts", "packages/*/*/spec/fixture/**/*.ts"],
       "rules": {
         "global-require": "off",
         "import/no-dynamic-require": "off",
@@ -93,13 +88,13 @@
       }
     },
     {
-      "files": ["packages/api/core/test/**/*.ts", "packages/maker/*/src/Maker*.ts"],
+      "files": ["packages/api/core/spec/**/*.ts", "packages/maker/*/src/Maker*.ts"],
       "rules": {
         "@typescript-eslint/no-require-imports": "off"
       }
     },
     {
-      "files": ["packages/*/*/test/fixture/**/*.js", "packages/*/*/test/fixtures/**/*.js"],
+      "files": ["packages/*/*/spec/fixture/**/*.js", "packages/*/*/spec/fixtures/**/*.js"],
       "rules": {
         "node/no-extraneous-require": "off",
         "node/no-missing-require": "off",
@@ -107,7 +102,7 @@
       }
     },
     {
-      "files": ["packages/plugin/webpack/test/fixtures/**/*.js"],
+      "files": ["packages/plugin/webpack/spec/fixtures/**/*.js"],
       "rules": {
         "no-process-exit": "off",
         "no-undef": "off",
diff --git a/.gitignore b/.gitignore
index d3d165dcf2..bb7a85a5f7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,9 +22,9 @@ packages/api/cli/README.md
 packages/**/tsconfig.tsbuildinfo
 packages/**/.swc
 .webpack
-packages/api/core/test/fixture/app-with-scoped-name/out/make
-packages/plugin/webpack/test/fixtures/apps/native-modules/package-lock.json
-packages/plugin/fuses/test/fixture/app
+packages/api/core/spec/fixture/app-with-scoped-name/out/make
+packages/plugin/webpack/spec/fixtures/apps/native-modules/package-lock.json
+packages/plugin/fuses/spec/fixture/app
 .links
 reports
 packages/**/typedoc.json
diff --git a/.mocharc.js b/.mocharc.js
deleted file mode 100644
index b8046fe9da..0000000000
--- a/.mocharc.js
+++ /dev/null
@@ -1,47 +0,0 @@
-const path = require('path');
-const minimist = require('minimist');
-
-const {
-  _: [_node, _mocha, ...args], // _ contains the node binary, the mocha binary, and any positional args
-  ...flags
-} = minimist(process.argv);
-
-process.env.LINK_FORGE_DEPENDENCIES_ON_INIT = true;
-
-let testGlob;
-
-/**
- * Determine which sets of tests to run. Priority goes:
- * 1. If positional arguments are passed in, run those files.
- * 2. If `--suite` is either slow or fast, run slow or fast test.
- * 3. Otherwise, run all spec tests.
- */
-if (args.length === 0) {
-  if (flags.suite === 'fast') {
-    testGlob = 'packages/**/*_spec.ts';
-  } else if (flags.suite === 'slow') {
-    testGlob = 'packages/**/*_spec_slow.ts';
-  } else {
-    testGlob = 'packages/**/**/*_spec*';
-  }
-}
-
-// In CI, use the JUnit reporter to upload results to CircleCI.
-// Locally, use the default 'spec' reporter.
-const reporterConfig = process.env.CI
-  ? {
-      reporter: 'mocha-junit-reporter',
-      'reporter-option': ['mochaFile=./reports/out/test_output.xml'],
-    }
-  : {};
-
-const opts = {
-  extension: ['ts'],
-  require: ['ts-node/register', path.join(__dirname, 'tools', 'test-setup.ts')],
-  spec: testGlob,
-  timeout: 800000,
-  recursive: true,
-  ...reporterConfig,
-};
-
-module.exports = opts;
diff --git a/.prettierignore b/.prettierignore
index 667568b936..95df6730f3 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -9,6 +9,6 @@ packages/*/*/index.ts
 packages/*/*/README.md
 packages/*/*/tsconfig.json
 packages/*/*/typedoc.json
-packages/api/core/test/fixture/bad_external_forge_config/bad.js
+packages/api/core/spec/fixture/bad_external_forge_config/bad.js
 packages/plugin/webpack/spec/**/.webpack
 .links
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
index e89e3baeac..3e6cc1fd54 100644
--- a/.vscode/extensions.json
+++ b/.vscode/extensions.json
@@ -1,3 +1,3 @@
 {
-  "recommendations": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode", "maty.vscode-mocha-sidebar"]
+  "recommendations": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode", "vitest.explorer"]
 }
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 871043a5f2..5f8eeaa9e6 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -13,17 +13,5 @@
       "source.fixAll.eslint": "explicit"
     },
     "editor.defaultFormatter": "esbenp.prettier-vscode"
-  },
-  "mocha.env": {
-    "TS_NODE_PROJECT": "tsconfig.test.json",
-    "TS_NODE_FILES": "1",
-    "TEST_FAST_ONLY": "1"
-  },
-  "mocha.files.glob": "packages/*/*/test/**/*_spec*.ts",
-  "mocha.requires": ["ts-node/register", "tools/test-setup.ts"],
-  "mocha.options": {
-    "extension": ["ts"],
-    "timeout": 800000,
-    "recursive": true
   }
 }
diff --git a/package.json b/package.json
index 24f44d15ce..c5512aa346 100644
--- a/package.json
+++ b/package.json
@@ -21,9 +21,9 @@
     "lint:fix": "prettier --write . && eslint --fix .",
     "link:prepare": "lerna exec -- node ../../../tools/silent.js yarn link --silent --no-bin-links --link-folder ../../../.links",
     "link:remove": "lerna exec -- node ../../../tools/silent.js yarn unlink --silent --no-bin-links --link-folder ../../../.links",
-    "test": "npm run test:clear && xvfb-maybe cross-env NODE_ENV=test TS_NODE_PROJECT='./tsconfig.test.json' TS_NODE_FILES=1 mocha",
-    "test:fast": "xvfb-maybe vitest run",
-    "test:slow": "npm run test -- --suite=slow",
+    "test": "xvfb-maybe vitest run --project fast --project slow",
+    "test:fast": "xvfb-maybe vitest run --project fast",
+    "test:slow": "xvfb-maybe vitest run --project slow",
     "test:clear": "ts-node tools/test-clear",
     "postinstall": "rimraf node_modules/.bin/*.ps1 && ts-node ./tools/gen-tsconfigs.ts && ts-node ./tools/gen-ts-glue.ts",
     "prepare": "husky install",
@@ -85,8 +85,6 @@
     "@electron/fuses": ">=1.0.0",
     "@electron/lint-roller": "1.10.1",
     "@malept/eslint-config": "^2.0.0",
-    "@types/chai": "^4.2.12",
-    "@types/chai-as-promised": "^7.1.2",
     "@types/cross-spawn": "^6.0.1",
     "@types/debug": "^4.1.5",
     "@types/express": "^4.17.9",
@@ -98,7 +96,6 @@
     "@types/lodash": "^4.14.166",
     "@types/mime-types": "^2.1.0",
     "@types/minimist": "^1.2.0",
-    "@types/mocha": "^9.0.0",
     "@types/node": "^18.0.3",
     "@types/node-fetch": "^2.5.5",
     "@types/rechoir": "^0.6.1",
@@ -106,13 +103,9 @@
     "@types/which": "^2.0.0",
     "@typescript-eslint/eslint-plugin": "^8.0.0",
     "@typescript-eslint/parser": "^8.0.0",
-    "chai": "^4.3.3",
-    "chai-as-promised": "^7.0.0",
-    "cross-env": "^7.0.2",
     "electron-installer-common": "^0.10.2",
     "eslint": "^8.56.0",
     "eslint-plugin-import": "^2.31.0",
-    "eslint-plugin-mocha": "^9.0.0",
     "eslint-plugin-node": "^11.1.0",
     "eslint-plugin-prettier": "^4.0.0",
     "eslint-plugin-promise": "^6.0.0",
@@ -124,8 +117,6 @@
     "lerna": "^7.4.2",
     "lint-staged": "^12.1.7",
     "minimist": "^1.2.6",
-    "mocha": "^9.0.1",
-    "mocha-junit-reporter": "^2.2.1",
     "msw": "^2.7.0",
     "prettier": "^2.4.0",
     "rimraf": "^3.0.1",
diff --git a/packages/api/cli/package.json b/packages/api/cli/package.json
index 2669fcfa94..54f5fbf94f 100644
--- a/packages/api/cli/package.json
+++ b/packages/api/cli/package.json
@@ -12,9 +12,6 @@
   },
   "devDependencies": {
     "@malept/cross-spawn-promise": "^2.0.0",
-    "chai": "^4.3.3",
-    "chai-as-promised": "^7.0.0",
-    "mocha": "^9.0.1",
     "vitest": "^2.1.6"
   },
   "dependencies": {
diff --git a/packages/api/cli/spec/cli.spec.ts b/packages/api/cli/spec/cli.slow.spec.ts
similarity index 92%
rename from packages/api/cli/spec/cli.spec.ts
rename to packages/api/cli/spec/cli.slow.spec.ts
index 997621bf3b..1d92067eb7 100644
--- a/packages/api/cli/spec/cli.spec.ts
+++ b/packages/api/cli/spec/cli.slow.spec.ts
@@ -8,7 +8,7 @@ function runForgeCLI(...extraArgs: string[]): Promise<string> {
   return spawn('npx', args);
 }
 
-describe('cli', { timeout: 30_000 }, () => {
+describe('cli', () => {
   it('should not fail on known subcommands', async () => {
     await expect(runForgeCLI('help')).resolves.toMatch(/Usage:/);
   });
diff --git a/packages/api/core/package.json b/packages/api/core/package.json
index 2c43de7cbd..dac732dc25 100644
--- a/packages/api/core/package.json
+++ b/packages/api/core/package.json
@@ -7,13 +7,6 @@
   "typings": "dist/api/index.d.ts",
   "author": "Samuel Attard",
   "license": "MIT",
-  "scripts": {
-    "coverage:base": "nyc yarn test:base",
-    "test": "yarn test:base test/**/*_spec.ts test/**/*_spec_slow.ts",
-    "test:base": "cross-env TS_NODE_FILES=1 mocha --config ../../../.mocharc.js",
-    "test:fast": "yarn test:base test/fast/**/*_spec.ts",
-    "test:slow": "yarn test:base test/slow/**/*_spec_slow.ts"
-  },
   "devDependencies": {
     "@electron-forge/maker-appx": "7.6.0",
     "@electron-forge/maker-deb": "7.6.0",
@@ -28,11 +21,8 @@
     "@types/interpret": "^1.1.1",
     "@types/progress": "^2.0.5",
     "@types/rechoir": "^0.6.1",
-    "chai": "^4.3.3",
-    "chai-as-promised": "^7.0.0",
     "cross-env": "^7.0.2",
     "electron-installer-common": "^0.10.2",
-    "mocha": "^9.0.1",
     "vitest": "^2.1.6",
     "yaml-hook": "^1.0.0"
   },
diff --git a/packages/api/core/test/.eslintrc b/packages/api/core/spec/.eslintrc
similarity index 74%
rename from packages/api/core/test/.eslintrc
rename to packages/api/core/spec/.eslintrc
index fcf427ed5d..205240237f 100644
--- a/packages/api/core/test/.eslintrc
+++ b/packages/api/core/spec/.eslintrc
@@ -1,7 +1,4 @@
 {
-  "env": {
-    "mocha": true
-  },
   "rules": {
     "class-methods-use-this": 0,
     "import/no-extraneous-dependencies": 0
diff --git a/packages/api/core/test/slow/init_git_spec_slow.ts b/packages/api/core/spec/fast/init-git.spec.ts
similarity index 58%
rename from packages/api/core/test/slow/init_git_spec_slow.ts
rename to packages/api/core/spec/fast/init-git.spec.ts
index 1134e087f7..ffe390a2ce 100644
--- a/packages/api/core/test/slow/init_git_spec_slow.ts
+++ b/packages/api/core/spec/fast/init-git.spec.ts
@@ -1,9 +1,9 @@
 import { execSync } from 'node:child_process';
+import fs from 'node:fs';
 import os from 'node:os';
 import path from 'node:path';
 
-import { expect } from 'chai';
-import fs from 'fs-extra';
+import { beforeEach, describe, expect, it } from 'vitest';
 
 import { initGit } from '../../src/api/init-scripts/init-git';
 
@@ -13,56 +13,56 @@ let dirID = Date.now();
 const ensureTestDirIsNonexistent = async () => {
   dir = path.resolve(os.tmpdir(), `electron-forge-git-test-${dirID}`);
   dirID += 1;
-  await fs.remove(dir);
+  await fs.promises.rm(dir, { recursive: true, force: true });
 };
 
 describe('init-git', () => {
   beforeEach(async () => {
     await ensureTestDirIsNonexistent();
-    await fs.mkdir(dir);
+    await fs.promises.mkdir(dir, { recursive: true });
   });
 
   it('creates Git repository when run inside non-Git directory', async () => {
     await initGit(dir);
     const gitDir = path.join(dir, '.git');
-    expect(await fs.pathExists(gitDir), 'the .git directory inside the folder').to.equal(true);
+    expect(fs.existsSync(gitDir), 'the .git directory inside the folder').toEqual(true);
   });
 
   it('skips when run at root of Git repository', async () => {
-    await execSync('git init', { cwd: dir });
+    execSync('git init', { cwd: dir });
 
     const gitDir = path.join(dir, '.git');
     const config = path.join(gitDir, 'config');
-    const statBefore = await fs.lstat(config);
+    const statBefore = await fs.promises.lstat(config);
     const before = statBefore.mtimeMs;
 
     await initGit(dir);
 
-    const statAfter = await fs.lstat(config);
+    const statAfter = await fs.promises.lstat(config);
     const after = statAfter.mtimeMs;
 
-    expect(after, 'the config file in the repository').to.equal(before);
+    expect(after, 'the config file in the repository').toEqual(before);
   });
 
   it('skips when run in subdirectory of Git repository', async () => {
-    await execSync('git init', { cwd: dir });
+    execSync('git init', { cwd: dir });
 
     const gitDir = path.join(dir, '.git');
     const config = path.join(gitDir, 'config');
-    const statBefore = await fs.lstat(config);
+    const statBefore = await fs.promises.lstat(config);
     const before = statBefore.mtimeMs;
 
     const subdir = path.join(dir, 'some', 'other', 'folder');
     const innerGitDir = path.join(subdir, '.git');
 
-    await fs.mkdirp(subdir);
+    await fs.promises.mkdir(subdir, { recursive: true });
 
     await initGit(subdir);
 
-    const statAfter = await fs.lstat(config);
+    const statAfter = await fs.promises.lstat(config);
     const after = statAfter.mtimeMs;
 
-    expect(after, 'the config file in the repository').to.equal(before);
-    expect(await fs.pathExists(innerGitDir), 'a nested .git directory inside the repository').to.equal(false);
+    expect(after, 'the config file in the repository').toEqual(before);
+    expect(fs.existsSync(innerGitDir), 'a nested .git directory inside the repository').toEqual(false);
   });
 });
diff --git a/packages/api/core/spec/fast/make.spec.ts b/packages/api/core/spec/fast/make.spec.ts
index 7541fcd2fb..33c689c098 100644
--- a/packages/api/core/spec/fast/make.spec.ts
+++ b/packages/api/core/spec/fast/make.spec.ts
@@ -14,7 +14,7 @@ vi.mock(import('@electron-forge/core-utils'), async (importOriginal) => {
 });
 
 describe('make', () => {
-  const fixtureDir = path.resolve(__dirname, '../../test/fixture');
+  const fixtureDir = path.resolve(__dirname, '../fixture');
 
   it.todo('should call "package"');
 
diff --git a/packages/api/core/spec/fast/util/electron-executable.spec.ts b/packages/api/core/spec/fast/util/electron-executable.spec.ts
index d371133866..fffb61be05 100644
--- a/packages/api/core/spec/fast/util/electron-executable.spec.ts
+++ b/packages/api/core/spec/fast/util/electron-executable.spec.ts
@@ -4,7 +4,7 @@ import { describe, expect, it } from 'vitest';
 
 import locateElectronExecutable from '../../../src/util/electron-executable';
 
-const fixtureDir = path.resolve(__dirname, '..', '..', '..', 'test', 'fixture', 'electron-executable');
+const fixtureDir = path.resolve(__dirname, '..', '..', 'fixture', 'electron-executable');
 
 describe('locateElectronExecutable', () => {
   it('returns the correct path to electron', async () => {
diff --git a/packages/api/core/spec/fast/util/forge-config.spec.ts b/packages/api/core/spec/fast/util/forge-config.spec.ts
index a4672b81e9..212eaa60d2 100644
--- a/packages/api/core/spec/fast/util/forge-config.spec.ts
+++ b/packages/api/core/spec/fast/util/forge-config.spec.ts
@@ -20,20 +20,20 @@ const DEFAULTS = {
 
 describe('findConfig', () => {
   it('falls back to default if no config exists', async () => {
-    const fixturePath = path.resolve(__dirname, '../../../test/fixture/no_forge_config');
+    const fixturePath = path.resolve(__dirname, '../../fixture/no_forge_config');
     const config = await findConfig(fixturePath);
     expect(config).toEqual({ ...DEFAULTS, pluginInterface: expect.objectContaining({}) });
   });
 
   it('sets a pluginInterface property', async () => {
-    const fixturePath = path.resolve(__dirname, '../../../test/fixture/dummy_app');
+    const fixturePath = path.resolve(__dirname, '../../fixture/dummy_app');
     const config = await findConfig(fixturePath);
     expect(config).toEqual(expect.objectContaining({ pluginInterface: expect.objectContaining({}) }));
   });
 
   it('should resolve undefined from fromBuildIdentifier if no value is provided', async () => {
     type ResolveUndefConfig = ResolvedForgeConfig & { topLevelUndef?: string };
-    const conf = (await findConfig(path.resolve(__dirname, '../../../test/fixture/dummy_js_conf'))) as ResolveUndefConfig;
+    const conf = (await findConfig(path.resolve(__dirname, '../../fixture/dummy_js_conf'))) as ResolveUndefConfig;
     expect(conf.topLevelUndef).toEqual(undefined);
   });
 
@@ -45,13 +45,13 @@ describe('findConfig', () => {
         };
       };
     };
-    const conf = (await findConfig(path.resolve(__dirname, '../../../test/fixture/dummy_js_conf'))) as NestedConfig;
+    const conf = (await findConfig(path.resolve(__dirname, '../../fixture/dummy_js_conf'))) as NestedConfig;
     expect(Array.isArray(conf.sub.prop.inArray)).toEqual(true);
   });
 
   it('should leave regexps intact', async () => {
     type RegExpConfig = ResolvedForgeConfig & { regexp: RegExp };
-    const conf = (await findConfig(path.resolve(__dirname, '../../../test/fixture/dummy_js_conf'))) as RegExpConfig;
+    const conf = (await findConfig(path.resolve(__dirname, '../../fixture/dummy_js_conf'))) as RegExpConfig;
     expect(conf.regexp).toBeInstanceOf(RegExp);
     expect(conf.regexp.test('foo')).toEqual(true);
     expect(conf.regexp.test('bar')).toEqual(false);
@@ -59,21 +59,21 @@ describe('findConfig', () => {
 
   describe('from package.json', () => {
     it('throws if the "config.forge" property is not an object or requirable path', async () => {
-      const fixturePath = path.resolve(__dirname, '../../../test/fixture/bad_forge_config');
+      const fixturePath = path.resolve(__dirname, '../../fixture/bad_forge_config');
       const err = 'Expected packageJSON.config.forge to be an object or point to a requirable JS file';
       await expect(findConfig(fixturePath)).rejects.toThrow(err);
     });
 
     it('throws if the "config.forge" property is not parseable', async () => {
       const spy = vi.spyOn(console, 'error').mockImplementation(() => undefined);
-      const fixturePath = path.resolve(__dirname, '../../../test/fixture/bad_external_forge_config');
+      const fixturePath = path.resolve(__dirname, '../../fixture/bad_external_forge_config');
       const err = /Unexpected token/;
       await expect(findConfig(fixturePath)).rejects.toThrow(err);
       spy.mockRestore();
     });
 
     it('should resolve the "config.forge" object', async () => {
-      const fixturePath = path.resolve(__dirname, '../../../test/fixture/dummy_app');
+      const fixturePath = path.resolve(__dirname, '../../fixture/dummy_app');
       const config = await findConfig(fixturePath);
       expect(config).toEqual({
         ...DEFAULTS,
@@ -88,7 +88,7 @@ describe('findConfig', () => {
 
   describe('from forge.config.js', () => {
     it('resolves when "config.forge" points to a JS file', async () => {
-      const fixturePath = path.resolve(__dirname, '../../../test/fixture/dummy_js_conf');
+      const fixturePath = path.resolve(__dirname, '../../fixture/dummy_js_conf');
       const config = await findConfig(fixturePath);
       expect(config).toEqual(
         expect.objectContaining({
@@ -102,13 +102,13 @@ describe('findConfig', () => {
     });
 
     it('falls back to forge.config.js if "config.forge" does not exist', async () => {
-      const fixturePath = path.resolve(__dirname, '../../../test/fixture/dummy_default_js_conf');
+      const fixturePath = path.resolve(__dirname, '../../fixture/dummy_default_js_conf');
       const conf = await findConfig(fixturePath);
       expect(conf.buildIdentifier).toEqual('default');
     });
 
     it('maintains functions from the JS export', async () => {
-      const fixturePath = path.resolve(__dirname, '../../../test/fixture/dummy_js_conf');
+      const fixturePath = path.resolve(__dirname, '../../fixture/dummy_js_conf');
       const conf = await findConfig(fixturePath);
       const preStart = conf.hooks?.preStart;
       expect(preStart).not.toBeUndefined();
@@ -117,7 +117,7 @@ describe('findConfig', () => {
     });
 
     it('should support async configs', async () => {
-      const fixturePath = path.resolve(__dirname, '../../../test/fixture/async_forge_config');
+      const fixturePath = path.resolve(__dirname, '../../fixture/async_forge_config');
       const config = await findConfig(fixturePath);
       expect(config).toEqual({
         ...DEFAULTS,
@@ -134,7 +134,7 @@ describe('findConfig', () => {
 
     it('should support ESM configs', async () => {
       type DefaultResolvedConfig = ResolvedForgeConfig & { defaultResolved: boolean };
-      const conf = (await findConfig(path.resolve(__dirname, '../../../test/fixture/dummy_default_esm_conf'))) as DefaultResolvedConfig;
+      const conf = (await findConfig(path.resolve(__dirname, '../../fixture/dummy_default_esm_conf'))) as DefaultResolvedConfig;
       expect(conf.buildIdentifier).toEqual('esm');
       expect(conf.defaultResolved).toEqual(true);
     });
@@ -143,7 +143,7 @@ describe('findConfig', () => {
   describe('proxied objects', () => {
     it('allows access to built-ins', async () => {
       // Why: This needs to get refactored anyway.
-      const fixture = path.resolve(__dirname, '../../../test/fixture/dummy_js_conf');
+      const fixture = path.resolve(__dirname, '../../fixture/dummy_js_conf');
       // eslint-disable-next-line @typescript-eslint/no-explicit-any
       const conf: any = await findConfig(fixture);
       expect(conf.packagerConfig.baz.hasOwnProperty).toBeTypeOf('function');
@@ -156,7 +156,7 @@ describe('findConfig', () => {
     it('allows overwrite of properties', async () => {
       // Why: This needs to get refactored anyway.
       // eslint-disable-next-line @typescript-eslint/no-explicit-any
-      const conf: any = await findConfig(path.resolve(__dirname, '../../../test/fixture/dummy_js_conf'));
+      const conf: any = await findConfig(path.resolve(__dirname, '../../fixture/dummy_js_conf'));
       expect(conf.packagerConfig.baz.hasOwnProperty).toBeTypeOf('function');
       expect(() => {
         conf.packagerConfig.baz = 'bar';
@@ -186,7 +186,7 @@ describe('findConfig', () => {
           baseUrl: string;
         };
       };
-      const conf = (await findConfig(path.resolve(__dirname, '../../../test/fixture/dummy_js_conf'))) as MappedConfig;
+      const conf = (await findConfig(path.resolve(__dirname, '../../fixture/dummy_js_conf'))) as MappedConfig;
       expect(conf.s3.secretAccessKey).toBe(undefined);
 
       process.env.ELECTRON_FORGE_S3_SECRET_ACCESS_KEY = 'SecretyThing';
@@ -200,7 +200,7 @@ describe('findConfig', () => {
 
   describe('virtual config', () => {
     it('should resolve to the virtual config if present', async () => {
-      const fixture = path.resolve(__dirname, '../../../test/fixture/no_forge_config');
+      const fixture = path.resolve(__dirname, '../../fixture/no_forge_config');
       try {
         registerForgeConfigForDirectory(fixture, { outDir: 'magic' });
         const config = await findConfig(fixture);
@@ -215,7 +215,7 @@ describe('findConfig', () => {
     });
 
     it('should prioritize virtual config over package.json', async () => {
-      const fixturePath = path.resolve(__dirname, '../../../test/fixture/dummy_app');
+      const fixturePath = path.resolve(__dirname, '../../fixture/dummy_app');
       try {
         registerForgeConfigForDirectory(fixturePath, { outDir: 'magic' });
         const config = await findConfig(fixturePath);
@@ -230,7 +230,7 @@ describe('findConfig', () => {
     });
 
     it('should prioritize virtual config over forge.config.js', async () => {
-      const fixturePath = path.resolve(__dirname, '../../../test/fixture/async_forge_config');
+      const fixturePath = path.resolve(__dirname, '../../fixture/async_forge_config');
       try {
         registerForgeConfigForDirectory(fixturePath, { outDir: 'magic' });
         const config = await findConfig(fixturePath);
@@ -247,13 +247,13 @@ describe('findConfig', () => {
 
   describe('alternate config formats', () => {
     it('should resolve the yml config from forge.config.yml specified in config.forge', async () => {
-      const fixturePath = path.resolve(__dirname, '../../../test/fixture/dummy_ts_conf');
+      const fixturePath = path.resolve(__dirname, '../../fixture/dummy_ts_conf');
       const conf = await findConfig(fixturePath);
       expect(conf.buildIdentifier).toEqual('yml');
     });
 
     it('should resolve the TS file exports of forge.config.ts if config.forge does not exist and the TS config exists', async () => {
-      const fixturePath = path.resolve(__dirname, '../../../test/fixture/dummy_default_ts_conf');
+      const fixturePath = path.resolve(__dirname, '../../fixture/dummy_default_ts_conf');
       const conf = await findConfig(fixturePath);
       expect(conf.buildIdentifier).toEqual('typescript');
     });
@@ -272,7 +272,7 @@ it('should resolve values fromBuildIdentifier', async () => {
       };
     };
   };
-  const conf = (await findConfig(path.resolve(__dirname, '../../../test/fixture/dummy_js_conf'))) as ResolveBIConfig;
+  const conf = (await findConfig(path.resolve(__dirname, '../../fixture/dummy_js_conf'))) as ResolveBIConfig;
   expect(conf.topLevelProp).toEqual('foo');
   expect(conf.sub).toEqual({
     prop: {
@@ -286,19 +286,19 @@ it('should resolve values fromBuildIdentifier', async () => {
 
 describe('forgeConfigIsValidFilePath', () => {
   it('succeeds for a file extension-less path', async () => {
-    const fixturePath = path.resolve(__dirname, '../../../test/fixture/dummy_js_conf/');
+    const fixturePath = path.resolve(__dirname, '../../fixture/dummy_js_conf/');
     await expect(forgeConfigIsValidFilePath(fixturePath, 'forge.different.config')).resolves.toEqual(true);
   });
 
   it('fails when a file is nonexistent', async () => {
-    const fixturePath = path.resolve(__dirname, '../../../test/fixture/dummy_js_conf/');
+    const fixturePath = path.resolve(__dirname, '../../fixture/dummy_js_conf/');
     await expect(forgeConfigIsValidFilePath(fixturePath, 'forge.nonexistent.config')).resolves.toEqual(false);
   });
 });
 
 describe('renderConfigTemplate', () => {
   it('should import a JS file when a string starts with "require:"', () => {
-    const dir = path.resolve(__dirname, '../../../test/fixture/dummy_js_conf');
+    const dir = path.resolve(__dirname, '../../fixture/dummy_js_conf');
     const config = {
       foo: 'require:foo',
     };
diff --git a/packages/api/core/spec/fast/util/import-search.spec.ts b/packages/api/core/spec/fast/util/import-search.spec.ts
index 5ecd29f3f9..4f3462dbe1 100644
--- a/packages/api/core/spec/fast/util/import-search.spec.ts
+++ b/packages/api/core/spec/fast/util/import-search.spec.ts
@@ -15,6 +15,6 @@ describe('import-search', () => {
   });
 
   it('should throw if file exists but fails to load', async () => {
-    await expect(importSearch(__dirname, ['../../../test/fixture/require-search/throw-error'])).rejects.toThrowError('test');
+    await expect(importSearch(__dirname, ['../../fixture/require-search/throw-error'])).rejects.toThrowError('test');
   });
 });
diff --git a/packages/api/core/spec/fast/util/resolve-dir.spec.ts b/packages/api/core/spec/fast/util/resolve-dir.spec.ts
index e0d59caf40..32c5236a7c 100644
--- a/packages/api/core/spec/fast/util/resolve-dir.spec.ts
+++ b/packages/api/core/spec/fast/util/resolve-dir.spec.ts
@@ -11,19 +11,17 @@ describe('resolve-dir', () => {
   });
 
   it('should return a directory if a forge config is found, but no package.json.forge.config', async () => {
-    const dir = path.resolve(__dirname, '../../../test/fixture/forge-config-no-package-json-config/');
+    const dir = path.resolve(__dirname, '../../fixture/forge-config-no-package-json-config/');
     const resolved = await resolveDir(dir);
     expect(resolved).not.toBeNull();
     expect(resolved).toEqual(dir);
   });
 
   it('should return a directory if it finds a node module', async () => {
-    const dir = path.resolve(__dirname, '../../../test/fixture/dummy_app/foo');
+    const dir = path.resolve(__dirname, '../../fixture/dummy_app/foo');
     const resolved = await resolveDir(dir);
     expect(resolved).not.toBeNull();
-    expect(await resolveDir(path.resolve(__dirname, '../../../test/fixture/dummy_app/foo'))).toEqual(
-      path.resolve(__dirname, '../../../test/fixture/dummy_app')
-    );
+    expect(await resolveDir(path.resolve(__dirname, '../../fixture/dummy_app/foo'))).toEqual(path.resolve(__dirname, '../../fixture/dummy_app'));
   });
 
   it('should return a directory if it finds a virtual config', async () => {
diff --git a/packages/api/core/test/fixture/app-with-custom-maker-config/out/test-linux-x64/.gitkeep b/packages/api/core/spec/fixture/app-with-custom-maker-config/out/test-linux-x64/.gitkeep
similarity index 100%
rename from packages/api/core/test/fixture/app-with-custom-maker-config/out/test-linux-x64/.gitkeep
rename to packages/api/core/spec/fixture/app-with-custom-maker-config/out/test-linux-x64/.gitkeep
diff --git a/packages/api/core/test/fixture/app-with-custom-maker-config/package.json b/packages/api/core/spec/fixture/app-with-custom-maker-config/package.json
similarity index 100%
rename from packages/api/core/test/fixture/app-with-custom-maker-config/package.json
rename to packages/api/core/spec/fixture/app-with-custom-maker-config/package.json
diff --git a/packages/api/core/test/fixture/app-with-maker-disable/out/test-linux-x64/.gitkeep b/packages/api/core/spec/fixture/app-with-maker-disable/out/test-linux-x64/.gitkeep
similarity index 100%
rename from packages/api/core/test/fixture/app-with-maker-disable/out/test-linux-x64/.gitkeep
rename to packages/api/core/spec/fixture/app-with-maker-disable/out/test-linux-x64/.gitkeep
diff --git a/packages/api/core/test/fixture/app-with-maker-disable/package.json b/packages/api/core/spec/fixture/app-with-maker-disable/package.json
similarity index 100%
rename from packages/api/core/test/fixture/app-with-maker-disable/package.json
rename to packages/api/core/spec/fixture/app-with-maker-disable/package.json
diff --git a/packages/api/core/test/fixture/app-with-scoped-name/out/@scope-package-linux-x64/.gitkeep b/packages/api/core/spec/fixture/app-with-scoped-name/out/@scope-package-linux-x64/.gitkeep
similarity index 100%
rename from packages/api/core/test/fixture/app-with-scoped-name/out/@scope-package-linux-x64/.gitkeep
rename to packages/api/core/spec/fixture/app-with-scoped-name/out/@scope-package-linux-x64/.gitkeep
diff --git a/packages/api/core/test/fixture/app-with-scoped-name/package.json b/packages/api/core/spec/fixture/app-with-scoped-name/package.json
similarity index 100%
rename from packages/api/core/test/fixture/app-with-scoped-name/package.json
rename to packages/api/core/spec/fixture/app-with-scoped-name/package.json
diff --git a/packages/api/core/test/fixture/async_forge_config/forge.config.js b/packages/api/core/spec/fixture/async_forge_config/forge.config.js
similarity index 100%
rename from packages/api/core/test/fixture/async_forge_config/forge.config.js
rename to packages/api/core/spec/fixture/async_forge_config/forge.config.js
diff --git a/packages/api/core/test/fixture/async_forge_config/package.json b/packages/api/core/spec/fixture/async_forge_config/package.json
similarity index 100%
rename from packages/api/core/test/fixture/async_forge_config/package.json
rename to packages/api/core/spec/fixture/async_forge_config/package.json
diff --git a/packages/api/core/test/fixture/bad_external_forge_config/bad.js b/packages/api/core/spec/fixture/bad_external_forge_config/bad.js
similarity index 100%
rename from packages/api/core/test/fixture/bad_external_forge_config/bad.js
rename to packages/api/core/spec/fixture/bad_external_forge_config/bad.js
diff --git a/packages/api/core/test/fixture/bad_external_forge_config/package.json b/packages/api/core/spec/fixture/bad_external_forge_config/package.json
similarity index 100%
rename from packages/api/core/test/fixture/bad_external_forge_config/package.json
rename to packages/api/core/spec/fixture/bad_external_forge_config/package.json
diff --git a/packages/api/core/test/fixture/bad_forge_config/package.json b/packages/api/core/spec/fixture/bad_forge_config/package.json
similarity index 100%
rename from packages/api/core/test/fixture/bad_forge_config/package.json
rename to packages/api/core/spec/fixture/bad_forge_config/package.json
diff --git a/packages/api/core/test/fixture/bogus-private-key.pvk b/packages/api/core/spec/fixture/bogus-private-key.pvk
similarity index 100%
rename from packages/api/core/test/fixture/bogus-private-key.pvk
rename to packages/api/core/spec/fixture/bogus-private-key.pvk
diff --git a/packages/api/core/test/fixture/custom-maker.ts b/packages/api/core/spec/fixture/custom-maker.ts
similarity index 100%
rename from packages/api/core/test/fixture/custom-maker.ts
rename to packages/api/core/spec/fixture/custom-maker.ts
diff --git a/packages/api/core/test/fixture/custom_init/index.js b/packages/api/core/spec/fixture/custom_init/index.js
similarity index 100%
rename from packages/api/core/test/fixture/custom_init/index.js
rename to packages/api/core/spec/fixture/custom_init/index.js
diff --git a/packages/api/core/test/fixture/custom_init/package-lock.json b/packages/api/core/spec/fixture/custom_init/package-lock.json
similarity index 100%
rename from packages/api/core/test/fixture/custom_init/package-lock.json
rename to packages/api/core/spec/fixture/custom_init/package-lock.json
diff --git a/packages/api/core/test/fixture/custom_init/package.json b/packages/api/core/spec/fixture/custom_init/package.json
similarity index 100%
rename from packages/api/core/test/fixture/custom_init/package.json
rename to packages/api/core/spec/fixture/custom_init/package.json
diff --git a/packages/api/core/test/fixture/custom_init/tmpl/_bar b/packages/api/core/spec/fixture/custom_init/tmpl/_bar
similarity index 100%
rename from packages/api/core/test/fixture/custom_init/tmpl/_bar
rename to packages/api/core/spec/fixture/custom_init/tmpl/_bar
diff --git a/packages/api/core/test/fixture/custom_init/tmpl/src/foo.js b/packages/api/core/spec/fixture/custom_init/tmpl/src/foo.js
similarity index 100%
rename from packages/api/core/test/fixture/custom_init/tmpl/src/foo.js
rename to packages/api/core/spec/fixture/custom_init/tmpl/src/foo.js
diff --git a/packages/api/core/test/fixture/dummy_app/foo/null b/packages/api/core/spec/fixture/dummy_app/foo/null
similarity index 100%
rename from packages/api/core/test/fixture/dummy_app/foo/null
rename to packages/api/core/spec/fixture/dummy_app/foo/null
diff --git a/packages/api/core/test/fixture/dummy_app/package.json b/packages/api/core/spec/fixture/dummy_app/package.json
similarity index 100%
rename from packages/api/core/test/fixture/dummy_app/package.json
rename to packages/api/core/spec/fixture/dummy_app/package.json
diff --git a/packages/api/core/test/fixture/dummy_default_esm_conf/forge.config.js b/packages/api/core/spec/fixture/dummy_default_esm_conf/forge.config.js
similarity index 100%
rename from packages/api/core/test/fixture/dummy_default_esm_conf/forge.config.js
rename to packages/api/core/spec/fixture/dummy_default_esm_conf/forge.config.js
diff --git a/packages/api/core/test/fixture/dummy_default_esm_conf/package.json b/packages/api/core/spec/fixture/dummy_default_esm_conf/package.json
similarity index 100%
rename from packages/api/core/test/fixture/dummy_default_esm_conf/package.json
rename to packages/api/core/spec/fixture/dummy_default_esm_conf/package.json
diff --git a/packages/api/core/test/fixture/dummy_default_js_conf/forge.config.js b/packages/api/core/spec/fixture/dummy_default_js_conf/forge.config.js
similarity index 100%
rename from packages/api/core/test/fixture/dummy_default_js_conf/forge.config.js
rename to packages/api/core/spec/fixture/dummy_default_js_conf/forge.config.js
diff --git a/packages/api/core/test/fixture/dummy_default_js_conf/package.json b/packages/api/core/spec/fixture/dummy_default_js_conf/package.json
similarity index 100%
rename from packages/api/core/test/fixture/dummy_default_js_conf/package.json
rename to packages/api/core/spec/fixture/dummy_default_js_conf/package.json
diff --git a/packages/api/core/test/fixture/dummy_default_ts_conf/forge.config.ts b/packages/api/core/spec/fixture/dummy_default_ts_conf/forge.config.ts
similarity index 100%
rename from packages/api/core/test/fixture/dummy_default_ts_conf/forge.config.ts
rename to packages/api/core/spec/fixture/dummy_default_ts_conf/forge.config.ts
diff --git a/packages/api/core/test/fixture/dummy_default_ts_conf/package.json b/packages/api/core/spec/fixture/dummy_default_ts_conf/package.json
similarity index 100%
rename from packages/api/core/test/fixture/dummy_default_ts_conf/package.json
rename to packages/api/core/spec/fixture/dummy_default_ts_conf/package.json
diff --git a/packages/api/core/test/fixture/dummy_js_conf/foo.js b/packages/api/core/spec/fixture/dummy_js_conf/foo.js
similarity index 100%
rename from packages/api/core/test/fixture/dummy_js_conf/foo.js
rename to packages/api/core/spec/fixture/dummy_js_conf/foo.js
diff --git a/packages/api/core/test/fixture/dummy_js_conf/forge.different.config.js b/packages/api/core/spec/fixture/dummy_js_conf/forge.different.config.js
similarity index 100%
rename from packages/api/core/test/fixture/dummy_js_conf/forge.different.config.js
rename to packages/api/core/spec/fixture/dummy_js_conf/forge.different.config.js
diff --git a/packages/api/core/test/fixture/dummy_js_conf/package.json b/packages/api/core/spec/fixture/dummy_js_conf/package.json
similarity index 100%
rename from packages/api/core/test/fixture/dummy_js_conf/package.json
rename to packages/api/core/spec/fixture/dummy_js_conf/package.json
diff --git a/packages/api/core/test/fixture/dummy_ts_conf/forge.config.yml b/packages/api/core/spec/fixture/dummy_ts_conf/forge.config.yml
similarity index 100%
rename from packages/api/core/test/fixture/dummy_ts_conf/forge.config.yml
rename to packages/api/core/spec/fixture/dummy_ts_conf/forge.config.yml
diff --git a/packages/api/core/test/fixture/dummy_ts_conf/package.json b/packages/api/core/spec/fixture/dummy_ts_conf/package.json
similarity index 100%
rename from packages/api/core/test/fixture/dummy_ts_conf/package.json
rename to packages/api/core/spec/fixture/dummy_ts_conf/package.json
diff --git a/packages/api/core/test/fixture/electron-executable/bad-export/node_modules/electron-prebuilt-compile/index.js b/packages/api/core/spec/fixture/electron-executable/bad-export/node_modules/electron-prebuilt-compile/index.js
similarity index 100%
rename from packages/api/core/test/fixture/electron-executable/bad-export/node_modules/electron-prebuilt-compile/index.js
rename to packages/api/core/spec/fixture/electron-executable/bad-export/node_modules/electron-prebuilt-compile/index.js
diff --git a/packages/api/core/test/fixture/electron-executable/bad-export/node_modules/electron-prebuilt-compile/package.json b/packages/api/core/spec/fixture/electron-executable/bad-export/node_modules/electron-prebuilt-compile/package.json
similarity index 100%
rename from packages/api/core/test/fixture/electron-executable/bad-export/node_modules/electron-prebuilt-compile/package.json
rename to packages/api/core/spec/fixture/electron-executable/bad-export/node_modules/electron-prebuilt-compile/package.json
diff --git a/packages/api/core/test/fixture/electron-executable/bad-export/node_modules/electron/index.js b/packages/api/core/spec/fixture/electron-executable/bad-export/node_modules/electron/index.js
similarity index 100%
rename from packages/api/core/test/fixture/electron-executable/bad-export/node_modules/electron/index.js
rename to packages/api/core/spec/fixture/electron-executable/bad-export/node_modules/electron/index.js
diff --git a/packages/api/core/test/fixture/electron-executable/bad-export/node_modules/electron/package.json b/packages/api/core/spec/fixture/electron-executable/bad-export/node_modules/electron/package.json
similarity index 100%
rename from packages/api/core/test/fixture/electron-executable/bad-export/node_modules/electron/package.json
rename to packages/api/core/spec/fixture/electron-executable/bad-export/node_modules/electron/package.json
diff --git a/packages/api/core/test/fixture/electron-executable/electron_app/node_modules/electron/index.js b/packages/api/core/spec/fixture/electron-executable/electron_app/node_modules/electron/index.js
similarity index 100%
rename from packages/api/core/test/fixture/electron-executable/electron_app/node_modules/electron/index.js
rename to packages/api/core/spec/fixture/electron-executable/electron_app/node_modules/electron/index.js
diff --git a/packages/api/core/test/fixture/electron-executable/electron_app/node_modules/electron/package.json b/packages/api/core/spec/fixture/electron-executable/electron_app/node_modules/electron/package.json
similarity index 100%
rename from packages/api/core/test/fixture/electron-executable/electron_app/node_modules/electron/package.json
rename to packages/api/core/spec/fixture/electron-executable/electron_app/node_modules/electron/package.json
diff --git a/packages/api/core/test/fixture/electron-executable/prebuilt-compile/node_modules/electron-prebuilt-compile/package.json b/packages/api/core/spec/fixture/electron-executable/prebuilt-compile/node_modules/electron-prebuilt-compile/package.json
similarity index 100%
rename from packages/api/core/test/fixture/electron-executable/prebuilt-compile/node_modules/electron-prebuilt-compile/package.json
rename to packages/api/core/spec/fixture/electron-executable/prebuilt-compile/node_modules/electron-prebuilt-compile/package.json
diff --git a/packages/api/core/test/fixture/forge-config-no-package-json-config/forge.config.js b/packages/api/core/spec/fixture/forge-config-no-package-json-config/forge.config.js
similarity index 100%
rename from packages/api/core/test/fixture/forge-config-no-package-json-config/forge.config.js
rename to packages/api/core/spec/fixture/forge-config-no-package-json-config/forge.config.js
diff --git a/packages/api/core/test/fixture/forge-config-no-package-json-config/package.json b/packages/api/core/spec/fixture/forge-config-no-package-json-config/package.json
similarity index 100%
rename from packages/api/core/test/fixture/forge-config-no-package-json-config/package.json
rename to packages/api/core/spec/fixture/forge-config-no-package-json-config/package.json
diff --git a/packages/api/core/test/fixture/maker-incompatible.ts b/packages/api/core/spec/fixture/maker-incompatible.ts
similarity index 100%
rename from packages/api/core/test/fixture/maker-incompatible.ts
rename to packages/api/core/spec/fixture/maker-incompatible.ts
diff --git a/packages/api/core/test/fixture/maker-name-wrong-type/package.json b/packages/api/core/spec/fixture/maker-name-wrong-type/package.json
similarity index 100%
rename from packages/api/core/test/fixture/maker-name-wrong-type/package.json
rename to packages/api/core/spec/fixture/maker-name-wrong-type/package.json
diff --git a/packages/api/core/test/fixture/maker-sans-name/package.json b/packages/api/core/spec/fixture/maker-sans-name/package.json
similarity index 100%
rename from packages/api/core/test/fixture/maker-sans-name/package.json
rename to packages/api/core/spec/fixture/maker-sans-name/package.json
diff --git a/packages/api/core/test/fixture/maker-unsupported.ts b/packages/api/core/spec/fixture/maker-unsupported.ts
similarity index 100%
rename from packages/api/core/test/fixture/maker-unsupported.ts
rename to packages/api/core/spec/fixture/maker-unsupported.ts
diff --git a/packages/api/core/test/fixture/maker-wrong-platform.ts b/packages/api/core/spec/fixture/maker-wrong-platform.ts
similarity index 100%
rename from packages/api/core/test/fixture/maker-wrong-platform.ts
rename to packages/api/core/spec/fixture/maker-wrong-platform.ts
diff --git a/packages/api/core/test/fixture/no_forge_config/package.json b/packages/api/core/spec/fixture/no_forge_config/package.json
similarity index 100%
rename from packages/api/core/test/fixture/no_forge_config/package.json
rename to packages/api/core/spec/fixture/no_forge_config/package.json
diff --git a/packages/api/core/test/fixture/npm-workspace/package-lock.json b/packages/api/core/spec/fixture/npm-workspace/package-lock.json
similarity index 100%
rename from packages/api/core/test/fixture/npm-workspace/package-lock.json
rename to packages/api/core/spec/fixture/npm-workspace/package-lock.json
diff --git a/packages/api/core/test/fixture/npm-workspace/package.json b/packages/api/core/spec/fixture/npm-workspace/package.json
similarity index 100%
rename from packages/api/core/test/fixture/npm-workspace/package.json
rename to packages/api/core/spec/fixture/npm-workspace/package.json
diff --git a/packages/api/core/test/fixture/npm-workspace/packages/subpackage/.gitkeep b/packages/api/core/spec/fixture/npm-workspace/packages/subpackage/.gitkeep
similarity index 100%
rename from packages/api/core/test/fixture/npm-workspace/packages/subpackage/.gitkeep
rename to packages/api/core/spec/fixture/npm-workspace/packages/subpackage/.gitkeep
diff --git a/packages/api/core/test/fixture/require-search/throw-error.js b/packages/api/core/spec/fixture/require-search/throw-error.js
similarity index 100%
rename from packages/api/core/test/fixture/require-search/throw-error.js
rename to packages/api/core/spec/fixture/require-search/throw-error.js
diff --git a/packages/api/core/test/fixture/template-nonmatching-forge-version/index.js b/packages/api/core/spec/fixture/template-nonmatching-forge-version/index.js
similarity index 100%
rename from packages/api/core/test/fixture/template-nonmatching-forge-version/index.js
rename to packages/api/core/spec/fixture/template-nonmatching-forge-version/index.js
diff --git a/packages/api/core/test/fixture/template-sans-forge-version/index.js b/packages/api/core/spec/fixture/template-sans-forge-version/index.js
similarity index 100%
rename from packages/api/core/test/fixture/template-sans-forge-version/index.js
rename to packages/api/core/spec/fixture/template-sans-forge-version/index.js
diff --git a/packages/api/core/test/fixture/template-sans-forge-version/package.json b/packages/api/core/spec/fixture/template-sans-forge-version/package.json
similarity index 100%
rename from packages/api/core/test/fixture/template-sans-forge-version/package.json
rename to packages/api/core/spec/fixture/template-sans-forge-version/package.json
diff --git a/packages/api/core/test/fixture/yarn-workspace/packages/electron-folder-in-node-modules/.gitkeep b/packages/api/core/spec/fixture/yarn-workspace/packages/electron-folder-in-node-modules/.gitkeep
similarity index 100%
rename from packages/api/core/test/fixture/yarn-workspace/packages/electron-folder-in-node-modules/.gitkeep
rename to packages/api/core/spec/fixture/yarn-workspace/packages/electron-folder-in-node-modules/.gitkeep
diff --git a/packages/api/core/test/fixture/yarn-workspace/packages/subpackage/.gitkeep b/packages/api/core/spec/fixture/yarn-workspace/packages/subpackage/.gitkeep
similarity index 100%
rename from packages/api/core/test/fixture/yarn-workspace/packages/subpackage/.gitkeep
rename to packages/api/core/spec/fixture/yarn-workspace/packages/subpackage/.gitkeep
diff --git a/packages/api/core/test/fixture/yarn-workspace/packages/with-node-modules/.gitkeep b/packages/api/core/spec/fixture/yarn-workspace/packages/with-node-modules/.gitkeep
similarity index 100%
rename from packages/api/core/test/fixture/yarn-workspace/packages/with-node-modules/.gitkeep
rename to packages/api/core/spec/fixture/yarn-workspace/packages/with-node-modules/.gitkeep
diff --git a/packages/api/core/test/slow/api_spec_slow.ts b/packages/api/core/spec/slow/api.slow.spec.ts
similarity index 53%
rename from packages/api/core/test/slow/api_spec_slow.ts
rename to packages/api/core/spec/slow/api.slow.spec.ts
index 54b9772cfb..1aba3a304f 100644
--- a/packages/api/core/test/slow/api_spec_slow.ts
+++ b/packages/api/core/spec/slow/api.slow.spec.ts
@@ -1,14 +1,14 @@
 import assert from 'node:assert';
 import { execSync } from 'node:child_process';
+import fs from 'node:fs';
 import path from 'node:path';
 
 import { yarnOrNpmSpawn } from '@electron-forge/core-utils';
 import { createDefaultCertificate } from '@electron-forge/maker-appx';
 import { ForgeConfig, IForgeResolvableMaker } from '@electron-forge/shared-types';
-import { ensureTestDirIsNonexistent, expectLintToPass, expectProjectPathExists } from '@electron-forge/test-utils';
-import { expect } from 'chai';
+import { ensureTestDirIsNonexistent, expectLintToPass } from '@electron-forge/test-utils';
 import { readMetadata } from 'electron-installer-common';
-import fs from 'fs-extra';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { api, InitOptions } from '../../src/api';
 import installDeps from '../../src/util/install-dependencies';
@@ -25,221 +25,210 @@ type PackageJSON = Record<string, unknown> & {
 async function updatePackageJSON(dir: string, packageJSONUpdater: (packageJSON: PackageJSON) => Promise<void>) {
   const packageJSON = await readRawPackageJson(dir);
   await packageJSONUpdater(packageJSON);
-  await fs.writeJson(path.resolve(dir, 'package.json'), packageJSON);
+  await fs.promises.writeFile(path.resolve(dir, 'package.json'), JSON.stringify(packageJSON), 'utf-8');
 }
 
-for (const nodeInstaller of ['npm', 'yarn']) {
-  process.env.NODE_INSTALLER = nodeInstaller;
-  describe(`electron-forge API (with installer=${nodeInstaller})`, () => {
-    let dir: string;
+describe.each([{ installer: 'npm' }, { installer: 'yarn' }])(`init (with $installer)`, ({ installer }) => {
+  let dir: string;
+
+  beforeAll(async () => {
+    await yarnOrNpmSpawn(['run', 'link:prepare']);
+    process.env.NODE_INSTALLER = installer;
+  });
 
-    before(async () => {
-      await yarnOrNpmSpawn(['link:prepare']);
+  const beforeInitTest = (params?: Partial<InitOptions>, beforeInit?: BeforeInitFunction) => {
+    beforeAll(async () => {
+      dir = await ensureTestDirIsNonexistent();
+      if (beforeInit) {
+        beforeInit();
+      }
+      await api.init({ ...params, dir });
     });
+  };
 
-    const beforeInitTest = (params?: Partial<InitOptions>, beforeInit?: BeforeInitFunction) => {
-      before(async () => {
-        dir = await ensureTestDirIsNonexistent();
-        if (beforeInit) {
-          beforeInit();
-        }
-        await api.init({ ...params, dir });
-      });
-    };
+  describe('init', () => {
+    beforeInitTest();
 
-    describe('init', () => {
-      beforeInitTest();
+    it('should fail in initializing an already initialized directory', async () => {
+      await expect(api.init({ dir })).rejects.toThrow(
+        `The specified path: "${dir}" is not empty.  Please ensure it is empty before initializing a new project`
+      );
+    });
 
-      it('should fail in initializing an already initialized directory', async () => {
-        await expect(api.init({ dir })).to.eventually.be.rejected;
-      });
-
-      it('should initialize an already initialized directory when forced to', async () => {
-        await api.init({
-          dir,
-          force: true,
-        });
+    it('should initialize an already initialized directory when forced to', async () => {
+      await api.init({
+        dir,
+        force: true,
       });
+    });
 
-      it('should create a new folder with a npm module inside', async () => {
-        expect(await fs.pathExists(dir), 'the target dir should have been created').to.equal(true);
-        await expectProjectPathExists(dir, 'package.json', 'file');
-      });
+    it('should create a new folder with a npm module inside', async () => {
+      expect(fs.existsSync(dir), 'the target dir should have been created').toEqual(true);
+      expect(fs.existsSync(path.join(dir, 'package.json'))).toEqual(true);
+      expect(fs.existsSync(path.join(dir, '.git'))).toEqual(true);
+      expect(fs.existsSync(path.resolve(dir, 'node_modules/electron')), 'electron should exist').toEqual(true);
+      expect(fs.existsSync(path.resolve(dir, 'node_modules/electron-squirrel-startup')), 'electron-squirrel-startup should exist').toEqual(true);
+      expect(fs.existsSync(path.resolve(dir, 'node_modules/@electron-forge/cli')), '@electron-forge/cli should exist').toEqual(true);
+      expect(fs.existsSync(path.join(dir, 'forge.config.js'))).toEqual(true);
+    });
 
-      it('should have initialized a git repository', async () => {
-        await expectProjectPathExists(dir, '.git', 'folder');
-      });
+    describe('lint', () => {
+      it('should initially pass the linting process', () => expectLintToPass(dir));
+    });
 
-      it('should have installed the initial node_modules', async () => {
-        await expectProjectPathExists(dir, 'node_modules', 'folder');
-        expect(await fs.pathExists(path.resolve(dir, 'node_modules/electron')), 'electron should exist').to.equal(true);
-        expect(await fs.pathExists(path.resolve(dir, 'node_modules/electron-squirrel-startup')), 'electron-squirrel-startup should exist').to.equal(true);
-        expect(await fs.pathExists(path.resolve(dir, 'node_modules/@electron-forge/cli')), '@electron-forge/cli should exist').to.equal(true);
-      });
+    afterAll(() => fs.promises.rm(dir, { recursive: true, force: true }));
+  });
 
-      it('should create a forge.config.js', async () => {
-        await expectProjectPathExists(dir, 'forge.config.js', 'file');
-      });
+  describe.skip('init with CI files enabled', () => {
+    beforeInitTest({ copyCIFiles: true });
+    it.todo('should copy over the CI config files correctly');
+  });
 
-      describe('lint', () => {
-        it('should initially pass the linting process', () => expectLintToPass(dir));
-      });
+  describe('init (with custom templater)', () => {
+    beforeInitTest({ template: path.resolve(__dirname, '../fixture/custom_init') });
 
-      after(() => fs.remove(dir));
+    it('should add custom dependencies', async () => {
+      // eslint-disable-next-line node/no-unsupported-features/es-syntax
+      const packageJSON = await import(path.resolve(dir, 'package.json'));
+      expect(packageJSON.dependencies).toHaveProperty('debug');
     });
 
-    describe.skip('init with CI files enabled', () => {
-      beforeInitTest({ copyCIFiles: true });
-
-      it('should copy over the CI config files correctly', async () => {
-        expect(await fs.pathExists(dir), 'the target dir should have been created').to.equal(true);
-        await expectProjectPathExists(dir, '.appveyor.yml', 'file');
-        await expectProjectPathExists(dir, '.travis.yml', 'file');
-      });
+    it('should add custom devDependencies', async () => {
+      // eslint-disable-next-line node/no-unsupported-features/es-syntax
+      const packageJSON = await import(path.resolve(dir, 'package.json'));
+      expect(packageJSON.devDependencies).toHaveProperty('lodash');
     });
 
-    describe('init (with custom templater)', () => {
-      beforeInitTest({ template: path.resolve(__dirname, '../fixture/custom_init') });
-
-      it('should add custom dependencies', async () => {
-        expect(Object.keys(require(path.resolve(dir, 'package.json')).dependencies)).to.contain('debug');
-      });
-
-      it('should add custom devDependencies', async () => {
-        expect(Object.keys(require(path.resolve(dir, 'package.json')).devDependencies)).to.contain('lodash');
-      });
+    it('should create dot files correctly', async () => {
+      expect(fs.existsSync(dir), 'the target dir should have been created').toEqual(true);
+      expect(fs.existsSync(path.join(dir, '.bar'))).toEqual(true);
+    });
 
-      it('should create dot files correctly', async () => {
-        expect(await fs.pathExists(dir), 'the target dir should have been created').to.equal(true);
-        await expectProjectPathExists(dir, '.bar', 'file');
-      });
+    it('should create deep files correctly', async () => {
+      expect(fs.existsSync(path.join(dir, 'src/foo.js'))).toBe(true);
+      expect(fs.existsSync(path.join(dir, 'src/index.html'))).toBe(true);
+    });
 
-      it('should create deep files correctly', async () => {
-        await expectProjectPathExists(dir, 'src/foo.js', 'file');
-        await expectProjectPathExists(dir, 'src/index.html', 'file');
-      });
+    describe('lint', () => {
+      it('should initially pass the linting process', () => expectLintToPass(dir));
+    });
 
-      describe('lint', () => {
-        it('should initially pass the linting process', () => expectLintToPass(dir));
+    afterAll(async () => {
+      await fs.promises.rm(dir, { recursive: true, force: true });
+      execSync('npm unlink -g', {
+        cwd: path.resolve(__dirname, '../fixture/custom_init'),
       });
+    });
+  });
 
-      after(async () => {
-        await fs.remove(dir);
-        execSync('npm unlink -g', {
-          cwd: path.resolve(__dirname, '../fixture/custom_init'),
-        });
-      });
+  describe('init (with a templater sans required Forge version)', () => {
+    beforeAll(async () => {
+      dir = await ensureTestDirIsNonexistent();
     });
 
-    describe('init (with a templater sans required Forge version)', () => {
-      before(async () => {
-        dir = await ensureTestDirIsNonexistent();
-      });
+    it('should fail in initializing', async () => {
+      await expect(
+        api.init({
+          dir,
+          template: path.resolve(__dirname, '../fixture/template-sans-forge-version'),
+        })
+      ).rejects.toThrow(/it does not specify its required Forge version\.$/);
+    });
 
-      it('should fail in initializing', async () => {
-        await expect(
-          api.init({
-            dir,
-            template: path.resolve(__dirname, '../fixture/template-sans-forge-version'),
-          })
-        ).to.eventually.be.rejectedWith(/it does not specify its required Forge version\.$/);
-      });
+    afterAll(async () => {
+      await fs.promises.rm(dir, { recursive: true, force: true });
+    });
+  });
 
-      after(async () => {
-        await fs.remove(dir);
-      });
+  describe('init (with a templater with a non-matching Forge version)', () => {
+    beforeAll(async () => {
+      dir = await ensureTestDirIsNonexistent();
     });
 
-    describe('init (with a templater with a non-matching Forge version)', () => {
-      before(async () => {
-        dir = await ensureTestDirIsNonexistent();
-      });
+    it('should fail in initializing', async () => {
+      await expect(
+        api.init({
+          dir,
+          template: path.resolve(__dirname, '../fixture/template-nonmatching-forge-version'),
+        })
+      ).rejects.toThrow(/is not compatible with this version of Electron Forge/);
+    });
 
-      it('should fail in initializing', async () => {
-        await expect(
-          api.init({
-            dir,
-            template: path.resolve(__dirname, '../fixture/template-nonmatching-forge-version'),
-          })
-        ).to.eventually.be.rejectedWith(/is not compatible with this version of Electron Forge/);
-      });
+    afterAll(async () => {
+      await fs.promises.rm(dir, { recursive: true, force: true });
+    });
+  });
 
-      after(async () => {
-        await fs.remove(dir);
-      });
+  describe('init (with a nonexistent templater)', () => {
+    beforeAll(async () => {
+      dir = await ensureTestDirIsNonexistent();
     });
 
-    describe('init (with a nonexistent templater)', () => {
-      before(async () => {
-        dir = await ensureTestDirIsNonexistent();
-      });
+    it('should fail in initializing', async () => {
+      await expect(
+        api.init({
+          dir,
+          template: 'does-not-exist',
+        })
+      ).rejects.toThrow('Failed to locate custom template');
+    });
 
-      it('should fail in initializing', async () => {
-        await expect(
-          api.init({
-            dir,
-            template: 'does-not-exist',
-          })
-        ).to.eventually.be.rejectedWith('Failed to locate custom template');
-      });
+    afterAll(async () => {
+      await fs.promises.rm(dir, { recursive: true, force: true });
+    });
+  });
 
-      after(async () => {
-        await fs.remove(dir);
+  describe('import', () => {
+    beforeAll(async () => {
+      dir = await ensureTestDirIsNonexistent();
+      await fs.promises.mkdir(dir);
+      execSync(`git clone https://github.com/electron/electron-quick-start.git . --quiet`, {
+        cwd: dir,
       });
     });
 
-    describe('import', () => {
-      before(async () => {
-        dir = await ensureTestDirIsNonexistent();
-        await fs.mkdir(dir);
-        execSync(`git clone https://github.com/electron/electron-quick-start.git . --quiet`, {
-          cwd: dir,
-        });
+    it('creates forge.config.js and is packageable', async () => {
+      await updatePackageJSON(dir, async (packageJSON) => {
+        packageJSON.name = 'Name';
+        packageJSON.productName = 'ProductName';
       });
 
-      it('creates forge.config.js and is packageable', async () => {
-        await updatePackageJSON(dir, async (packageJSON) => {
-          packageJSON.name = 'Name';
-          packageJSON.productName = 'ProductName';
-        });
-
-        await api.import({ dir });
+      await api.import({ dir });
 
-        expect(fs.existsSync(path.join(dir, 'forge.config.js'))).to.equal(true);
-
-        execSync(`${nodeInstaller} install`, {
-          cwd: dir,
-        });
+      expect(fs.existsSync(path.join(dir, 'forge.config.js'))).toEqual(true);
 
-        await api.package({ dir });
-
-        const outDirContents = fs.readdirSync(path.join(dir, 'out'));
-        expect(outDirContents).to.have.length(1);
-        expect(outDirContents[0]).to.equal(`ProductName-${process.platform}-${process.arch}`);
+      execSync(`${installer} install`, {
+        cwd: dir,
       });
 
-      after(async () => {
-        await fs.remove(dir);
-      });
+      await api.package({ dir });
+
+      const outDirContents = fs.readdirSync(path.join(dir, 'out'));
+      expect(outDirContents).toHaveLength(1);
+      expect(outDirContents[0]).toEqual(`ProductName-${process.platform}-${process.arch}`);
     });
 
-    after(async () => {
-      await yarnOrNpmSpawn(['link:remove']);
+    afterAll(async () => {
+      await fs.promises.rm(dir, { recursive: true, force: true });
     });
   });
-}
+
+  afterAll(async () => {
+    await yarnOrNpmSpawn(['run', 'link:remove']);
+  });
+});
 
 describe('Electron Forge API', () => {
   let dir: string;
 
-  before(async () => {
-    await yarnOrNpmSpawn(['link:prepare']);
+  beforeAll(async () => {
+    await yarnOrNpmSpawn(['run', 'link:prepare']);
   });
 
   describe('after init', () => {
     let devCert: string;
 
-    before(async () => {
+    beforeAll(async () => {
       dir = path.join(await ensureTestDirIsNonexistent(), 'electron-forge-test');
       await api.init({ dir });
 
@@ -255,7 +244,7 @@ describe('Electron Forge API', () => {
           },
         };
         if (process.platform === 'win32') {
-          await fs.copy(path.join(__dirname, '..', 'fixture', 'bogus-private-key.pvk'), path.join(dir, 'default.pvk'));
+          await fs.promises.rename(path.join(__dirname, '..', 'fixture', 'bogus-private-key.pvk'), path.join(dir, 'default.pvk'));
           devCert = await createDefaultCertificate('CN=Test Author', { certFilePath: dir });
         } else if (process.platform === 'linux') {
           packageJSON.config.forge.packagerConfig = {
@@ -273,7 +262,7 @@ describe('Electron Forge API', () => {
         assert(packageJSON.config.forge.packagerConfig);
         packageJSON.config.forge.packagerConfig.all = true;
       });
-      await expect(api.package({ dir })).to.eventually.be.rejectedWith(/packagerConfig\.all is not supported by Electron Forge/);
+      await expect(api.package({ dir })).rejects.toThrow(/packagerConfig\.all is not supported by Electron Forge/);
       await updatePackageJSON(dir, async (packageJSON) => {
         assert(packageJSON.config.forge.packagerConfig);
         delete packageJSON.config.forge.packagerConfig.all;
@@ -283,11 +272,11 @@ describe('Electron Forge API', () => {
     it('can package to outDir without errors', async () => {
       const outDir = `${dir}/foo`;
 
-      expect(await fs.pathExists(outDir)).to.equal(false);
+      expect(fs.existsSync(outDir)).toEqual(false);
 
       await api.package({ dir, outDir });
 
-      expect(await fs.pathExists(outDir)).to.equal(true);
+      expect(fs.existsSync(outDir)).toEqual(true);
     });
 
     it('can make from custom outDir without errors', async () => {
@@ -299,15 +288,15 @@ describe('Electron Forge API', () => {
       await api.make({ dir, skipPackage: true, outDir: `${dir}/foo` });
 
       // Cleanup here to ensure things dont break in the make tests
-      await fs.remove(path.resolve(dir, 'foo'));
-      await fs.remove(path.resolve(dir, 'out'));
+      await fs.promises.rm(path.resolve(dir, 'foo'), { recursive: true, force: true });
+      await fs.promises.rm(path.resolve(dir, 'out'), { recursive: true, force: true });
     });
 
     // FIXME(erickzhao): This test hangs on the electron-rebuild step
     // with Electron 19. It was tested to work on Electron 18.
     // see https://github.com/electron/forge/pull/2869
     describe.skip('with prebuilt native module deps installed', () => {
-      before(async () => {
+      beforeAll(async () => {
         await installDeps(dir, ['ref-napi']);
       });
 
@@ -315,8 +304,8 @@ describe('Electron Forge API', () => {
         await api.package({ dir });
       });
 
-      after(async () => {
-        await fs.remove(path.resolve(dir, 'node_modules/ref-napi'));
+      afterAll(async () => {
+        await fs.promises.rm(path.resolve(dir, 'node_modules/ref-napi'), { recursive: true, force: true });
         await updatePackageJSON(dir, async (packageJSON) => {
           delete packageJSON.dependencies['ref-napi'];
         });
@@ -338,12 +327,12 @@ describe('Electron Forge API', () => {
           src: path.resolve(dir, 'out', `Test-App-${process.platform}-${process.arch}`),
           logger: console.error,
         });
-        expect(cleanPackageJSON).to.not.have.nested.property('config.forge');
+        expect(cleanPackageJSON).not.toHaveProperty('config.forge');
       });
 
       it('should not affect the actual forge config', async () => {
         const normalPackageJSON = await readRawPackageJson(dir);
-        expect(normalPackageJSON).to.have.nested.property('config.forge');
+        expect(normalPackageJSON).toHaveProperty('config.forge');
       });
 
       if (process.platform !== 'win32') {
@@ -365,6 +354,7 @@ describe('Electron Forge API', () => {
         return allMakers
           .map((maker) => require.resolve(maker))
           .filter((makerPath) => {
+            // eslint-disable-next-line @typescript-eslint/no-require-imports
             const MakerClass = require(makerPath).default;
             const maker = new MakerClass();
             return maker.isSupportedOnCurrentPlatform() === good && maker.externalBinariesExist() === good;
@@ -396,7 +386,7 @@ describe('Electron Forge API', () => {
         ...options: any[]
       ) {
         describe(`make (with target=${target().name})`, async () => {
-          before(async () => {
+          beforeAll(async () => {
             await updatePackageJSON(dir, async (packageJSON) => {
               packageJSON.config.forge.makers = [target() as IForgeResolvableMaker];
             });
@@ -408,14 +398,14 @@ describe('Electron Forge API', () => {
                 const outputs = await api.make(optionsFetcher());
                 for (const outputResult of outputs) {
                   for (const output of outputResult.artifacts) {
-                    expect(await fs.pathExists(output)).to.equal(true);
-                    expect(output.startsWith(path.resolve(dir, 'out', 'make'))).to.equal(true);
+                    expect(fs.existsSync(output)).toEqual(true);
+                    expect(output.startsWith(path.resolve(dir, 'out', 'make'))).toEqual(true);
                   }
                 }
               });
             } else {
               it(`fails for config: ${JSON.stringify(optionsFetcher())}`, async () => {
-                await expect(api.make(optionsFetcher())).to.eventually.be.rejected;
+                await expect(api.make(optionsFetcher())).rejects.toThrow();
               });
             }
           }
@@ -433,7 +423,7 @@ describe('Electron Forge API', () => {
 
       describe('make', () => {
         it('throws an error when given an unrecognized platform', async () => {
-          await expect(api.make({ dir, platform: 'dos' })).to.eventually.be.rejectedWith(/invalid platform/);
+          await expect(api.make({ dir, platform: 'dos' })).rejects.toThrow(/invalid platform/);
         });
 
         it("throws an error when the specified maker doesn't support the current platform", async () => {
@@ -448,7 +438,7 @@ describe('Electron Forge API', () => {
               ],
               skipPackage: true,
             })
-          ).to.eventually.be.rejectedWith(/the maker declared that it cannot run/);
+          ).rejects.toThrow(/the maker declared that it cannot run/);
         });
 
         it("throws an error when the specified maker doesn't implement isSupportedOnCurrentPlatform()", async () => {
@@ -463,7 +453,7 @@ describe('Electron Forge API', () => {
               ],
               skipPackage: true,
             })
-          ).to.eventually.be.rejectedWith(/incompatible with this version/);
+          ).rejects.toThrow(/incompatible with this version/);
         });
 
         it('throws an error when no makers are configured for the given platform', async () => {
@@ -478,11 +468,10 @@ describe('Electron Forge API', () => {
               platform: 'linux',
               skipPackage: true,
             })
-          ).to.eventually.be.rejectedWith('Could not find any make targets configured for the "linux" platform.');
+          ).rejects.toThrow('Could not find any make targets configured for the "linux" platform.');
         });
 
-        it('can make for the MAS platform successfully', async () => {
-          if (process.platform !== 'darwin') return;
+        it.runIf(process.platform === 'darwin')('can make for the MAS platform successfully', async () => {
           await expect(
             api.make({
               dir,
@@ -490,15 +479,15 @@ describe('Electron Forge API', () => {
               overrideTargets: [require.resolve('@electron-forge/maker-zip'), require.resolve('@electron-forge/maker-dmg')],
               platform: 'mas',
             })
-          ).to.eventually.have.length(2);
+          ).resolves.toHaveLength(2);
         });
       });
     });
 
-    after(() => fs.remove(dir));
+    afterAll(() => fs.promises.rm(dir, { recursive: true, force: true }));
   });
 
-  after(async () => {
+  afterAll(async () => {
     await yarnOrNpmSpawn(['link:remove']);
   });
 });
diff --git a/packages/api/core/spec/slow/install-dependencies.slow.spec.ts b/packages/api/core/spec/slow/install-dependencies.slow.spec.ts
new file mode 100644
index 0000000000..91dbb03509
--- /dev/null
+++ b/packages/api/core/spec/slow/install-dependencies.slow.spec.ts
@@ -0,0 +1,27 @@
+import fs from 'node:fs/promises';
+import os from 'node:os';
+import path from 'node:path';
+
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
+
+import installDeps from '../../src/util/install-dependencies';
+
+describe.runIf(!(process.platform === 'linux' && process.env.CI))('install-dependencies', () => {
+  let installDir: string;
+
+  beforeAll(async () => {
+    const tmp = os.tmpdir();
+    const tmpdir = path.join(tmp, 'electron-forge-test-');
+    installDir = await fs.mkdtemp(tmpdir);
+  });
+
+  it('should install the latest minor version when the dependency has a caret', async () => {
+    await installDeps(installDir, ['debug@^2.0.0']);
+
+    // eslint-disable-next-line node/no-unsupported-features/es-syntax
+    const packageJSON = await import(path.resolve(installDir, 'node_modules', 'debug', 'package.json'));
+    expect(packageJSON.version).not.toEqual('2.0.0');
+  });
+
+  afterAll(async () => fs.rm(installDir, { recursive: true, force: true }));
+});
diff --git a/packages/api/core/test/slow/install-dependencies_spec_slow.ts b/packages/api/core/test/slow/install-dependencies_spec_slow.ts
deleted file mode 100644
index 805e47d64f..0000000000
--- a/packages/api/core/test/slow/install-dependencies_spec_slow.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import os from 'node:os';
-import path from 'node:path';
-
-import { expect } from 'chai';
-import fs from 'fs-extra';
-
-import installDeps from '../../src/util/install-dependencies';
-
-if (!(process.platform === 'linux' && process.env.CI)) {
-  describe('install-dependencies', () => {
-    const installDir = path.resolve(os.tmpdir(), 'electron-forge-test-install-dependencies');
-
-    before(async () => {
-      fs.ensureDir(installDir);
-    });
-
-    it('should install the latest minor version when the dependency has a caret', async () => {
-      await installDeps(installDir, ['debug@^2.0.0']);
-
-      const packageJSON = require(path.resolve(installDir, 'node_modules', 'debug', 'package.json'));
-      expect(packageJSON.version).to.not.equal('2.0.0');
-    });
-
-    after(async () => fs.remove(installDir));
-  });
-}
diff --git a/packages/maker/appx/package.json b/packages/maker/appx/package.json
index 0956a9a3fd..c1f2efc2c0 100644
--- a/packages/maker/appx/package.json
+++ b/packages/maker/appx/package.json
@@ -8,8 +8,6 @@
   "main": "dist/MakerAppX.js",
   "typings": "dist/MakerAppX.d.ts",
   "devDependencies": {
-    "chai": "^4.3.3",
-    "mocha": "^9.0.1",
     "vitest": "^2.1.6"
   },
   "engines": {
diff --git a/packages/maker/appx/spec/MakerAppX.spec.ts b/packages/maker/appx/spec/MakerAppX.spec.ts
index 7aba916ecb..62307b85ed 100644
--- a/packages/maker/appx/spec/MakerAppX.spec.ts
+++ b/packages/maker/appx/spec/MakerAppX.spec.ts
@@ -23,7 +23,7 @@ describe.runIf(process.platform === 'win32')('MakerAppX', function () {
     const def = process.platform === 'win32' ? it : it.skip;
 
     def('should create a .pfx file', async () => {
-      await fs.copyFile(path.join(__dirname, '../../../api/core/test/fixture', 'bogus-private-key.pvk'), path.join(tmpDir, 'dummy.pvk'));
+      await fs.copyFile(path.join(__dirname, '../../../api/core/spec/fixture', 'bogus-private-key.pvk'), path.join(tmpDir, 'dummy.pvk'));
       const outputCertPath = await createDefaultCertificate('CN=Test', {
         certFilePath: tmpDir,
         certFileName: 'dummy',
diff --git a/packages/maker/base/package.json b/packages/maker/base/package.json
index c084855290..6db52870b8 100644
--- a/packages/maker/base/package.json
+++ b/packages/maker/base/package.json
@@ -8,8 +8,6 @@
   "main": "dist/Maker.js",
   "typings": "dist/Maker.d.ts",
   "devDependencies": {
-    "chai": "^4.3.3",
-    "mocha": "^9.0.1",
     "vitest": "^2.1.6"
   },
   "engines": {
diff --git a/packages/maker/deb/package.json b/packages/maker/deb/package.json
index 43a0a751f8..933acc0828 100644
--- a/packages/maker/deb/package.json
+++ b/packages/maker/deb/package.json
@@ -9,9 +9,6 @@
   "typings": "dist/MakerDeb.d.ts",
   "devDependencies": {
     "@electron-forge/test-utils": "7.6.0",
-    "chai": "^4.3.3",
-    "chai-as-promised": "^7.0.0",
-    "mocha": "^9.0.1",
     "vitest": "^2.1.6"
   },
   "engines": {
diff --git a/packages/maker/dmg/package.json b/packages/maker/dmg/package.json
index b3560aad26..3e459ceeca 100644
--- a/packages/maker/dmg/package.json
+++ b/packages/maker/dmg/package.json
@@ -7,15 +7,8 @@
   "license": "MIT",
   "main": "dist/MakerDMG.js",
   "typings": "dist/MakerDMG.d.ts",
-  "scripts": {
-    "test": "yarn test:base test/**/*_spec.ts",
-    "test:base": "cross-env TS_NODE_FILES=1 mocha --config ../../../.mocharc.js"
-  },
   "devDependencies": {
     "@electron-forge/test-utils": "7.6.0",
-    "chai": "^4.3.3",
-    "chai-as-promised": "^7.0.0",
-    "mocha": "^9.0.1",
     "vitest": "^2.1.6"
   },
   "engines": {
diff --git a/packages/maker/flatpak/package.json b/packages/maker/flatpak/package.json
index d85069aca9..94e38102f0 100644
--- a/packages/maker/flatpak/package.json
+++ b/packages/maker/flatpak/package.json
@@ -7,15 +7,8 @@
   "license": "MIT",
   "main": "dist/MakerFlatpak.js",
   "typings": "dist/MakerFlatpak.d.ts",
-  "scripts": {
-    "test": "yarn test:base test/**/*_spec.ts",
-    "test:base": "cross-env TS_NODE_FILES=1 mocha --config ../../../.mocharc.js"
-  },
   "devDependencies": {
     "@electron-forge/test-utils": "7.6.0",
-    "chai": "^4.3.3",
-    "chai-as-promised": "^7.0.0",
-    "mocha": "^9.0.1",
     "vitest": "^2.1.6"
   },
   "engines": {
diff --git a/packages/maker/pkg/package.json b/packages/maker/pkg/package.json
index 2bbdbf8fba..0af7fd4e90 100644
--- a/packages/maker/pkg/package.json
+++ b/packages/maker/pkg/package.json
@@ -8,9 +8,6 @@
   "typings": "dist/MakerPKG.d.ts",
   "devDependencies": {
     "@electron-forge/test-utils": "7.6.0",
-    "chai": "^4.3.3",
-    "chai-as-promised": "^7.0.0",
-    "mocha": "^9.0.1",
     "vitest": "^2.1.6"
   },
   "engines": {
diff --git a/packages/maker/rpm/package.json b/packages/maker/rpm/package.json
index a5de122c30..82aa68a2e6 100644
--- a/packages/maker/rpm/package.json
+++ b/packages/maker/rpm/package.json
@@ -7,15 +7,8 @@
   "license": "MIT",
   "main": "dist/MakerRpm.js",
   "typings": "dist/MakerRpm.d.ts",
-  "scripts": {
-    "test": "yarn test:base test/**/*_spec.ts",
-    "test:base": "cross-env TS_NODE_FILES=1 mocha --config ../../../.mocharc.js"
-  },
   "devDependencies": {
     "@electron-forge/test-utils": "7.6.0",
-    "chai": "^4.3.3",
-    "chai-as-promised": "^7.0.0",
-    "mocha": "^9.0.1",
     "vitest": "^2.1.6"
   },
   "engines": {
diff --git a/packages/maker/snap/package.json b/packages/maker/snap/package.json
index 04ec77492d..a2213cad63 100644
--- a/packages/maker/snap/package.json
+++ b/packages/maker/snap/package.json
@@ -6,15 +6,8 @@
   "license": "MIT",
   "main": "dist/MakerSnap.js",
   "typings": "dist/MakerSnap.d.ts",
-  "scripts": {
-    "test": "yarn test:base test/**/*_spec.ts",
-    "test:base": "cross-env TS_NODE_FILES=1 mocha --config ../../../.mocharc.js"
-  },
   "devDependencies": {
     "@electron-forge/test-utils": "7.6.0",
-    "chai": "^4.3.3",
-    "chai-as-promised": "^7.0.0",
-    "mocha": "^9.0.1",
     "vitest": "^2.1.6"
   },
   "engines": {
diff --git a/packages/maker/squirrel/package.json b/packages/maker/squirrel/package.json
index 0d3d780eda..d93c7906d0 100644
--- a/packages/maker/squirrel/package.json
+++ b/packages/maker/squirrel/package.json
@@ -7,10 +7,6 @@
   "license": "MIT",
   "main": "dist/MakerSquirrel.js",
   "typings": "dist/MakerSquirrel.d.ts",
-  "devDependencies": {
-    "chai": "^4.3.3",
-    "mocha": "^9.0.1"
-  },
   "engines": {
     "node": ">= 16.4.0"
   },
diff --git a/packages/maker/wix/package.json b/packages/maker/wix/package.json
index 4e29ad4053..52dbb62721 100644
--- a/packages/maker/wix/package.json
+++ b/packages/maker/wix/package.json
@@ -8,8 +8,6 @@
   "main": "dist/MakerWix.js",
   "typings": "dist/MakerWix.d.ts",
   "devDependencies": {
-    "chai": "^4.3.3",
-    "mocha": "^9.0.1",
     "vitest": "^2.1.6"
   },
   "engines": {
diff --git a/packages/maker/zip/package.json b/packages/maker/zip/package.json
index 7b7bac89c9..1947cca9e2 100644
--- a/packages/maker/zip/package.json
+++ b/packages/maker/zip/package.json
@@ -9,8 +9,6 @@
   "typings": "dist/MakerZIP.d.ts",
   "devDependencies": {
     "@electron-forge/test-utils": "7.6.0",
-    "chai": "^4.3.3",
-    "mocha": "^9.0.1",
     "vitest": "^2.1.6"
   },
   "engines": {
diff --git a/packages/plugin/base/package.json b/packages/plugin/base/package.json
index 3724d16289..6ed92fe4a0 100644
--- a/packages/plugin/base/package.json
+++ b/packages/plugin/base/package.json
@@ -7,10 +7,6 @@
   "license": "MIT",
   "main": "dist/Plugin.js",
   "typings": "dist/Plugin.d.ts",
-  "devDependencies": {
-    "chai": "^4.3.3",
-    "mocha": "^9.0.1"
-  },
   "engines": {
     "node": ">= 16.4.0"
   },
diff --git a/packages/plugin/fuses/package.json b/packages/plugin/fuses/package.json
index ca74e0f99f..98e9f619b3 100644
--- a/packages/plugin/fuses/package.json
+++ b/packages/plugin/fuses/package.json
@@ -13,15 +13,9 @@
     "README.md"
   ],
   "typings": "dist/FusesPlugin.d.ts",
-  "scripts": {
-    "test": "xvfb-maybe mocha --config ../../../.mocharc.js test/**/*_spec*.ts"
-  },
   "devDependencies": {
     "@electron/fuses": ">=1.0.0",
     "@malept/cross-spawn-promise": "^2.0.0",
-    "chai": "^4.3.3",
-    "fs-extra": "^10.0.0",
-    "mocha": "^9.0.1",
     "xvfb-maybe": "^0.2.1"
   },
   "peerDependencies": {
diff --git a/packages/plugin/fuses/test/FusesPlugin_spec_slow.ts b/packages/plugin/fuses/spec/FusesPlugin.slow.spec.ts
similarity index 85%
rename from packages/plugin/fuses/test/FusesPlugin_spec_slow.ts
rename to packages/plugin/fuses/spec/FusesPlugin.slow.spec.ts
index 15622cecc9..ba33a49461 100644
--- a/packages/plugin/fuses/test/FusesPlugin_spec_slow.ts
+++ b/packages/plugin/fuses/spec/FusesPlugin.slow.spec.ts
@@ -2,8 +2,7 @@ import fs from 'node:fs';
 import path from 'node:path';
 
 import { CrossSpawnOptions, spawn } from '@malept/cross-spawn-promise';
-import { expect } from 'chai';
-import fsExtra from 'fs-extra';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { getElectronExecutablePath } from '../src/util/getElectronExecutablePath';
 
@@ -25,14 +24,14 @@ describe('FusesPlugin', () => {
 
   const outDir = path.join(appPath, 'out', 'fuses-test-app');
 
-  before(async () => {
+  beforeAll(async () => {
     delete process.env.TS_NODE_PROJECT;
     await fs.promises.copyFile(path.join(appPath, 'package.json.tmpl'), path.join(appPath, 'package.json'));
     await spawn('yarn', ['install'], spawnOptions);
   });
 
-  after(async () => {
-    await fsExtra.remove(path.resolve(outDir, '../'));
+  afterAll(async () => {
+    await fs.promises.rm(path.resolve(outDir, '../'), { recursive: true, force: true });
   });
 
   it('should flip Fuses', async () => {
@@ -59,6 +58,6 @@ describe('FusesPlugin', () => {
       })
     ).trim();
 
-    expect(output).to.equals('The Fuses plugin is working');
+    expect(output).toEqual('The Fuses plugin is working');
   });
 });
diff --git a/packages/plugin/fuses/test/fixture/app/forge.config.ts b/packages/plugin/fuses/spec/fixture/app/forge.config.ts
similarity index 100%
rename from packages/plugin/fuses/test/fixture/app/forge.config.ts
rename to packages/plugin/fuses/spec/fixture/app/forge.config.ts
diff --git a/packages/plugin/fuses/test/fixture/app/package.json.tmpl b/packages/plugin/fuses/spec/fixture/app/package.json
similarity index 100%
rename from packages/plugin/fuses/test/fixture/app/package.json.tmpl
rename to packages/plugin/fuses/spec/fixture/app/package.json
diff --git a/packages/plugin/fuses/spec/fixture/app/package.json.tmpl b/packages/plugin/fuses/spec/fixture/app/package.json.tmpl
new file mode 100644
index 0000000000..df090ecc4f
--- /dev/null
+++ b/packages/plugin/fuses/spec/fixture/app/package.json.tmpl
@@ -0,0 +1,18 @@
+{
+  "name": "fuses-test-app",
+  "version": "1.0.0",
+  "main": "./src/main.js",
+  "scripts": {
+    "package": "electron-forge package"
+  },
+  "dependencies": {
+    "@electron/fuses": "^1.6.1",
+    "fs-extra": "^10.0.0"
+  },
+  "devDependencies": {
+    "@electron-forge/cli": "6.4.0",
+    "@electron-forge/plugin-fuses": "6.4.0",
+    "@electron-forge/shared-types": "6.4.0",
+    "electron": "12.0.0"
+  }
+}
diff --git a/packages/plugin/fuses/test/fixture/app/src/main.js b/packages/plugin/fuses/spec/fixture/app/src/main.js
similarity index 100%
rename from packages/plugin/fuses/test/fixture/app/src/main.js
rename to packages/plugin/fuses/spec/fixture/app/src/main.js
diff --git a/packages/plugin/local-electron/package.json b/packages/plugin/local-electron/package.json
index 5dbc9cd404..c18a06fd85 100644
--- a/packages/plugin/local-electron/package.json
+++ b/packages/plugin/local-electron/package.json
@@ -16,8 +16,6 @@
     "fs-extra": "^10.0.0"
   },
   "devDependencies": {
-    "chai": "^4.3.3",
-    "mocha": "^9.0.1",
     "vitest": "^2.1.6"
   },
   "publishConfig": {
diff --git a/packages/plugin/vite/package.json b/packages/plugin/vite/package.json
index 01c2244184..1b02bd13c7 100644
--- a/packages/plugin/vite/package.json
+++ b/packages/plugin/vite/package.json
@@ -11,9 +11,6 @@
   "license": "MIT",
   "main": "dist/VitePlugin.js",
   "typings": "dist/VitePlugin.d.ts",
-  "scripts": {
-    "test": "xvfb-maybe mocha --config ../../../.mocharc.js test/**/*_spec.ts test/*_spec.ts"
-  },
   "dependencies": {
     "@electron-forge/core-utils": "7.6.0",
     "@electron-forge/plugin-base": "7.6.0",
@@ -28,8 +25,6 @@
     "@electron/packager": "^18.3.5",
     "@malept/cross-spawn-promise": "^2.0.0",
     "@types/node": "^18.0.3",
-    "chai": "^4.3.3",
-    "mocha": "^9.0.1",
     "vite": "^5.0.12",
     "vitest": "^2.1.6",
     "which": "^2.0.2",
diff --git a/packages/plugin/webpack/package.json b/packages/plugin/webpack/package.json
index 4a0d62093c..e84346d316 100644
--- a/packages/plugin/webpack/package.json
+++ b/packages/plugin/webpack/package.json
@@ -7,15 +7,10 @@
   "license": "MIT",
   "main": "dist/WebpackPlugin.js",
   "typings": "dist/WebpackPlugin.d.ts",
-  "scripts": {
-    "test": "xvfb-maybe mocha --config ../../../.mocharc.js test/**/*_spec.ts test/*_spec.ts"
-  },
   "devDependencies": {
     "@electron/packager": "^18.3.5",
     "@malept/cross-spawn-promise": "^2.0.0",
     "@types/node": "^18.0.3",
-    "chai": "^4.3.3",
-    "mocha": "^9.0.1",
     "vitest": "^2.1.6",
     "which": "^2.0.2",
     "xvfb-maybe": "^0.2.1"
diff --git a/packages/plugin/webpack/spec/AssetRelocatorPatch.spec.ts b/packages/plugin/webpack/spec/AssetRelocatorPatch.spec.ts
index 3f1e7c7ddd..bcb12cd413 100644
--- a/packages/plugin/webpack/spec/AssetRelocatorPatch.spec.ts
+++ b/packages/plugin/webpack/spec/AssetRelocatorPatch.spec.ts
@@ -179,7 +179,7 @@ describe('AssetRelocatorPatch', () => {
       });
     });
 
-    it('runs the app with the native module', { timeout: 15000 }, async () => {
+    it('runs the app with the native module', { timeout: 15_000 }, async () => {
       servers.push(createSimpleDevServer(rendererOut));
 
       const output = await runApp();
diff --git a/packages/publisher/base-static/package.json b/packages/publisher/base-static/package.json
index b2ba7982fc..be623af375 100644
--- a/packages/publisher/base-static/package.json
+++ b/packages/publisher/base-static/package.json
@@ -7,17 +7,11 @@
   "license": "MIT",
   "main": "dist/PublisherStatic.js",
   "typings": "dist/PublisherStatic.d.ts",
-  "scripts": {
-    "test": "yarn test:base test/**/*_spec.ts",
-    "test:base": "cross-env TS_NODE_FILES=1 mocha --config ../../../.mocharc.js"
-  },
   "dependencies": {
     "@electron-forge/publisher-base": "7.6.0",
     "@electron-forge/shared-types": "7.6.0"
   },
   "devDependencies": {
-    "chai": "^4.3.3",
-    "mocha": "^9.0.1",
     "vitest": "^2.1.6"
   },
   "engines": {
diff --git a/packages/publisher/base/package.json b/packages/publisher/base/package.json
index 4dfa2aeb32..990c9afe59 100644
--- a/packages/publisher/base/package.json
+++ b/packages/publisher/base/package.json
@@ -7,16 +7,10 @@
   "license": "MIT",
   "main": "dist/Publisher.js",
   "typings": "dist/Publisher.d.ts",
-  "scripts": {
-    "test": "yarn test:base test/**/*_spec.ts",
-    "test:base": "cross-env TS_NODE_FILES=1 mocha --config ../../../.mocharc.js"
-  },
   "dependencies": {
     "@electron-forge/shared-types": "7.6.0"
   },
   "devDependencies": {
-    "chai": "^4.3.3",
-    "mocha": "^9.0.1",
     "vitest": "^2.1.6"
   },
   "engines": {
diff --git a/packages/publisher/bitbucket/package.json b/packages/publisher/bitbucket/package.json
index ad69a9b2dd..a224daaea2 100644
--- a/packages/publisher/bitbucket/package.json
+++ b/packages/publisher/bitbucket/package.json
@@ -7,10 +7,6 @@
   "license": "MIT",
   "main": "dist/PublisherBitbucket.js",
   "typings": "dist/PublisherBitbucket.d.ts",
-  "devDependencies": {
-    "chai": "^4.3.3",
-    "mocha": "^9.0.1"
-  },
   "engines": {
     "node": ">= 16.4.0"
   },
diff --git a/packages/publisher/electron-release-server/package.json b/packages/publisher/electron-release-server/package.json
index 7d5dc2230c..c01c45f435 100644
--- a/packages/publisher/electron-release-server/package.json
+++ b/packages/publisher/electron-release-server/package.json
@@ -8,8 +8,6 @@
   "main": "dist/PublisherERS.js",
   "typings": "dist/PublisherERS.d.ts",
   "devDependencies": {
-    "chai": "^4.3.3",
-    "mocha": "^9.0.1",
     "msw": "^2.7.0",
     "vitest": "^2.1.6"
   },
diff --git a/packages/publisher/gcs/package.json b/packages/publisher/gcs/package.json
index 05349bb7fb..ee883a8bfe 100644
--- a/packages/publisher/gcs/package.json
+++ b/packages/publisher/gcs/package.json
@@ -7,10 +7,6 @@
   "license": "MIT",
   "main": "dist/PublisherGCS.js",
   "typings": "dist/PublisherGCS.d.ts",
-  "devDependencies": {
-    "chai": "^4.3.3",
-    "mocha": "^9.0.1"
-  },
   "engines": {
     "node": ">= 16.4.0"
   },
diff --git a/packages/publisher/github/package.json b/packages/publisher/github/package.json
index 3f6f3398a8..d801c824cb 100644
--- a/packages/publisher/github/package.json
+++ b/packages/publisher/github/package.json
@@ -7,13 +7,7 @@
   "license": "MIT",
   "main": "dist/PublisherGithub.js",
   "typings": "dist/PublisherGithub.d.ts",
-  "scripts": {
-    "test": "yarn test:base test/**/*_spec.ts",
-    "test:base": "cross-env TS_NODE_FILES=1 mocha --config ../../../.mocharc.js"
-  },
   "devDependencies": {
-    "chai": "^4.3.3",
-    "mocha": "^9.0.1",
     "vitest": "^2.1.6"
   },
   "engines": {
diff --git a/packages/publisher/nucleus/package.json b/packages/publisher/nucleus/package.json
index 96487f1656..8b693fc8cb 100644
--- a/packages/publisher/nucleus/package.json
+++ b/packages/publisher/nucleus/package.json
@@ -7,10 +7,6 @@
   "license": "MIT",
   "main": "dist/PublisherNucleus.js",
   "typings": "dist/PublisherNucleus.d.ts",
-  "devDependencies": {
-    "chai": "^4.3.3",
-    "mocha": "^9.0.1"
-  },
   "engines": {
     "node": ">= 16.4.0"
   },
diff --git a/packages/publisher/s3/package.json b/packages/publisher/s3/package.json
index 08b04bd2ee..648fa8e342 100644
--- a/packages/publisher/s3/package.json
+++ b/packages/publisher/s3/package.json
@@ -7,10 +7,6 @@
   "license": "MIT",
   "main": "dist/PublisherS3.js",
   "typings": "dist/PublisherS3.d.ts",
-  "devDependencies": {
-    "chai": "^4.3.3",
-    "mocha": "^9.0.1"
-  },
   "engines": {
     "node": ">= 16.4.0"
   },
diff --git a/packages/publisher/snapcraft/package.json b/packages/publisher/snapcraft/package.json
index a6a253a866..b00044d3c6 100644
--- a/packages/publisher/snapcraft/package.json
+++ b/packages/publisher/snapcraft/package.json
@@ -7,10 +7,6 @@
   "license": "MIT",
   "main": "dist/PublisherSnapcraft.js",
   "typings": "dist/PublisherSnapcraft.d.ts",
-  "devDependencies": {
-    "chai": "^4.3.3",
-    "mocha": "^9.0.1"
-  },
   "engines": {
     "node": ">= 16.4.0"
   },
diff --git a/packages/template/base/package.json b/packages/template/base/package.json
index ef461622c8..a4922a4515 100644
--- a/packages/template/base/package.json
+++ b/packages/template/base/package.json
@@ -7,9 +7,6 @@
   "license": "MIT",
   "main": "dist/BaseTemplate.js",
   "typings": "dist/BaseTemplate.d.ts",
-  "scripts": {
-    "test": "mocha --config ../../../.mocharc.js test/**/*_spec.ts"
-  },
   "engines": {
     "node": ">= 16.4.0"
   },
@@ -22,8 +19,6 @@
   },
   "devDependencies": {
     "@electron-forge/test-utils": "7.6.0",
-    "chai": "^4.3.3",
-    "mocha": "^9.0.1",
     "vitest": "^2.1.6"
   },
   "publishConfig": {
diff --git a/packages/template/vite-typescript/package.json b/packages/template/vite-typescript/package.json
index 190507822f..8c2b8bc972 100644
--- a/packages/template/vite-typescript/package.json
+++ b/packages/template/vite-typescript/package.json
@@ -11,9 +11,6 @@
   "license": "MIT",
   "main": "dist/ViteTypeScriptTemplate.js",
   "typings": "dist/ViteTypeScriptTemplate.d.ts",
-  "scripts": {
-    "test": "mocha --config ../../../.mocharc.js test/**/*_spec_slow.ts"
-  },
   "engines": {
     "node": ">= 16.4.0"
   },
@@ -25,8 +22,8 @@
   "devDependencies": {
     "@electron-forge/core-utils": "7.6.0",
     "@electron-forge/test-utils": "7.6.0",
-    "chai": "^4.3.3",
-    "fast-glob": "^3.2.7"
+    "fast-glob": "^3.2.7",
+    "vitest": "^2.1.6"
   },
   "files": [
     "dist",
diff --git a/packages/template/vite-typescript/test/ViteTypeScriptTemplate_spec_slow.ts b/packages/template/vite-typescript/spec/ViteTypeScriptTemplate.slow.spec.ts
similarity index 69%
rename from packages/template/vite-typescript/test/ViteTypeScriptTemplate_spec_slow.ts
rename to packages/template/vite-typescript/spec/ViteTypeScriptTemplate.slow.spec.ts
index 7c4aea4e19..a0a6b6107c 100644
--- a/packages/template/vite-typescript/test/ViteTypeScriptTemplate_spec_slow.ts
+++ b/packages/template/vite-typescript/spec/ViteTypeScriptTemplate.slow.spec.ts
@@ -1,28 +1,28 @@
+import fs from 'node:fs';
 import os from 'node:os';
 import path from 'node:path';
 
 import { yarnOrNpmSpawn } from '@electron-forge/core-utils';
-import * as testUtils from '@electron-forge/test-utils';
-import { expect } from 'chai';
+import testUtils from '@electron-forge/test-utils';
 import glob from 'fast-glob';
-import fs from 'fs-extra';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
-import { api } from '../../../api/core';
+import { api } from '../../../api/core/dist/api';
 import { initLink } from '../../../api/core/src/api/init-scripts/init-link';
 
 describe('ViteTypeScriptTemplate', () => {
   let dir: string;
 
-  before(async () => {
-    await yarnOrNpmSpawn(['link:prepare']);
+  beforeAll(async () => {
+    await yarnOrNpmSpawn(['run', 'link:prepare']);
     dir = await testUtils.ensureTestDirIsNonexistent();
   });
 
-  after(async () => {
-    await yarnOrNpmSpawn(['link:remove']);
+  afterAll(async () => {
+    await yarnOrNpmSpawn(['run', 'link:remove']);
     if (os.platform() !== 'win32') {
-      // Windows platform `fs.remove(dir)` logic useing npm `npm run test:clear`.
-      await fs.remove(dir);
+      // Windows platform `fs.remove(dir)` logic using `npm run test:clear`.
+      await fs.promises.rm(dir, { force: true, recursive: true });
     }
   });
 
@@ -30,12 +30,12 @@ describe('ViteTypeScriptTemplate', () => {
     it('should succeed in initializing the typescript template', async () => {
       await api.init({
         dir,
-        template: path.resolve(__dirname, '..', 'src', 'ViteTypeScriptTemplate'),
+        template: path.resolve(__dirname, '..'),
         interactive: false,
       });
     });
 
-    const expectedFiles = [
+    it.each([
       'package.json',
       'tsconfig.json',
       '.eslintrc.json',
@@ -47,16 +47,13 @@ describe('ViteTypeScriptTemplate', () => {
       path.join('src', 'main.ts'),
       path.join('src', 'renderer.ts'),
       path.join('src', 'preload.ts'),
-    ];
-    for (const filename of expectedFiles) {
-      it(`${filename} should exist`, async () => {
-        await testUtils.expectProjectPathExists(dir, filename, 'file');
-      });
-    }
+    ])(`%s should exist`, async (filename) => {
+      expect(fs.existsSync(path.join(dir, filename))).toBe(true);
+    });
 
     it('should ensure js source files from base template are removed', async () => {
       const jsFiles = await glob(path.join(dir, 'src', '**', '*.js'));
-      expect(jsFiles.length).to.equal(0, `The following unexpected js files were found in the src/ folder: ${JSON.stringify(jsFiles)}`);
+      expect(jsFiles.length).toEqual(0);
     });
   });
 
@@ -70,19 +67,19 @@ describe('ViteTypeScriptTemplate', () => {
   describe('package', () => {
     let cwd: string;
 
-    before(async () => {
+    beforeAll(async () => {
       delete process.env.TS_NODE_PROJECT;
       // Vite resolves plugins via cwd
       cwd = process.cwd();
       process.chdir(dir);
       // We need the version of vite to match exactly during development due to a quirk in
       // typescript type-resolution.  In prod no one has to worry about things like this
-      const pj = await fs.readJson(path.resolve(dir, 'package.json'));
+      const pj = JSON.parse(await fs.promises.readFile(path.resolve(dir, 'package.json'), 'utf-8'));
       pj.resolutions = {
         // eslint-disable-next-line @typescript-eslint/no-require-imports
         vite: `${require('../../../../node_modules/vite/package.json').version}`,
       };
-      await fs.writeJson(path.resolve(dir, 'package.json'), pj);
+      await fs.promises.writeFile(path.resolve(dir, 'package.json'), JSON.stringify(pj));
       await yarnOrNpmSpawn(['install'], {
         cwd: dir,
       });
@@ -93,7 +90,7 @@ describe('ViteTypeScriptTemplate', () => {
       await initLink(dir);
     });
 
-    after(() => {
+    afterAll(() => {
       process.chdir(cwd);
     });
 
diff --git a/packages/template/vite/package.json b/packages/template/vite/package.json
index 26cf292109..ffbbb703b5 100644
--- a/packages/template/vite/package.json
+++ b/packages/template/vite/package.json
@@ -11,9 +11,6 @@
   "license": "MIT",
   "main": "dist/ViteTemplate.js",
   "typings": "dist/ViteTemplate.d.ts",
-  "scripts": {
-    "test": "mocha --config ../../../.mocharc.js test/**/*_spec.ts"
-  },
   "engines": {
     "node": ">= 16.4.0"
   },
@@ -24,7 +21,6 @@
   },
   "devDependencies": {
     "@electron-forge/test-utils": "7.6.0",
-    "chai": "^4.3.3",
     "listr2": "^7.0.2",
     "vitest": "^2.1.6"
   },
diff --git a/packages/template/vite/spec/ViteTemplate.spec.ts b/packages/template/vite/spec/ViteTemplate.spec.ts
index 0b867d0b8f..0417137ef3 100644
--- a/packages/template/vite/spec/ViteTemplate.spec.ts
+++ b/packages/template/vite/spec/ViteTemplate.spec.ts
@@ -1,7 +1,7 @@
-import fs from 'node:fs/promises';
+import fs from 'node:fs';
 import path from 'node:path';
 
-import * as testUtils from '@electron-forge/test-utils';
+import testUtils from '@electron-forge/test-utils';
 import { Listr } from 'listr2';
 import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
@@ -15,7 +15,7 @@ describe('ViteTemplate', () => {
   });
 
   afterAll(async () => {
-    await fs.rm(dir, { recursive: true });
+    await fs.promises.rm(dir, { recursive: true });
   });
 
   it('should succeed in initializing the vite template', async () => {
@@ -40,23 +40,24 @@ describe('ViteTemplate', () => {
       path.join('src', 'preload.js'),
     ];
     it.each(expectedFiles)(`%s should exist`, async (filename) => {
-      await testUtils.expectProjectPathExists(dir, filename, 'file');
+      const file = path.join(dir, filename);
+      expect(fs.existsSync(file)).toBe(true);
     });
   });
 
   it('should move and rewrite the main process file', async () => {
-    await testUtils.expectProjectPathNotExists(dir, path.join('src', 'index.js'), 'file');
-    await testUtils.expectProjectPathExists(dir, path.join('src', 'main.js'), 'file');
-    const mainFile = (await fs.readFile(path.join(dir, 'src', 'main.js'))).toString();
+    expect(fs.existsSync(path.join(dir, 'src', 'index.js'))).toBe(false);
+    expect(fs.existsSync(path.join(dir, 'src', 'main.js'))).toBe(true);
+    const mainFile = (await fs.promises.readFile(path.join(dir, 'src', 'main.js'))).toString();
     expect(mainFile).toMatch(/MAIN_WINDOW_VITE_DEV_SERVER_URL/);
     expect(mainFile).toMatch(/\.\.\/renderer\/\${MAIN_WINDOW_VITE_NAME}\/index\.html/);
   });
 
   it('should remove the stylesheet link from the HTML file', async () => {
-    expect((await fs.readFile(path.join(dir, 'index.html'))).toString()).not.toMatch(/link rel="stylesheet"/);
+    expect((await fs.promises.readFile(path.join(dir, 'index.html'))).toString()).not.toMatch(/link rel="stylesheet"/);
   });
 
   it('should inject script into the HTML file', async () => {
-    expect((await fs.readFile(path.join(dir, 'index.html'))).toString()).toMatch(/src="\/src\/renderer\.js"/);
+    expect((await fs.promises.readFile(path.join(dir, 'index.html'))).toString()).toMatch(/src="\/src\/renderer\.js"/);
   });
 });
diff --git a/packages/template/webpack-typescript/package.json b/packages/template/webpack-typescript/package.json
index b03f1696d0..8ecc4cb15a 100644
--- a/packages/template/webpack-typescript/package.json
+++ b/packages/template/webpack-typescript/package.json
@@ -7,9 +7,6 @@
   "license": "MIT",
   "main": "dist/WebpackTypeScriptTemplate.js",
   "typings": "dist/WebpackTypeScriptTemplate.d.ts",
-  "scripts": {
-    "test": "mocha --config ../../../.mocharc.js test/**/*_spec_slow.ts"
-  },
   "engines": {
     "node": ">= 16.4.0"
   },
@@ -26,10 +23,10 @@
     "@electron-forge/maker-zip": "7.6.0",
     "@electron-forge/plugin-webpack": "7.6.0",
     "@electron-forge/test-utils": "7.6.0",
-    "chai": "^4.3.3",
     "fast-glob": "^3.2.7",
     "fork-ts-checker-webpack-plugin": "^7.2.13",
-    "listr2": "^7.0.2"
+    "listr2": "^7.0.2",
+    "vitest": "^2.1.6"
   },
   "files": [
     "dist",
diff --git a/packages/template/webpack-typescript/test/WebpackTypeScript_spec_slow.ts b/packages/template/webpack-typescript/spec/WebpackTypeScript.slow.spec.ts
similarity index 70%
rename from packages/template/webpack-typescript/test/WebpackTypeScript_spec_slow.ts
rename to packages/template/webpack-typescript/spec/WebpackTypeScript.slow.spec.ts
index 9632653328..72e22e6b19 100644
--- a/packages/template/webpack-typescript/test/WebpackTypeScript_spec_slow.ts
+++ b/packages/template/webpack-typescript/spec/WebpackTypeScript.slow.spec.ts
@@ -1,32 +1,32 @@
+import fs from 'node:fs';
 import path from 'node:path';
 
 import { yarnOrNpmSpawn } from '@electron-forge/core-utils';
-import * as testUtils from '@electron-forge/test-utils';
-import { expect } from 'chai';
+import testUtils from '@electron-forge/test-utils';
 import glob from 'fast-glob';
-import fs from 'fs-extra';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
-import { api } from '../../../api/core';
+import { api } from '../../../api/core/dist/api';
 import { initLink } from '../../../api/core/src/api/init-scripts/init-link';
 
 describe('WebpackTypeScriptTemplate', () => {
   let dir: string;
 
-  before(async () => {
-    await yarnOrNpmSpawn(['link:prepare']);
+  beforeAll(async () => {
+    await yarnOrNpmSpawn(['run', 'link:prepare']);
     dir = await testUtils.ensureTestDirIsNonexistent();
   });
 
   it('should succeed in initializing the typescript template', async () => {
     await api.init({
       dir,
-      template: path.resolve(__dirname, '..', 'src', 'WebpackTypeScriptTemplate'),
+      template: path.join(__dirname, '..'),
       interactive: false,
     });
   });
 
-  context('template files are copied to project', () => {
-    const expectedFiles = [
+  describe('template files are copied to project', () => {
+    it.each([
       'tsconfig.json',
       '.eslintrc.json',
       'forge.config.ts',
@@ -37,17 +37,14 @@ describe('WebpackTypeScriptTemplate', () => {
       path.join('src', 'index.ts'),
       path.join('src', 'renderer.ts'),
       path.join('src', 'preload.ts'),
-    ];
-    for (const filename of expectedFiles) {
-      it(`${filename} should exist`, async () => {
-        await testUtils.expectProjectPathExists(dir, filename, 'file');
-      });
-    }
+    ])(`%s should exist`, async (filename) => {
+      expect(fs.existsSync(path.join(dir, filename))).toBe(true);
+    });
   });
 
   it('should ensure js source files from base template are removed', async () => {
     const jsFiles = await glob(path.join(dir, 'src', '**', '*.js'));
-    expect(jsFiles.length).to.equal(0, `The following unexpected js files were found in the src/ folder: ${JSON.stringify(jsFiles)}`);
+    expect(jsFiles.length).toEqual(0);
   });
 
   describe('lint', () => {
@@ -60,19 +57,19 @@ describe('WebpackTypeScriptTemplate', () => {
   describe('package', () => {
     let cwd: string;
 
-    before(async () => {
+    beforeAll(async () => {
       delete process.env.TS_NODE_PROJECT;
       // Webpack resolves plugins via cwd
       cwd = process.cwd();
       process.chdir(dir);
       // We need the version of webpack to match exactly during development due to a quirk in
       // typescript type-resolution.  In prod no one has to worry about things like this
-      const pj = await fs.readJson(path.resolve(dir, 'package.json'));
+      const pj = JSON.parse(await fs.promises.readFile(path.resolve(dir, 'package.json'), 'utf-8'));
       pj.resolutions = {
         // eslint-disable-next-line @typescript-eslint/no-require-imports
         webpack: `${require('../../../../node_modules/webpack/package.json').version}`,
       };
-      await fs.writeJson(path.resolve(dir, 'package.json'), pj);
+      await fs.promises.writeFile(path.resolve(dir, 'package.json'), JSON.stringify(pj));
       await yarnOrNpmSpawn(['install'], {
         cwd: dir,
       });
@@ -83,7 +80,7 @@ describe('WebpackTypeScriptTemplate', () => {
       await initLink(dir);
     });
 
-    after(() => {
+    afterAll(() => {
       process.chdir(cwd);
     });
 
@@ -95,8 +92,8 @@ describe('WebpackTypeScriptTemplate', () => {
     });
   });
 
-  after(async () => {
+  afterAll(async () => {
     await yarnOrNpmSpawn(['link:remove']);
-    await fs.remove(dir);
+    await fs.promises.rm(dir, { recursive: true, force: true });
   });
 });
diff --git a/packages/template/webpack/package.json b/packages/template/webpack/package.json
index 4d6efd275a..435b949b4c 100644
--- a/packages/template/webpack/package.json
+++ b/packages/template/webpack/package.json
@@ -7,9 +7,6 @@
   "license": "MIT",
   "main": "dist/WebpackTemplate.js",
   "typings": "dist/WebpackTemplate.d.ts",
-  "scripts": {
-    "test": "mocha --config ../../../.mocharc.js test/**/*_spec.ts"
-  },
   "engines": {
     "node": ">= 16.4.0"
   },
@@ -20,7 +17,6 @@
   },
   "devDependencies": {
     "@electron-forge/test-utils": "7.6.0",
-    "chai": "^4.3.3",
     "listr2": "^7.0.2",
     "vitest": "^2.1.6"
   },
diff --git a/packages/template/webpack/spec/WebpackTemplate.spec.ts b/packages/template/webpack/spec/WebpackTemplate.spec.ts
index 37a6eceb48..a977683208 100644
--- a/packages/template/webpack/spec/WebpackTemplate.spec.ts
+++ b/packages/template/webpack/spec/WebpackTemplate.spec.ts
@@ -1,7 +1,7 @@
-import fs from 'node:fs/promises';
+import fs from 'node:fs';
 import path from 'node:path';
 
-import * as testUtils from '@electron-forge/test-utils';
+import testUtils from '@electron-forge/test-utils';
 import { Listr } from 'listr2';
 import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
@@ -15,7 +15,7 @@ describe('WebpackTemplate', () => {
   });
 
   afterAll(async () => {
-    await fs.rm(dir, { recursive: true });
+    await fs.promises.rm(dir, { recursive: true });
   });
 
   it('should succeed in initializing the webpack template', async () => {
@@ -38,19 +38,20 @@ describe('WebpackTemplate', () => {
       path.join('src', 'preload.js'),
     ];
     it.each(expectedFiles)(`%s should exist`, async (filename) => {
-      await testUtils.expectProjectPathExists(dir, filename, 'file');
+      const file = path.join(dir, filename);
+      expect(fs.existsSync(file)).toBe(true);
     });
   });
 
   it('should move and rewrite the main process file', async () => {
-    await testUtils.expectProjectPathNotExists(dir, path.join('src', 'index.js'), 'file');
-    await testUtils.expectProjectPathExists(dir, path.join('src', 'main.js'), 'file');
-    const mainFile = (await fs.readFile(path.join(dir, 'src', 'main.js'))).toString();
+    expect(fs.existsSync(path.join(dir, 'src', 'index.js'))).toBe(false);
+    expect(fs.existsSync(path.join(dir, 'src', 'main.js'))).toBe(true);
+    const mainFile = (await fs.promises.readFile(path.join(dir, 'src', 'main.js'))).toString();
     expect(mainFile).toMatch(/MAIN_WINDOW_WEBPACK_ENTRY/);
     expect(mainFile).toMatch(/MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY/);
   });
 
   it('should remove the stylesheet link from the HTML file', async () => {
-    expect((await fs.readFile(path.join(dir, 'src', 'index.html'))).toString()).not.toMatch(/link rel="stylesheet"/);
+    expect((await fs.promises.readFile(path.join(dir, 'src', 'index.html'))).toString()).not.toMatch(/link rel="stylesheet"/);
   });
 });
diff --git a/packages/utils/core-utils/package.json b/packages/utils/core-utils/package.json
index f38b17931a..82ab581b1e 100644
--- a/packages/utils/core-utils/package.json
+++ b/packages/utils/core-utils/package.json
@@ -23,7 +23,6 @@
     "node": ">= 16.4.0"
   },
   "devDependencies": {
-    "chai": "^4.3.3",
     "vitest": "^2.1.6"
   },
   "files": [
diff --git a/packages/utils/core-utils/spec/electron-version.spec.ts b/packages/utils/core-utils/spec/electron-version.spec.ts
index 0626cdba83..1d3ac4bef6 100644
--- a/packages/utils/core-utils/spec/electron-version.spec.ts
+++ b/packages/utils/core-utils/spec/electron-version.spec.ts
@@ -7,7 +7,7 @@ import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 import { devDeps, exactDevDeps } from '../../../api/core/src/api/init-scripts/init-npm';
 import { getElectronModulePath, getElectronVersion, updateElectronDependency } from '../src/electron-version';
 
-const fixturePath = path.resolve(__dirname, '..', '..', '..', 'api', 'core', 'test', 'fixture');
+const fixturePath = path.resolve(__dirname, 'fixture');
 
 describe('updateElectronDependency', () => {
   it('adds an Electron dep if one does not already exist', () => {
diff --git a/packages/api/core/test/fixture/yarn-workspace/yarn.lock b/packages/utils/core-utils/spec/fixture/dummy_app/foo/null
similarity index 100%
rename from packages/api/core/test/fixture/yarn-workspace/yarn.lock
rename to packages/utils/core-utils/spec/fixture/dummy_app/foo/null
diff --git a/packages/utils/core-utils/spec/fixture/dummy_app/package.json b/packages/utils/core-utils/spec/fixture/dummy_app/package.json
new file mode 100644
index 0000000000..b85dbb4343
--- /dev/null
+++ b/packages/utils/core-utils/spec/fixture/dummy_app/package.json
@@ -0,0 +1,24 @@
+{
+  "name": "",
+  "productName": "",
+  "version": "1.0.0",
+  "description": "",
+  "main": "src/index.js",
+  "scripts": {
+    "start": "electron-forge start"
+  },
+  "keywords": [],
+  "author": "",
+  "license": "MIT",
+  "config": {
+    "forge": {
+      "packagerConfig": {
+        "baz": {}
+      },
+      "s3": {}
+    }
+  },
+  "devDependencies": {
+    "electron": "1000.100.10"
+  }
+}
diff --git a/packages/api/core/test/fixture/non-exact/node_modules/electron/package.json b/packages/utils/core-utils/spec/fixture/non-exact/node_modules/electron/package.json
similarity index 100%
rename from packages/api/core/test/fixture/non-exact/node_modules/electron/package.json
rename to packages/utils/core-utils/spec/fixture/non-exact/node_modules/electron/package.json
diff --git a/packages/api/core/test/fixture/npm-workspace/node_modules/electron/package.json b/packages/utils/core-utils/spec/fixture/npm-workspace/node_modules/electron/package.json
similarity index 100%
rename from packages/api/core/test/fixture/npm-workspace/node_modules/electron/package.json
rename to packages/utils/core-utils/spec/fixture/npm-workspace/node_modules/electron/package.json
diff --git a/packages/utils/core-utils/spec/fixture/npm-workspace/package-lock.json b/packages/utils/core-utils/spec/fixture/npm-workspace/package-lock.json
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/packages/utils/core-utils/spec/fixture/npm-workspace/package.json b/packages/utils/core-utils/spec/fixture/npm-workspace/package.json
new file mode 100644
index 0000000000..4fbfcc3533
--- /dev/null
+++ b/packages/utils/core-utils/spec/fixture/npm-workspace/package.json
@@ -0,0 +1,5 @@
+{
+  "workspaces": [
+    "packages/subpackage"
+  ]
+}
diff --git a/packages/utils/core-utils/spec/fixture/npm-workspace/packages/subpackage/.gitkeep b/packages/utils/core-utils/spec/fixture/npm-workspace/packages/subpackage/.gitkeep
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/packages/api/core/test/fixture/yarn-workspace/node_modules/electron/package.json b/packages/utils/core-utils/spec/fixture/yarn-workspace/node_modules/electron/package.json
similarity index 100%
rename from packages/api/core/test/fixture/yarn-workspace/node_modules/electron/package.json
rename to packages/utils/core-utils/spec/fixture/yarn-workspace/node_modules/electron/package.json
diff --git a/packages/utils/core-utils/spec/fixture/yarn-workspace/packages/electron-folder-in-node-modules/.gitkeep b/packages/utils/core-utils/spec/fixture/yarn-workspace/packages/electron-folder-in-node-modules/.gitkeep
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/packages/api/core/test/fixture/yarn-workspace/packages/electron-folder-in-node-modules/node_modules/electron/package.json b/packages/utils/core-utils/spec/fixture/yarn-workspace/packages/electron-folder-in-node-modules/node_modules/electron/package.json
similarity index 100%
rename from packages/api/core/test/fixture/yarn-workspace/packages/electron-folder-in-node-modules/node_modules/electron/package.json
rename to packages/utils/core-utils/spec/fixture/yarn-workspace/packages/electron-folder-in-node-modules/node_modules/electron/package.json
diff --git a/packages/utils/core-utils/spec/fixture/yarn-workspace/packages/subpackage/.gitkeep b/packages/utils/core-utils/spec/fixture/yarn-workspace/packages/subpackage/.gitkeep
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/packages/utils/core-utils/spec/fixture/yarn-workspace/packages/with-node-modules/.gitkeep b/packages/utils/core-utils/spec/fixture/yarn-workspace/packages/with-node-modules/.gitkeep
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/packages/api/core/test/fixture/yarn-workspace/packages/with-node-modules/node_modules/some-other-module-second/package.json b/packages/utils/core-utils/spec/fixture/yarn-workspace/packages/with-node-modules/node_modules/some-other-module-second/package.json
similarity index 100%
rename from packages/api/core/test/fixture/yarn-workspace/packages/with-node-modules/node_modules/some-other-module-second/package.json
rename to packages/utils/core-utils/spec/fixture/yarn-workspace/packages/with-node-modules/node_modules/some-other-module-second/package.json
diff --git a/packages/api/core/test/fixture/yarn-workspace/packages/with-node-modules/node_modules/some-other-module/package.json b/packages/utils/core-utils/spec/fixture/yarn-workspace/packages/with-node-modules/node_modules/some-other-module/package.json
similarity index 100%
rename from packages/api/core/test/fixture/yarn-workspace/packages/with-node-modules/node_modules/some-other-module/package.json
rename to packages/utils/core-utils/spec/fixture/yarn-workspace/packages/with-node-modules/node_modules/some-other-module/package.json
diff --git a/packages/utils/core-utils/spec/fixture/yarn-workspace/yarn.lock b/packages/utils/core-utils/spec/fixture/yarn-workspace/yarn.lock
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/packages/utils/test-utils/package.json b/packages/utils/test-utils/package.json
index aa8421f8fb..204319b696 100644
--- a/packages/utils/test-utils/package.json
+++ b/packages/utils/test-utils/package.json
@@ -8,9 +8,7 @@
   "main": "dist/index.js",
   "typings": "dist/index.d.ts",
   "dependencies": {
-    "@malept/cross-spawn-promise": "^2.0.0",
-    "chai": "^4.3.3",
-    "fs-extra": "^10.0.0"
+    "@malept/cross-spawn-promise": "^2.0.0"
   },
   "engines": {
     "node": ">= 16.4.0"
diff --git a/packages/utils/test-utils/src/index.ts b/packages/utils/test-utils/src/index.ts
index a677acbac5..1def97e60b 100644
--- a/packages/utils/test-utils/src/index.ts
+++ b/packages/utils/test-utils/src/index.ts
@@ -1,9 +1,8 @@
+import fs from 'node:fs';
 import os from 'node:os';
 import path from 'node:path';
 
 import { ExitError, spawn } from '@malept/cross-spawn-promise';
-import { expect } from 'chai';
-import fs from 'fs-extra';
 
 async function runNPM(dir: string, ...args: string[]) {
   await spawn('npm', args, { cwd: dir });
@@ -23,7 +22,7 @@ let dirID = Date.now();
 export async function ensureTestDirIsNonexistent(): Promise<string> {
   const dir = path.resolve(os.tmpdir(), `electron-forge-test-${dirID}`);
   dirID += 1;
-  await fs.remove(dir);
+  await fs.promises.rm(dir, { recursive: true, force: true });
 
   return dir;
 }
@@ -40,14 +39,6 @@ export async function expectLintToPass(dir: string): Promise<void> {
   }
 }
 
-export async function expectProjectPathExists(dir: string, subPath: string, pathType: string, exists = true): Promise<void> {
-  expect(await fs.pathExists(path.resolve(dir, subPath)), `the ${subPath} ${pathType} should exist`).to.equal(exists);
-}
-
-export async function expectProjectPathNotExists(dir: string, subPath: string, pathType: string): Promise<void> {
-  await expectProjectPathExists(dir, subPath, pathType, false);
-}
-
 /**
  * Helper function to mock CommonJS `require` calls with Vitest.
  *
@@ -55,6 +46,7 @@ export async function expectProjectPathNotExists(dir: string, subPath: string, p
  * @param mockedUri - mocked module URI
  * @param stub - stub function to assign to mock
  */
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
 export async function mockRequire(mockedUri: string, stub: any) {
   // eslint-disable-next-line node/no-unsupported-features/es-syntax
   const { Module } = await import('module');
diff --git a/tools/test-clear.ts b/tools/test-clear.ts
index 25751276ad..9e2aaf5267 100644
--- a/tools/test-clear.ts
+++ b/tools/test-clear.ts
@@ -13,7 +13,7 @@ import fs from 'fs-extra';
     for (const dir of dirs) {
       console.log('Clean up the test dir:', dir);
 
-      // Remove the tmp files generated by run `template/**/*_spec_slow.ts`,
+      // Remove the tmp files generated by slow tests
       // see here 👉 https://github.com/electron/forge/pull/3468#issuecomment-1920805240
       await fs.remove(dir);
     }
diff --git a/tools/test-setup.ts b/tools/test-setup.ts
deleted file mode 100644
index 931bcc9d91..0000000000
--- a/tools/test-setup.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-import * as chai from 'chai';
-import chaiAsPromised from 'chai-as-promised';
-
-chai.use(chaiAsPromised);
diff --git a/tools/update-dependencies.js b/tools/update-dependencies.js
index 3d74e40e94..1b807729f7 100755
--- a/tools/update-dependencies.js
+++ b/tools/update-dependencies.js
@@ -9,7 +9,6 @@ const DO_NOT_UPGRADE = [
   '@typescript-eslint/eslint-plugin', // special case
   'chalk', // Requires ESM
   'commander', // TODO: convert to yargs
-  'eslint-plugin-mocha', // Requires Node 14
   'find-up', // Requires ESM
   'log-symbols', // Requires ESM
   'node-fetch', // Requires ESM
diff --git a/vitest.config.mts b/vitest.config.mts
index 3b6b274440..23fc70f4ae 100644
--- a/vitest.config.mts
+++ b/vitest.config.mts
@@ -4,5 +4,7 @@ import { defineConfig } from 'vitest/config';
 export default defineConfig({
   test: {
     clearMocks: true,
+    exclude: ['**/.links/**', '**/node_modules/**'],
+    fileParallelism: false,
   },
 });
diff --git a/vitest.workspace.mts b/vitest.workspace.mts
index 700ed1bb0e..11b25a5b03 100644
--- a/vitest.workspace.mts
+++ b/vitest.workspace.mts
@@ -1,3 +1,21 @@
 import { defineWorkspace } from 'vitest/config';
 
-export default defineWorkspace(['./vitest.config.mts']);
+export default defineWorkspace([
+  {
+    extends: './vitest.config.mts',
+    test: {
+      include: ['**/spec/**/*.spec.ts'],
+      exclude: ['**/spec/**/*.slow.spec.ts'],
+      name: 'fast',
+    },
+  },
+  {
+    extends: './vitest.config.mts',
+    test: {
+      include: ['**/spec/**/*.slow.spec.ts'],
+      name: 'slow',
+      hookTimeout: 120000,
+      testTimeout: 120000,
+    },
+  },
+]);
diff --git a/yarn.lock b/yarn.lock
index 97a9f4f839..0892d27524 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2915,18 +2915,6 @@
   resolved "https://registry.yarnpkg.com/@types/caseless/-/caseless-0.12.4.tgz#1326429a519cc077028150343fd502b04686bd6f"
   integrity sha512-2in/lrHRNmDvHPgyormtEralhPcN3An1gLjJzj2Bw145VBxkQ75JEXW6CTdMAwShiHQcYsl2d10IjQSdJSJz4g==
 
-"@types/chai-as-promised@^7.1.2":
-  version "7.1.5"
-  resolved "https://registry.yarnpkg.com/@types/chai-as-promised/-/chai-as-promised-7.1.5.tgz#6e016811f6c7a64f2eed823191c3a6955094e255"
-  integrity sha512-jStwss93SITGBwt/niYrkf2C+/1KTeZCZl1LaeezTlqppAKeoQC7jxyqYuP72sxBGKCIbw7oHgbYssIRzT5FCQ==
-  dependencies:
-    "@types/chai" "*"
-
-"@types/chai@*", "@types/chai@^4.2.12":
-  version "4.3.0"
-  resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.0.tgz#23509ebc1fa32f1b4d50d6a66c4032d5b8eaabdc"
-  integrity sha512-/ceqdqeRraGolFTcfoXNiqjyQhZzbINDngeoAq9GoHa8PPK1yNzTaxWjA6BFWp5Ua9JpXEMSS4s5i9tS0hOJtw==
-
 "@types/connect-history-api-fallback@^1.3.5":
   version "1.3.5"
   resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz#d1f7a8a09d0ed5a57aee5ae9c18ab9b803205dae"
@@ -3124,11 +3112,6 @@
   resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.2.tgz#ee771e2ba4b3dc5b372935d549fd9617bf345b8c"
   integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==
 
-"@types/mocha@^9.0.0":
-  version "9.1.0"
-  resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.0.tgz#baf17ab2cca3fcce2d322ebc30454bff487efad5"
-  integrity sha512-QCWHkbMv4Y5U9oW10Uxbr45qMMSzl4OzijsozynUAgx3kEHUdXB00udx2dWDQ7f2TU2a2uuiFaRZjCe3unPpeg==
-
 "@types/ms@*":
   version "0.7.31"
   resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197"
@@ -3392,11 +3375,6 @@
     "@typescript-eslint/types" "8.18.1"
     eslint-visitor-keys "^4.2.0"
 
-"@ungap/promise-all-settled@1.1.2":
-  version "1.1.2"
-  resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44"
-  integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==
-
 "@ungap/structured-clone@^1.2.0":
   version "1.2.1"
   resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.1.tgz#28fa185f67daaf7b7a1a8c1d445132c5d979f8bd"
@@ -3755,11 +3733,6 @@ ajv@^8.0.0, ajv@^8.0.1, ajv@^8.8.0:
     require-from-string "^2.0.2"
     uri-js "^4.2.2"
 
-ansi-colors@4.1.1:
-  version "4.1.1"
-  resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
-  integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==
-
 ansi-colors@^4.1.1:
   version "4.1.3"
   resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b"
@@ -4084,11 +4057,6 @@ asar@^3.0.0:
   optionalDependencies:
     "@types/glob" "^7.1.1"
 
-assertion-error@^1.1.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b"
-  integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==
-
 assertion-error@^2.0.1:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-2.0.1.tgz#f641a196b335690b1070bf00b6e7593fec190bf7"
@@ -4290,11 +4258,6 @@ braces@^3.0.3, braces@~3.0.2:
   dependencies:
     fill-range "^7.1.1"
 
-browser-stdout@1.3.1:
-  version "1.3.1"
-  resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60"
-  integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==
-
 browserslist@^4.21.10:
   version "4.23.3"
   resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.3.tgz#debb029d3c93ebc97ffbc8d9cbb03403e227c800"
@@ -4500,36 +4463,11 @@ camelcase@^5.3.1:
   resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
   integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
 
-camelcase@^6.0.0:
-  version "6.3.0"
-  resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a"
-  integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
-
 caniuse-lite@^1.0.30001646:
   version "1.0.30001662"
   resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001662.tgz#3574b22dfec54a3f3b6787331da1040fe8e763ec"
   integrity sha512-sgMUVwLmGseH8ZIrm1d51UbrhqMCH3jvS7gF/M6byuHOnKyLOBL7W8yz5V02OHwgLGA36o/AFhWzzh4uc5aqTA==
 
-chai-as-promised@^7.0.0:
-  version "7.1.1"
-  resolved "https://registry.yarnpkg.com/chai-as-promised/-/chai-as-promised-7.1.1.tgz#08645d825deb8696ee61725dbf590c012eb00ca0"
-  integrity sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==
-  dependencies:
-    check-error "^1.0.2"
-
-chai@^4.3.3:
-  version "4.3.6"
-  resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.6.tgz#ffe4ba2d9fa9d6680cc0b370adae709ec9011e9c"
-  integrity sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==
-  dependencies:
-    assertion-error "^1.1.0"
-    check-error "^1.0.2"
-    deep-eql "^3.0.1"
-    get-func-name "^2.0.0"
-    loupe "^2.3.1"
-    pathval "^1.1.1"
-    type-detect "^4.0.5"
-
 chai@^5.1.2:
   version "5.1.2"
   resolved "https://registry.yarnpkg.com/chai/-/chai-5.1.2.tgz#3afbc340b994ae3610ca519a6c70ace77ad4378d"
@@ -4576,16 +4514,6 @@ chardet@^0.7.0:
   resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
   integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
 
-charenc@0.0.2:
-  version "0.0.2"
-  resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
-  integrity sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==
-
-check-error@^1.0.2:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82"
-  integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=
-
 check-error@^2.1.1:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/check-error/-/check-error-2.1.1.tgz#87eb876ae71ee388fa0471fe423f494be1d96ccc"
@@ -4616,21 +4544,6 @@ cheerio@^1.0.0-rc.9:
     parse5 "^7.0.0"
     parse5-htmlparser2-tree-adapter "^7.0.0"
 
-chokidar@3.5.3:
-  version "3.5.3"
-  resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
-  integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
-  dependencies:
-    anymatch "~3.1.2"
-    braces "~3.0.2"
-    glob-parent "~5.1.2"
-    is-binary-path "~2.1.0"
-    is-glob "~4.0.1"
-    normalize-path "~3.0.0"
-    readdirp "~3.6.0"
-  optionalDependencies:
-    fsevents "~2.3.2"
-
 chokidar@^3.5.3:
   version "3.6.0"
   resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b"
@@ -5144,11 +5057,6 @@ cross-zip@^4.0.0:
   resolved "https://registry.yarnpkg.com/cross-zip/-/cross-zip-4.0.0.tgz#c29bfb2c001659a6d480ae9596f3bee83b48a230"
   integrity sha512-MEzGfZo0rqE10O/B+AEcCSJLZsrWuRUvmqJTqHNqBtALhaJc3E3ixLGLJNTRzEA2K34wbmOHC4fwYs9sVsdcCA==
 
-crypt@0.0.2:
-  version "0.0.2"
-  resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
-  integrity sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==
-
 css-select@^4.1.3:
   version "4.3.0"
   resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.3.0.tgz#db7129b2846662fd8628cfc496abb2b59e41529b"
@@ -5240,13 +5148,6 @@ debug@4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, d
   dependencies:
     ms "2.1.2"
 
-debug@4.3.3:
-  version "4.3.3"
-  resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664"
-  integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==
-  dependencies:
-    ms "2.1.2"
-
 debug@^3.2.7:
   version "3.2.7"
   resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
@@ -5279,11 +5180,6 @@ decamelize@^1.1.0:
   resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
   integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==
 
-decamelize@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837"
-  integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==
-
 decode-named-character-reference@^1.0.0:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz#daabac9690874c394c81e4162a0304b35d824f0e"
@@ -5303,13 +5199,6 @@ dedent@0.7.0:
   resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c"
   integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==
 
-deep-eql@^3.0.1:
-  version "3.0.1"
-  resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df"
-  integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==
-  dependencies:
-    type-detect "^4.0.0"
-
 deep-eql@^5.0.1:
   version "5.0.2"
   resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-5.0.2.tgz#4b756d8d770a9257300825d52a2c2cff99c3a341"
@@ -5443,16 +5332,16 @@ diff-sequences@^29.6.3:
   resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921"
   integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==
 
-diff@5.0.0, diff@^5.0.0:
-  version "5.0.0"
-  resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b"
-  integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==
-
 diff@^4.0.1:
   version "4.0.2"
   resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
   integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
 
+diff@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b"
+  integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==
+
 dir-compare@^4.2.0:
   version "4.2.0"
   resolved "https://registry.yarnpkg.com/dir-compare/-/dir-compare-4.2.0.tgz#d1d4999c14fbf55281071fdae4293b3b9ce86f19"
@@ -6215,16 +6104,16 @@ escape-html@~1.0.3:
   resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
   integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==
 
-escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
-  integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
-
 escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
   version "1.0.5"
   resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
   integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
 
+escape-string-regexp@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
+  integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
+
 escope@^3.6.0:
   version "3.6.0"
   resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3"
@@ -6344,14 +6233,6 @@ eslint-plugin-import@^2.31.0:
     string.prototype.trimend "^1.0.8"
     tsconfig-paths "^3.15.0"
 
-eslint-plugin-mocha@^9.0.0:
-  version "9.0.0"
-  resolved "https://registry.yarnpkg.com/eslint-plugin-mocha/-/eslint-plugin-mocha-9.0.0.tgz#b4457d066941eecb070dc06ed301c527d9c61b60"
-  integrity sha512-d7knAcQj1jPCzZf3caeBIn3BnW6ikcvfz0kSqQpwPYcVGLoJV5sz0l0OJB2LR8I7dvTDbqq1oV6ylhSgzA10zg==
-  dependencies:
-    eslint-utils "^3.0.0"
-    ramda "^0.27.1"
-
 eslint-plugin-n@^15.7.0:
   version "15.7.0"
   resolved "https://registry.yarnpkg.com/eslint-plugin-n/-/eslint-plugin-n-15.7.0.tgz#e29221d8f5174f84d18f2eb94765f2eeea033b90"
@@ -7055,14 +6936,6 @@ finalhandler@1.3.1:
     statuses "2.0.1"
     unpipe "~1.0.0"
 
-find-up@5.0.0, find-up@^5.0.0:
-  version "5.0.0"
-  resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc"
-  integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==
-  dependencies:
-    locate-path "^6.0.0"
-    path-exists "^4.0.0"
-
 find-up@^2.0.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7"
@@ -7085,6 +6958,14 @@ find-up@^4.0.0, find-up@^4.1.0:
     locate-path "^5.0.0"
     path-exists "^4.0.0"
 
+find-up@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc"
+  integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==
+  dependencies:
+    locate-path "^6.0.0"
+    path-exists "^4.0.0"
+
 flat-cache@^3.0.4:
   version "3.0.4"
   resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11"
@@ -7461,11 +7342,6 @@ get-folder-size@^2.0.1:
     gar "^1.0.4"
     tiny-each-async "2.0.3"
 
-get-func-name@^2.0.0:
-  version "2.0.2"
-  resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41"
-  integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==
-
 get-installed-path@^2.0.3:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/get-installed-path/-/get-installed-path-2.1.1.tgz#a1f33dc6b8af542c9331084e8edbe37fe2634152"
@@ -7678,18 +7554,6 @@ glob@7.1.4:
     once "^1.3.0"
     path-is-absolute "^1.0.0"
 
-glob@7.2.0, glob@^7.1.4:
-  version "7.2.0"
-  resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023"
-  integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==
-  dependencies:
-    fs.realpath "^1.0.0"
-    inflight "^1.0.4"
-    inherits "2"
-    minimatch "^3.0.4"
-    once "^1.3.0"
-    path-is-absolute "^1.0.0"
-
 glob@^10.2.2:
   version "10.3.10"
   resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.10.tgz#0351ebb809fd187fe421ab96af83d3a70715df4b"
@@ -7713,6 +7577,18 @@ glob@^7.1.1, glob@^7.1.3, glob@^7.1.6:
     once "^1.3.0"
     path-is-absolute "^1.0.0"
 
+glob@^7.1.4:
+  version "7.2.0"
+  resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023"
+  integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==
+  dependencies:
+    fs.realpath "^1.0.0"
+    inflight "^1.0.4"
+    inherits "2"
+    minimatch "^3.0.4"
+    once "^1.3.0"
+    path-is-absolute "^1.0.0"
+
 glob@^8.0.1, glob@~8.0.3:
   version "8.0.3"
   resolved "https://registry.yarnpkg.com/glob/-/glob-8.0.3.tgz#415c6eb2deed9e502c68fa44a272e6da6eeca42e"
@@ -7886,11 +7762,6 @@ graphql@^16.8.1:
   resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.10.0.tgz#24c01ae0af6b11ea87bf55694429198aaa8e220c"
   integrity sha512-AjqGKbDGUFRKIRCP9tCKiIGHyriz2oHEbPIbEtcSLSs4YjReZOIPQQWek4+6hjw62H9QShXHyaGivGiYVLeYFQ==
 
-growl@1.10.5:
-  version "1.10.5"
-  resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e"
-  integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==
-
 gtoken@^7.0.0:
   version "7.0.1"
   resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-7.0.1.tgz#b64bd01d88268ea3a3572c9076a85d1c48f1a455"
@@ -8005,7 +7876,7 @@ hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2:
   dependencies:
     function-bind "^1.1.2"
 
-he@1.2.0, he@^1.2.0:
+he@^1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
   integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
@@ -8514,11 +8385,6 @@ is-boolean-object@^1.2.1:
     call-bound "^1.0.2"
     has-tostringtag "^1.0.2"
 
-is-buffer@~1.1.6:
-  version "1.1.6"
-  resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
-  integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
-
 is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7:
   version "1.2.7"
   resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055"
@@ -8710,11 +8576,6 @@ is-plain-obj@^1.0.0, is-plain-obj@^1.1.0:
   resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
   integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==
 
-is-plain-obj@^2.1.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287"
-  integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==
-
 is-plain-obj@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7"
@@ -9449,7 +9310,7 @@ lodash@^4.17.12, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
   integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
 
-log-symbols@4.1.0, log-symbols@^4.0.0, log-symbols@^4.1.0:
+log-symbols@^4.0.0, log-symbols@^4.1.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503"
   integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==
@@ -9485,13 +9346,6 @@ loose-envify@^1.4.0:
   dependencies:
     js-tokens "^3.0.0 || ^4.0.0"
 
-loupe@^2.3.1:
-  version "2.3.4"
-  resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.4.tgz#7e0b9bffc76f148f9be769cb1321d3dcf3cb25f3"
-  integrity sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==
-  dependencies:
-    get-func-name "^2.0.0"
-
 loupe@^3.1.0, loupe@^3.1.2:
   version "3.1.2"
   resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.1.2.tgz#c86e0696804a02218f2206124c45d8b15291a240"
@@ -9697,15 +9551,6 @@ math-intrinsics@^1.0.0:
   resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9"
   integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==
 
-md5@^2.3.0:
-  version "2.3.0"
-  resolved "https://registry.yarnpkg.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f"
-  integrity sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==
-  dependencies:
-    charenc "0.0.2"
-    crypt "0.0.2"
-    is-buffer "~1.1.6"
-
 mdast-util-from-markdown@^1.3.0:
   version "1.3.1"
   resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.1.tgz#9421a5a247f10d31d2faed2a30df5ec89ceafcf0"
@@ -10055,13 +9900,6 @@ minimatch@3.0.5:
   dependencies:
     brace-expansion "^1.1.7"
 
-minimatch@4.2.1:
-  version "4.2.1"
-  resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-4.2.1.tgz#40d9d511a46bdc4e563c22c3080cde9c0d8299b4"
-  integrity sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==
-  dependencies:
-    brace-expansion "^1.1.7"
-
 minimatch@9.0.3, minimatch@^9.0.0, minimatch@^9.0.1, minimatch@^9.0.3:
   version "9.0.3"
   resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825"
@@ -10235,52 +10073,6 @@ mkdirp@^1.0.3, mkdirp@^1.0.4:
   resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
   integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
 
-mkdirp@^3.0.0:
-  version "3.0.1"
-  resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-3.0.1.tgz#e44e4c5607fb279c168241713cc6e0fea9adcb50"
-  integrity sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==
-
-mocha-junit-reporter@^2.2.1:
-  version "2.2.1"
-  resolved "https://registry.yarnpkg.com/mocha-junit-reporter/-/mocha-junit-reporter-2.2.1.tgz#739f5595d0f051d07af9d74e32c416e13a41cde5"
-  integrity sha512-iDn2tlKHn8Vh8o4nCzcUVW4q7iXp7cC4EB78N0cDHIobLymyHNwe0XG8HEHHjc3hJlXm0Vy6zcrxaIhnI2fWmw==
-  dependencies:
-    debug "^4.3.4"
-    md5 "^2.3.0"
-    mkdirp "^3.0.0"
-    strip-ansi "^6.0.1"
-    xml "^1.0.1"
-
-mocha@^9.0.1:
-  version "9.2.2"
-  resolved "https://registry.yarnpkg.com/mocha/-/mocha-9.2.2.tgz#d70db46bdb93ca57402c809333e5a84977a88fb9"
-  integrity sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==
-  dependencies:
-    "@ungap/promise-all-settled" "1.1.2"
-    ansi-colors "4.1.1"
-    browser-stdout "1.3.1"
-    chokidar "3.5.3"
-    debug "4.3.3"
-    diff "5.0.0"
-    escape-string-regexp "4.0.0"
-    find-up "5.0.0"
-    glob "7.2.0"
-    growl "1.10.5"
-    he "1.2.0"
-    js-yaml "4.1.0"
-    log-symbols "4.1.0"
-    minimatch "4.2.1"
-    ms "2.1.3"
-    nanoid "3.3.1"
-    serialize-javascript "6.0.0"
-    strip-json-comments "3.1.1"
-    supports-color "8.1.1"
-    which "2.0.2"
-    workerpool "6.2.0"
-    yargs "16.2.0"
-    yargs-parser "20.2.4"
-    yargs-unparser "2.0.0"
-
 modify-values@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022"
@@ -10400,11 +10192,6 @@ nan@^2.4.0:
   resolved "https://registry.yarnpkg.com/nan/-/nan-2.18.0.tgz#26a6faae7ffbeb293a39660e88a76b82e30b7554"
   integrity sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==
 
-nanoid@3.3.1:
-  version "3.3.1"
-  resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35"
-  integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==
-
 nanoid@^3.3.7:
   version "3.3.7"
   resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8"
@@ -11330,11 +11117,6 @@ pathe@^1.1.2:
   resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.2.tgz#6c4cb47a945692e48a1ddd6e4094d170516437ec"
   integrity sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==
 
-pathval@^1.1.1:
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d"
-  integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==
-
 pathval@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/pathval/-/pathval-2.0.0.tgz#7e2550b422601d4f6b8e26f1301bc8f15a741a25"
@@ -11614,11 +11396,6 @@ quick-lru@^5.1.1:
   resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932"
   integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==
 
-ramda@^0.27.1:
-  version "0.27.2"
-  resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.27.2.tgz#84463226f7f36dc33592f6f4ed6374c48306c3f1"
-  integrity sha512-SbiLPU40JuJniHexQSAgad32hfwd+DRUdwF2PlVuI5RZD0/vahUco7R8vD86J/tcEKKF9vZrUVwgtmGCqlCKyA==
-
 random-path@^0.1.0:
   version "0.1.2"
   resolved "https://registry.yarnpkg.com/random-path/-/random-path-0.1.2.tgz#78b7f1570e2a09f66a4e2e0113a98ed588e85da9"
@@ -12306,13 +12083,6 @@ serialize-error@^7.0.1:
   dependencies:
     type-fest "^0.13.1"
 
-serialize-javascript@6.0.0:
-  version "6.0.0"
-  resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8"
-  integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==
-  dependencies:
-    randombytes "^2.1.0"
-
 serialize-javascript@^6.0.1:
   version "6.0.1"
   resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.1.tgz#b206efb27c3da0b0ab6b52f48d170b7996458e5c"
@@ -12991,7 +12761,7 @@ strip-indent@^3.0.0:
   dependencies:
     min-indent "^1.0.0"
 
-strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1, strip-json-comments@~3.1.1:
+strip-json-comments@^3.1.0, strip-json-comments@^3.1.1, strip-json-comments@~3.1.1:
   version "3.1.1"
   resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
   integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
@@ -13034,13 +12804,6 @@ sumchecker@^3.0.1:
   dependencies:
     debug "^4.1.0"
 
-supports-color@8.1.1, supports-color@^8.0.0:
-  version "8.1.1"
-  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c"
-  integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==
-  dependencies:
-    has-flag "^4.0.0"
-
 supports-color@^5.3.0:
   version "5.5.0"
   resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
@@ -13055,6 +12818,13 @@ supports-color@^7.1.0:
   dependencies:
     has-flag "^4.0.0"
 
+supports-color@^8.0.0:
+  version "8.1.1"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c"
+  integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==
+  dependencies:
+    has-flag "^4.0.0"
+
 supports-color@^9.2.2:
   version "9.2.3"
   resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-9.2.3.tgz#a6e2c97fc20c80abecd69e50aebe4783ff77d45a"
@@ -13440,11 +13210,6 @@ type-check@^0.4.0, type-check@~0.4.0:
   dependencies:
     prelude-ls "^1.2.1"
 
-type-detect@^4.0.0, type-detect@^4.0.5:
-  version "4.0.8"
-  resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
-  integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
-
 type-fest@^0.13.1:
   version "0.13.1"
   resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934"
@@ -14153,13 +13918,6 @@ which-typed-array@^1.1.9:
     has-tostringtag "^1.0.0"
     is-typed-array "^1.1.10"
 
-which@2.0.2, which@^2.0.1, which@^2.0.2:
-  version "2.0.2"
-  resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
-  integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
-  dependencies:
-    isexe "^2.0.0"
-
 which@^1.2.14, which@^1.2.4, which@^1.2.9:
   version "1.3.1"
   resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
@@ -14167,6 +13925,13 @@ which@^1.2.14, which@^1.2.4, which@^1.2.9:
   dependencies:
     isexe "^2.0.0"
 
+which@^2.0.1, which@^2.0.2:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
+  integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
+  dependencies:
+    isexe "^2.0.0"
+
 which@^3.0.0:
   version "3.0.1"
   resolved "https://registry.yarnpkg.com/which/-/which-3.0.1.tgz#89f1cd0c23f629a8105ffe69b8172791c87b4be1"
@@ -14221,11 +13986,6 @@ wordwrap@^1.0.0:
   resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
   integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==
 
-workerpool@6.2.0:
-  version "6.2.0"
-  resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.0.tgz#827d93c9ba23ee2019c3ffaff5c27fccea289e8b"
-  integrity sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==
-
 "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
   version "7.0.0"
   resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
@@ -14320,11 +14080,6 @@ xdg-basedir@^4.0.0:
   resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13"
   integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==
 
-xml@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5"
-  integrity sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==
-
 xmlbuilder@^15.1.1:
   version "15.1.1"
   resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-15.1.1.tgz#9dcdce49eea66d8d10b42cae94a79c3c8d0c2ec5"
@@ -14406,16 +14161,6 @@ yargs-parser@^21.0.0:
   resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.0.0.tgz#a485d3966be4317426dd56bdb6a30131b281dc55"
   integrity sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA==
 
-yargs-unparser@2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb"
-  integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==
-  dependencies:
-    camelcase "^6.0.0"
-    decamelize "^4.0.0"
-    flat "^5.0.2"
-    is-plain-obj "^2.1.0"
-
 yargs@16.2.0, yargs@^16.0.0, yargs@^16.0.2, yargs@^16.2.0:
   version "16.2.0"
   resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66"