chore: Remove remaining Jest references (no-changelog) (#33412)

Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
This commit is contained in:
Matsu
2026-07-09 09:29:24 +03:00
committed by GitHub
co-authored by Claude Opus 4.8 cubic-dev-ai[bot]
parent 29e0e32e3b
commit 8bb6489918
25 changed files with 43 additions and 65 deletions
+1 -2
View File
@@ -29,8 +29,7 @@ on:
description: |
Newline-separated list of CHANGED_FILES from ci-filter. Passed to
per-package `janitor scope` invocations so test runners can filter
to actually-changed source files via jest --findRelatedTests or
vitest related.
to actually-changed source files via vitest related.
required: false
default: ''
type: string
@@ -1,7 +1,7 @@
import type { Mock } from 'vitest';
// Mock @daytona/sdk so we can drive sandbox creation, token refresh, and
// sandbox refetch behavior from Jest without touching the network.
// sandbox refetch behavior from Vitest without touching the network.
interface MockSandbox {
id: string;
@@ -185,7 +185,7 @@ describe('Discovery Subgraph - Integration Tests', () => {
vi.setConfig({ testTimeout: 1800000 }); // 30 minutes
beforeAll(async () => {
// Override console.log to use process.stdout directly, bypassing Jest's
// Override console.log to use process.stdout directly, bypassing Vitest's
// verbose wrapper that adds stack traces to every log line
vi.spyOn(console, 'log').mockImplementation((...args: unknown[]) => {
process.stdout.write(args.map(String).join(' ') + '\n');
@@ -106,10 +106,9 @@ function respondWith(routes: Route[]) {
type AnyFn = (...args: any[]) => any;
/**
* Test-framework mock factory — pass `jest.fn` or `vi.fn`. Injected so this
* helper stays framework-neutral: `@n8n/backend-network` runs on vitest while
* consumers such as `packages/cli` run on jest, and `expect(fn).toHaveBeenCalled…`
* assertions need a real mock from the consumer's own framework.
* Test-framework mock factory — pass `vi.fn`. Injected so this helper stays
* framework-neutral and `expect(fn).toHaveBeenCalled…` assertions get a real
* mock from the consumer's own test framework.
*/
export type MockFnFactory = <T extends AnyFn>(
impl: T,
@@ -121,7 +120,7 @@ export type MockFnFactory = <T extends AnyFn>(
* `headers` merged), so assertions see exactly what the real client would send.
*
* @param routes responses to serve, matched and consumed in order.
* @param fn the consumer's mock factory (`jest.fn` / `vi.fn`).
* @param fn the consumer's mock factory (`vi.fn`).
*/
export function createFakeOutboundHttp(routes: Route[], fn: MockFnFactory) {
const stub = respondWith(routes);
@@ -12,7 +12,7 @@
"lint": "eslint . --quiet",
"lint:fix": "eslint . --fix",
"watch": "tsc -p tsconfig.build.json --watch",
"test": "echo \"WARNING: no test specified\" && exit 0",
"test": "node -e \"process.exit(0)\"",
"test:dev": "echo \"WARNING: no test specified\" && exit 0"
},
"main": "dist/index.js",
+1 -1
View File
@@ -12,7 +12,7 @@
"lint": "eslint . --quiet",
"lint:fix": "eslint . --fix",
"start": "./bin/n8n-benchmark",
"test": "echo \"WARNING: no test specified\" && exit 0",
"test": "node -e \"process.exit(0)\"",
"typecheck": "tsc --noEmit",
"benchmark": "zx scripts/run.mjs",
"benchmark-in-cloud": "pnpm benchmark --env cloud",
+1 -1
View File
@@ -12,7 +12,7 @@
"lint": "eslint . --quiet",
"lint:fix": "eslint . --fix",
"watch": "tsc -p tsconfig.build.json --watch",
"test": "jest --passWithNoTests"
"test": "node -e \"process.exit(0)\""
},
"main": "dist/index.js",
"module": "src/index.ts",
+2 -2
View File
@@ -16,8 +16,8 @@ import { configDefaults } from 'vitest/config';
* only `tsc` with cross-file type information collapses the union to `String`. Vite's
* oxc transform — and SWC — emit `Object` instead, which TypeORM rejects at
* `DataSource.initialize()`. Single-file `transpileModule` also emits `Object` because
* it can't resolve the imported alias. A full Program is required, which mirrors the
* old jest config that set `isolatedModules: false` for exactly this reason.
* it can't resolve the imported alias. A full Program is required — the same
* reason a non-isolated-modules TypeScript compile is needed here.
*
* Scoping to `src/entities/**` keeps the cost contained: only the ~50 entity files pay
* the tsc price (and the Program is rooted there), while DI `@Service` constructor
+1 -1
View File
@@ -12,7 +12,7 @@
"lint": "eslint . --quiet",
"lint:fix": "eslint . --fix",
"watch": "tsc -p tsconfig.build.json --watch",
"test": "echo \"WARNING: no test specified\" && exit 0",
"test": "node -e \"process.exit(0)\"",
"test:dev": "echo \"WARNING: no test specified\" && exit 0"
},
"main": "dist/index.js",
@@ -5,7 +5,7 @@ export const NoErrorInstanceInToThrowRule = ESLintUtils.RuleCreator.withoutDocs(
type: 'problem',
docs: {
description:
'Disallow passing error instances to `.toThrow()` and `.toThrowError`. Jest compares by reference, not message, making assertions flaky. Pass the error class and message string separately instead.',
'Disallow passing error instances to `.toThrow()` and `.toThrowError`. Passing an instance makes the assertion ambiguous and flaky. Pass the error class and message string separately instead.',
},
messages: {
noErrorInstance:
@@ -40,7 +40,7 @@ n8n community nodes are distributed as pre-built npm packages. Unlike regular np
"name": "n8n-nodes-example",
"scripts": {
"build": "tsc",
"test": "jest"
"test": "vitest run"
}
}
```
+1 -1
View File
@@ -39,7 +39,7 @@
"build:unchecked": "pnpm run build",
"create-json-schema": "tsx scripts/create-json-schema.ts",
"preview": "vite preview",
"test": "node -e \"process.exit(0);\""
"test": "node -e \"process.exit(0)\""
},
"peerDependencies": {
"vue": "catalog:frontend",
@@ -3,7 +3,7 @@
*
* This entry point intentionally avoids importing anything from `../agent`
* or other native agent-tainted modules so it remains safe to consume from
* Jest CJS test environments.
* downstream test environments.
*/
export {
@@ -13,7 +13,7 @@ import * as path from 'node:path';
* 2. NODE_PATH must not be clobbered by load-nodes-and-credentials.ts
* 3. Module._initPaths() must be called to pick up NODE_PATH at runtime
*
* Tests use child processes because Jest intercepts require() with its own
* Tests use child processes because Vitest intercepts require() with its own
* resolver which doesn't respect NODE_PATH changes.
*
* IMPORTANT: Scripts are placed in a separate directory from the installed
@@ -3,9 +3,6 @@
* only auto-excludes the test files it runs, so type decls, mocks and test
* helpers otherwise land in the denominator at 0%. Spread these onto
* `coverageConfigDefaults.exclude` in each config.
*
* Mirrors the jest equivalent at the repo root (jest.coverage-excludes.js) —
* same intent, plain globs here vs `!`-negated globs there. Keep them in sync.
*/
export const coverageExcludes = [
'**/*.spec.ts',
@@ -17,10 +17,10 @@ import { generateNodeDefinitions } from '../generate-types/generate-node-defs-cl
// Use a worker-specific directory to prevent race conditions when multiple test
// workers run schema-using tests in parallel (they would otherwise concurrently
// delete and regenerate schemas into the same shared temp directory).
// Vitest exposes the per-worker id as VITEST_POOL_ID; Jest used JEST_WORKER_ID.
// Vitest exposes the per-worker id as VITEST_POOL_ID.
// Without this, every parallel worker collapses onto the same `-0` directory and
// one worker's rmSync wipes schemas another worker just generated.
const WORKER_ID = process.env.VITEST_POOL_ID ?? process.env.JEST_WORKER_ID ?? '0';
const WORKER_ID = process.env.VITEST_POOL_ID ?? '0';
const SCHEMA_TEST_DIR = path.join(os.tmpdir(), `n8n-schema-tests-${WORKER_ID}`);
const STAMP_FILE = path.join(SCHEMA_TEST_DIR, '.generator-hash');
@@ -425,7 +425,7 @@ describe('enqueueExecution', () => {
const error = new Error('stop for test purposes');
// mock a rejection to stop execution flow before we create the PCancelable promise,
// so that Jest does not move on to tear down the suite until the PCancelable settles
// so that Vitest does not move on to tear down the suite until the PCancelable settles
addJob.mockRejectedValueOnce(error);
// @ts-expect-error Private method
@@ -262,7 +262,7 @@ describe('TaskBroker', () => {
validUntil: createValidUntil(1000),
};
vi.spyOn(taskBroker, 'acceptOffer').mockResolvedValue(); // allow Jest to exit cleanly
vi.spyOn(taskBroker, 'acceptOffer').mockResolvedValue(); // allow Vitest to exit cleanly
taskBroker.taskOffered(offer);
@@ -41,7 +41,7 @@ function expectWorkflowsMatch(
const oldSorted = [...oldWorkflows].sort((a, b) => a.id.localeCompare(b.id));
const newSorted = [...newWorkflows].sort((a, b) => a.id.localeCompare(b.id));
// Jest's toEqual does deep recursive comparison of all fields
// Vitest's toEqual does deep recursive comparison of all fields
expect(newSorted).toEqual(oldSorted);
}
@@ -73,7 +73,7 @@ export interface SetupProps {
enabledFeatures?: BooleanLicenseFeature[];
quotas?: Partial<{ [K in NumericLicenseFeature]: number }>;
modules?: ModuleName[];
/** Override the default Jest timeout (ms) for the shared `beforeAll` setup hook. */
/** Override the default test timeout (ms) for the shared `beforeAll` setup hook. */
setupTimeout?: number;
}
@@ -379,7 +379,7 @@ export const setupTestServer = ({
// Close the HTTP server first so any in-flight requests can't reach the
// DI container after testDb.terminate() resets it. Await the close so
// pending handlers drain before the next file's beforeAll runs in
// persistent Jest workers — otherwise stale handlers call
// persistent Vitest workers — otherwise stale handlers call
// Container.get(Logger), construct a fresh Logger, and trip Vitest's
// "environment torn down" guard when winston is imported.
// Skip when the server never started listening (some suites bail in
+10 -20
View File
@@ -66,36 +66,26 @@ if (!pkgRoot) {
const fileRelToPkg = relative(pkgRoot, absFile);
function detectRunner(pkgRootDir) {
function detectVitest(pkgRootDir) {
const pkg = JSON.parse(readFileSync(resolve(pkgRootDir, 'package.json'), 'utf8'));
const deps = { ...pkg.devDependencies, ...pkg.dependencies };
if (deps.vitest) return 'vitest';
if (deps.jest) return 'jest';
if (deps.vitest) return true;
const testScript = pkg.scripts?.test ?? '';
if (/\bvitest\b/.test(testScript)) return 'vitest';
if (/\bjest\b/.test(testScript)) return 'jest';
if (/\bvitest\b/.test(pkg.scripts?.test ?? '')) return true;
if (existsSync(resolve(pkgRootDir, 'jest.config.js')) ||
existsSync(resolve(pkgRootDir, 'jest.config.ts')) ||
existsSync(resolve(pkgRootDir, 'jest.config.mjs'))) return 'jest';
if (existsSync(resolve(pkgRootDir, 'vitest.config.ts')) ||
return (
existsSync(resolve(pkgRootDir, 'vitest.config.ts')) ||
existsSync(resolve(pkgRootDir, 'vitest.config.js')) ||
existsSync(resolve(pkgRootDir, 'vitest.config.mjs'))) return 'vitest';
return null;
existsSync(resolve(pkgRootDir, 'vitest.config.mjs'))
);
}
const runner = detectRunner(pkgRoot);
if (!runner) {
console.error(`Could not detect vitest or jest in ${pkgRoot}/package.json`);
if (!detectVitest(pkgRoot)) {
console.error(`Could not detect vitest in ${pkgRoot}/package.json`);
process.exit(2);
}
const runnerArgs =
runner === 'vitest'
? ['vitest', 'run', fileRelToPkg, '--reporter=dot']
: ['jest', fileRelToPkg, '--colors=false'];
const runnerArgs = ['vitest', 'run', fileRelToPkg, '--reporter=dot'];
let passed = 0;
let firstFailureLogged = false;
@@ -65,10 +65,6 @@ describe('findPackageForSourceFile', () => {
});
it('returns undefined for unowned paths', () => {
assert.equal(
findPackageForSourceFile('packages/@n8n/expression-runtime/src/foo.ts', ELIGIBLE),
undefined,
);
assert.equal(findPackageForSourceFile('README.md', ELIGIBLE), undefined);
});
});
@@ -88,7 +84,7 @@ describe('buildMatrixRowForFile (on-demand re-score path)', () => {
it('throws for files outside ELIGIBLE_PACKAGES', () => {
assert.throws(
() => buildMatrixRowForFile('packages/cli/src/server.ts', ELIGIBLE),
() => buildMatrixRowForFile('packages/nodes-base/utils/binary.ts', ELIGIBLE),
/No mutation-tracked package owns/,
);
});
@@ -332,8 +328,8 @@ describe('buildMatrixFromPicked (global picker → matrix shape)', () => {
// builder dies rather than spawning a mutate job we can't service.
const picked = [
{
source_file_path: 'packages/@n8n/expression-runtime/src/foo.ts',
package: '@n8n/expression-runtime',
source_file_path: 'packages/nodes-base/utils/binary.ts',
package: 'n8n-nodes-base',
prior_status: 'new',
effective_status: 'new',
value: 1,
+4 -4
View File
@@ -118,14 +118,14 @@ const NON_SOURCE_DIRS = new Set(['__tests__', '__mocks__', 'fixtures']);
// The vitest-eligible mutation-tracked packages. Single source of truth for
// global mode: the picker walks every entry here unless overridden via
// --block. Adding a package = one-line append here AND in
// .github/workflows/mutation-health-nightly.yml `setup` job. Jest packages
// and the isolated-vm engine (@n8n/expression-runtime, blocked on DEVP-257)
// are intentionally absent.
// --block. The nightly workflow's `setup` job builds its matrix from this
// export (DEVP-497), so adding a package = one-line append here, nothing else.
export const ELIGIBLE_PACKAGES = [
{ name: 'n8n-workflow', dir: 'packages/workflow' },
{ name: '@n8n/crdt', dir: 'packages/@n8n/crdt' },
{ name: '@n8n/decorators', dir: 'packages/@n8n/decorators' },
{ name: '@n8n/expression-runtime', dir: 'packages/@n8n/expression-runtime' },
{ name: 'n8n', dir: 'packages/cli' },
];
export function isEligible(pkgName) {
+1 -4
View File
@@ -108,10 +108,7 @@ describe('isEligible (vitest allowlist unit test)', () => {
});
it('rejects packages outside the allowlist', () => {
// expression-runtime is intentionally blocked on DEVP-257
assert.equal(isEligible('@n8n/expression-runtime'), false);
// jest packages aren't onboarded yet
assert.equal(isEligible('@n8n/cli'), false);
assert.equal(isEligible('@n8n/foo'), false);
assert.equal(isEligible(''), false);
assert.equal(isEligible(undefined), false);
});