diff --git a/packages/@n8n/json-schema-to-zod/jest.config.js b/packages/@n8n/json-schema-to-zod/jest.config.js deleted file mode 100644 index b8e98e89708..00000000000 --- a/packages/@n8n/json-schema-to-zod/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -/** @type {import('jest').Config} */ -module.exports = { - ...require('../../../jest.config'), - setupFilesAfterEnv: ['/test/extend-expect.ts'], -}; diff --git a/packages/@n8n/json-schema-to-zod/package.json b/packages/@n8n/json-schema-to-zod/package.json index f653ce7b4f8..ae689eb0a54 100644 --- a/packages/@n8n/json-schema-to-zod/package.json +++ b/packages/@n8n/json-schema-to-zod/package.json @@ -28,9 +28,9 @@ "build:esm": "tsc -p tsconfig.esm.json && node postesm.cjs", "build": "rimraf ./dist && pnpm run build:types && pnpm run build:cjs && pnpm run build:esm", "dry": "pnpm run build && pnpm pub --dry-run", - "test": "jest", - "test:unit": "jest", - "test:watch": "jest --watch" + "test": "vitest run", + "test:unit": "vitest run", + "test:dev": "vitest --silent=false" }, "keywords": [ "zod", @@ -65,6 +65,10 @@ "devDependencies": { "@n8n/typescript-config": "workspace:*", "@types/json-schema": "^7.0.15", - "zod": "catalog:" + "zod": "catalog:", + "@n8n/vitest-config": "workspace:*", + "@vitest/coverage-v8": "catalog:", + "vitest": "catalog:", + "vitest-mock-extended": "catalog:" } } diff --git a/packages/@n8n/json-schema-to-zod/test/extend-expect.ts b/packages/@n8n/json-schema-to-zod/test/extend-expect.ts index 5196e434167..5cb6182c8c9 100644 --- a/packages/@n8n/json-schema-to-zod/test/extend-expect.ts +++ b/packages/@n8n/json-schema-to-zod/test/extend-expect.ts @@ -1,7 +1,8 @@ +import { expect, type MatcherState } from 'vitest'; import type { z } from 'zod'; expect.extend({ - toMatchZod(this: jest.MatcherContext, actual: z.ZodTypeAny, expected: z.ZodTypeAny) { + toMatchZod(this: MatcherState, actual: z.ZodTypeAny, expected: z.ZodTypeAny) { const actualSerialized = JSON.stringify(actual._def, null, 2); const expectedSerialized = JSON.stringify(expected._def, null, 2); const pass = this.equals(actualSerialized, expectedSerialized); diff --git a/packages/@n8n/json-schema-to-zod/test/parsers/parse-object.test.ts b/packages/@n8n/json-schema-to-zod/test/parsers/parse-object.test.ts index 00a2e194cd3..e3406405539 100644 --- a/packages/@n8n/json-schema-to-zod/test/parsers/parse-object.test.ts +++ b/packages/@n8n/json-schema-to-zod/test/parsers/parse-object.test.ts @@ -1,6 +1,6 @@ /* eslint-disable n8n-local-rules/no-skipped-tests */ import type { JSONSchema7 } from 'json-schema'; -import { z, ZodError } from 'zod'; +import { z } from 'zod'; import { parseObject } from '../../src/parsers/parse-object'; @@ -432,24 +432,26 @@ describe('parseObject', () => { }, }); - expect(run(result, { b: 'hello', x: true })).toEqual({ + expect(run(result, { b: 'hello', x: true })).toMatchObject({ success: false, - error: new ZodError([ - { - code: 'invalid_type', - expected: 'string', - received: 'undefined', - path: ['a'], - message: 'Required', - }, - { - code: 'invalid_type', - expected: 'number', - received: 'string', - path: ['b'], - message: 'Expected number, received string', - }, - ]), + error: expect.objectContaining({ + issues: [ + { + code: 'invalid_type', + expected: 'string', + received: 'undefined', + path: ['a'], + message: 'Required', + }, + { + code: 'invalid_type', + expected: 'number', + received: 'string', + path: ['b'], + message: 'Expected number, received string', + }, + ], + }), }); }); @@ -474,31 +476,33 @@ describe('parseObject', () => { expect(result).toMatchZod(expected); - expect(run(result, { b: 'hello', x: 'true' })).toEqual({ + expect(run(result, { b: 'hello', x: 'true' })).toMatchObject({ success: false, - error: new ZodError([ - { - code: 'invalid_type', - expected: 'string', - received: 'undefined', - path: ['a'], - message: 'Required', - }, - { - code: 'invalid_type', - expected: 'number', - received: 'string', - path: ['b'], - message: 'Expected number, received string', - }, - { - code: 'invalid_type', - expected: 'boolean', - received: 'string', - path: ['x'], - message: 'Expected boolean, received string', - }, - ]), + error: expect.objectContaining({ + issues: [ + { + code: 'invalid_type', + expected: 'string', + received: 'undefined', + path: ['a'], + message: 'Required', + }, + { + code: 'invalid_type', + expected: 'number', + received: 'string', + path: ['b'], + message: 'Expected number, received string', + }, + { + code: 'invalid_type', + expected: 'boolean', + received: 'string', + path: ['x'], + message: 'Expected boolean, received string', + }, + ], + }), }); }); @@ -549,17 +553,19 @@ describe('parseObject', () => { data: { a: 'a', b: 2, '.': [] }, }); - expect(run(result, { a: 'a', b: 2, '.': '[]' })).toEqual({ + expect(run(result, { a: 'a', b: 2, '.': '[]' })).toMatchObject({ success: false, - error: new ZodError([ - { - code: 'invalid_type', - expected: 'array', - received: 'string', - path: ['.'], - message: 'Expected array, received string', - }, - ]), + error: expect.objectContaining({ + issues: [ + { + code: 'invalid_type', + expected: 'array', + received: 'string', + path: ['.'], + message: 'Expected array, received string', + }, + ], + }), }); }); @@ -713,28 +719,30 @@ describe('parseObject', () => { expect(result).toMatchZod(expected); - expect(run(result, { x: true, '.': [], ',': [] })).toEqual({ + expect(run(result, { x: true, '.': [], ',': [] })).toMatchObject({ success: false, - error: new ZodError([ - { - path: [','], - code: 'custom', - message: 'Invalid input: Key matching regex /,/ must match schema', - params: { - issues: [ - { - code: 'too_small', - minimum: 1, - type: 'array', - inclusive: true, - exact: false, - message: 'Array must contain at least 1 element(s)', - path: [], - }, - ], + error: expect.objectContaining({ + issues: [ + { + path: [','], + code: 'custom', + message: 'Invalid input: Key matching regex /,/ must match schema', + params: { + issues: [ + { + code: 'too_small', + minimum: 1, + type: 'array', + inclusive: true, + exact: false, + message: 'Array must contain at least 1 element(s)', + path: [], + }, + ], + }, }, - }, - ]), + ], + }), }); }); @@ -818,28 +826,30 @@ describe('parseObject', () => { data: { '.': [] }, }); - expect(run(result, { ',': [] })).toEqual({ + expect(run(result, { ',': [] })).toMatchObject({ success: false, - error: new ZodError([ - { - path: [','], - code: 'custom', - message: 'Invalid input: Key matching regex /,/ must match schema', - params: { - issues: [ - { - code: 'too_small', - minimum: 1, - type: 'array', - inclusive: true, - exact: false, - message: 'Array must contain at least 1 element(s)', - path: [], - }, - ], + error: expect.objectContaining({ + issues: [ + { + path: [','], + code: 'custom', + message: 'Invalid input: Key matching regex /,/ must match schema', + params: { + issues: [ + { + code: 'too_small', + minimum: 1, + type: 'array', + inclusive: true, + exact: false, + message: 'Array must contain at least 1 element(s)', + path: [], + }, + ], + }, }, - }, - ]), + ], + }), }); expect(result).toMatchZod(expected); diff --git a/packages/@n8n/json-schema-to-zod/tsconfig.json b/packages/@n8n/json-schema-to-zod/tsconfig.json index 2d4dee48d9f..7bd5d90c740 100644 --- a/packages/@n8n/json-schema-to-zod/tsconfig.json +++ b/packages/@n8n/json-schema-to-zod/tsconfig.json @@ -6,7 +6,8 @@ "strict": true, "noEmit": true, "skipLibCheck": true, - "esModuleInterop": true + "esModuleInterop": true, + "types": ["vitest/globals"] }, "include": ["src/**/*.ts", "test/**/*.ts"] } diff --git a/packages/@n8n/json-schema-to-zod/vite.config.ts b/packages/@n8n/json-schema-to-zod/vite.config.ts new file mode 100644 index 00000000000..b1c054c6c3b --- /dev/null +++ b/packages/@n8n/json-schema-to-zod/vite.config.ts @@ -0,0 +1,11 @@ +import { defineConfig, mergeConfig } from 'vitest/config'; +import { vitestConfig } from '@n8n/vitest-config/node'; + +export default mergeConfig( + defineConfig({ + test: { + setupFiles: ['./test/extend-expect.ts'], + }, + }), + vitestConfig, +); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7e46a37dcaf..2db9b865c56 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1675,9 +1675,21 @@ importers: '@n8n/typescript-config': specifier: workspace:* version: link:../typescript-config + '@n8n/vitest-config': + specifier: workspace:* + version: link:../vitest-config '@types/json-schema': specifier: ^7.0.15 version: 7.0.15 + '@vitest/coverage-v8': + specifier: 'catalog:' + version: 4.1.1(vitest@4.1.1(@opentelemetry/api@1.9.0)(@types/node@20.19.21)(jsdom@23.0.1(bufferutil@4.0.9)(utf-8-validate@5.0.10))(vite@8.0.2(@types/node@20.19.21)(esbuild@0.25.10)(jiti@2.6.1)(sass-embedded@1.98.0)(sass@1.98.0)(terser@5.16.1)(tsx@4.19.3)(yaml@2.8.3))) + vitest: + specifier: 'catalog:' + version: 4.1.1(@opentelemetry/api@1.9.0)(@types/node@20.19.21)(@vitest/browser-playwright@4.0.16)(jsdom@23.0.1(bufferutil@4.0.9)(utf-8-validate@5.0.10))(vite@8.0.2(@types/node@20.19.21)(esbuild@0.25.10)(jiti@2.6.1)(sass-embedded@1.98.0)(sass@1.98.0)(terser@5.16.1)(tsx@4.19.3)(yaml@2.8.3)) + vitest-mock-extended: + specifier: 'catalog:' + version: 3.1.0(typescript@6.0.2)(vitest@4.1.1(@opentelemetry/api@1.9.0)(@types/node@20.19.21)(jsdom@23.0.1(bufferutil@4.0.9)(utf-8-validate@5.0.10))(vite@8.0.2(@types/node@20.19.21)(esbuild@0.25.10)(jiti@2.6.1)(sass-embedded@1.98.0)(sass@1.98.0)(terser@5.16.1)(tsx@4.19.3)(yaml@2.8.3))) zod: specifier: 3.25.67 version: 3.25.67