├── .eslintrc.cjs ├── .github └── workflows │ ├── ci.yml │ └── release.yml ├── .gitignore ├── .npmrc ├── .vscode └── settings.json ├── LICENSE ├── README.md ├── build.config.ts ├── changelogithub.config.ts ├── package.json ├── src ├── MockGenerator.ts ├── errors │ └── DepthLimitError.ts ├── generators │ ├── ArrayGenerator.ts │ ├── BaseGenerator.ts │ ├── BigIntGenerator.ts │ ├── BooleanGenerator.ts │ ├── BrandedGenerator.ts │ ├── CatchGenerator.ts │ ├── DateGenerator.ts │ ├── DefaultGenerator.ts │ ├── DiscriminatedUnionGenerator.ts │ ├── EffectsGenerator.ts │ ├── EnumGenerator.ts │ ├── FunctionGenerator.ts │ ├── IntersectionGenerator.ts │ ├── LazyGenerator.ts │ ├── LiteralGenerator.ts │ ├── MapGenerator.ts │ ├── NaNGenerator.ts │ ├── NativeEnumGenerator.ts │ ├── NullGenerator.ts │ ├── NullableGenerator.ts │ ├── NumberGenerator.ts │ ├── ObjectGenerator.ts │ ├── OptionalGenerator.ts │ ├── PipelineGenerator.ts │ ├── PromiseGenerator.ts │ ├── ReadonlyGenerator.ts │ ├── RecordGenerator.ts │ ├── SetGenerator.ts │ ├── StringGenerator.ts │ ├── SymbolGenerator.ts │ ├── TuppleGenerator.ts │ ├── UndefinedGenerator.ts │ ├── UnionGenerator.ts │ └── VoidGenerator.ts └── index.ts ├── tests ├── anyValues.test.ts ├── array.test.ts ├── bigInt.test.ts ├── boolean.test.ts ├── branded.test.ts ├── catch.test.ts ├── date.test.ts ├── default.test.ts ├── discriminatedUnion.test.ts ├── effects.test.ts ├── empty.test.ts ├── enum.test.ts ├── function.test.ts ├── intersection.test.ts ├── lazy.test.ts ├── literal.test.ts ├── map.test.ts ├── nan.test.ts ├── nativeEnum.test.ts ├── nullable.test.ts ├── number.test.ts ├── object.test.ts ├── optional.test.ts ├── pipeline.test.ts ├── promise.test.ts ├── readonly.test.ts ├── record.test.ts ├── set.test.ts ├── string.test.ts ├── symbol.test.ts ├── tuple.test.ts ├── union.test.ts ├── utils │ └── expect.ts └── void.test.ts ├── tsconfig.json └── yarn.lock /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: '@antfu/eslint-config-ts', 3 | rules: { 4 | 'semi': 'off', 5 | '@typescript-eslint/semi': ['error', 'always'], 6 | 'unused-imports/no-unused-imports': 'error', 7 | 'unused-imports/no-unused-vars': [ 8 | 'error', 9 | { vars: 'all', varsIgnorePattern: '^_', args: 'after-used', argsIgnorePattern: '^_' }, 10 | ], 11 | 'curly': ['error', 'multi-line', 'consistent'], 12 | 'prefer-destructuring': 'error', 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | pull_request: 9 | branches: 10 | - main 11 | 12 | jobs: 13 | lint: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v3 17 | 18 | - name: Set node 19 | uses: actions/setup-node@v3 20 | with: 21 | node-version: 18.x 22 | cache: yarn 23 | 24 | - name: Install 25 | run: yarn 26 | 27 | - name: Lint 28 | run: yarn lint 29 | 30 | typecheck: 31 | runs-on: ubuntu-latest 32 | steps: 33 | - uses: actions/checkout@v3 34 | 35 | - name: Set node 36 | uses: actions/setup-node@v3 37 | with: 38 | node-version: 18.x 39 | cache: yarn 40 | 41 | - name: Install 42 | run: yarn 43 | 44 | - name: Typecheck 45 | run: yarn typecheck 46 | 47 | test: 48 | runs-on: ${{ matrix.os }} 49 | 50 | strategy: 51 | matrix: 52 | node: [16.x, 18.x] 53 | os: [ubuntu-latest, windows-latest, macos-latest] 54 | fail-fast: false 55 | 56 | steps: 57 | - uses: actions/checkout@v3 58 | 59 | - name: Set node ${{ matrix.node }} 60 | uses: actions/setup-node@v3 61 | with: 62 | node-version: ${{ matrix.node }} 63 | cache: yarn 64 | 65 | - name: Install 66 | run: yarn 67 | 68 | - name: Build 69 | run: yarn build 70 | 71 | - name: Test 72 | run: yarn test 73 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | permissions: 4 | contents: write 5 | 6 | on: 7 | push: 8 | tags: 9 | - 'v*' 10 | 11 | jobs: 12 | release: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v3 16 | with: 17 | fetch-depth: 0 18 | 19 | - name: Set node 20 | uses: actions/setup-node@v3 21 | with: 22 | node-version: 18.x 23 | cache: yarn 24 | 25 | - run: npx changelogithub 26 | env: 27 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .idea 4 | 5 | package-lock.json 6 | yarn-error.log -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | ignore-workspace-root-check=true -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "prettier.enable": false, 3 | "editor.formatOnSave": true, 4 | "editor.codeActionsOnSave": { 5 | "source.fixAll.eslint": "explicit" 6 | }, 7 | "editor.tabSize": 2, 8 | "cSpell.words": [ 9 | "zodock" 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Magomed Chemurziev 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Zodock 2 | 3 | ![npm](https://img.shields.io/npm/v/zodock?color=2f68b7) 4 | ![npm bundle size](https://img.shields.io/bundlephobia/min/zodock?color=2f68b7) 5 | ![NPM](https://img.shields.io/npm/l/zodock) 6 | ![npm](https://img.shields.io/npm/dt/zodock) 7 | 8 | The mocking library for TypeScript-first schema validation [Zod](https://zod.dev/), creates a mock object based on the schema. It makes it easy to create mock data for testing purposes, to create mock data for the API request or response, and etc. 9 | 10 | ## Installation 11 | 12 | ```bash 13 | npm install -D zodock 14 | ``` 15 | 16 | ## Usage 17 | 18 | ```ts 19 | import { createMock } from 'zodock'; 20 | 21 | const schema = z.object({ 22 | name: z.string(), 23 | age: z.number(), 24 | }); 25 | 26 | createMock(schema); // { name: string, age: number } 27 | ``` 28 | 29 | ## Use cases 30 | 31 | ### Mocking data for testing 32 | 33 | ```ts 34 | import { createMock } from 'zodock'; 35 | 36 | const schema = z.object({ 37 | name: z.string(), 38 | age: z.number(), 39 | }); 40 | 41 | describe('test', () => { 42 | const mockSchema = createMock(schema); 43 | 44 | const apiMock = jest.fn().mockResolvedValue(mockSchema); 45 | 46 | it('should return mock data', async () => { 47 | const result = await apiMock(); 48 | 49 | expect(result).toEqual(mockSchema); 50 | }); 51 | }); 52 | ``` 53 | 54 | ### Mocking data for API request 55 | 56 | ```ts 57 | import { createMock } from 'zodock'; 58 | 59 | const schema = z.object({ 60 | name: z.string(), 61 | age: z.number(), 62 | }); 63 | 64 | const mockSchema = createMock(schema); 65 | 66 | export const api = { 67 | get: () => { 68 | return mockSchema; 69 | } 70 | }; 71 | ``` 72 | 73 | or you can imitate axios response 74 | 75 | ```ts 76 | import { createMock } from 'zodock'; 77 | 78 | const schema = z.object({ 79 | name: z.string(), 80 | age: z.number(), 81 | }); 82 | 83 | export const api = { 84 | get: () => { 85 | return new Promise(resolve => 86 | resolve({ 87 | status: 200, 88 | statusText: 'OK', 89 | headers: {}, 90 | data: createMock(schema), 91 | config: {}, 92 | }), 93 | ); 94 | } 95 | }; 96 | ``` 97 | 98 | ## TODO 99 | 100 | - ZodNever 101 | 102 | ## License 103 | 104 | [MIT](./LICENSE) License © 2023 [Magomed Chemurziev](https://github.com/ItMaga) -------------------------------------------------------------------------------- /build.config.ts: -------------------------------------------------------------------------------- 1 | import { defineBuildConfig } from 'unbuild'; 2 | 3 | export default defineBuildConfig({ 4 | entries: [ 5 | 'src/index', 6 | ], 7 | declaration: true, 8 | clean: true, 9 | rollup: { 10 | emitCJS: true, 11 | }, 12 | }); 13 | -------------------------------------------------------------------------------- /changelogithub.config.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | scopeMap: {}, 3 | types: { 4 | feat: { title: '🚀 Features' }, 5 | fix: { title: '🐞 Bug Fixes' }, 6 | perf: { title: '🏎 Performance' }, 7 | docs: { title: '📝 Documentation' }, 8 | test: { title: '🧪 Tests' }, 9 | refactor: { title: '🛠 Refactors' }, 10 | }, 11 | titles: { 12 | breakingChanges: '🚨 Breaking Changes', 13 | }, 14 | contributors: true, 15 | capitalize: true, 16 | group: true, 17 | }; 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "zodock", 3 | "type": "module", 4 | "version": "0.1.0", 5 | "description": "A library for generating mock data based on Zod schemas", 6 | "author": "ItMaga ", 7 | "license": "MIT", 8 | "homepage": "https://github.com/ItMaga/zodock#readme", 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/ItMaga/zodock.git" 12 | }, 13 | "bugs": "https://github.com/ItMaga/zodock/issues", 14 | "keywords": [ 15 | "zod", 16 | "mock", 17 | "faker", 18 | "fixture" 19 | ], 20 | "sideEffects": false, 21 | "exports": { 22 | ".": { 23 | "types": "./dist/index.d.ts", 24 | "require": "./dist/index.cjs", 25 | "import": "./dist/index.mjs" 26 | } 27 | }, 28 | "main": "./dist/index.cjs", 29 | "module": "./dist/index.mjs", 30 | "types": "./dist/index.d.ts", 31 | "typesVersions": { 32 | "*": { 33 | "*": [ 34 | "./dist/*", 35 | "./dist/index.d.ts" 36 | ] 37 | } 38 | }, 39 | "files": [ 40 | "dist" 41 | ], 42 | "scripts": { 43 | "build": "unbuild", 44 | "dev": "unbuild --stub", 45 | "lint": "eslint .", 46 | "prepublishOnly": "yarn build", 47 | "release": "bumpp && yarn publish", 48 | "test": "vitest --reporter verbose", 49 | "typecheck": "tsc --noEmit" 50 | }, 51 | "peerDependencies": { 52 | "zod": ">=3.0.0" 53 | }, 54 | "devDependencies": { 55 | "@antfu/eslint-config-ts": "^0.38.4", 56 | "@types/node": "^18.15.11", 57 | "bumpp": "^9.1.0", 58 | "eslint": "^8.37.0", 59 | "lint-staged": "^13.2.0", 60 | "simple-git-hooks": "^2.8.1", 61 | "typescript": "^5.0.4", 62 | "unbuild": "^2.0.0", 63 | "vite": "^4.2.1", 64 | "vitest": "^0.29.8", 65 | "zod": "^3.22.4" 66 | }, 67 | "simple-git-hooks": { 68 | "pre-commit": "yarn lint-staged" 69 | }, 70 | "lint-staged": { 71 | "*": "eslint --fix" 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/MockGenerator.ts: -------------------------------------------------------------------------------- 1 | import type { TypeOf, ZodFirstPartyTypeKind, z } from 'zod'; 2 | import StringGenerator from './generators/StringGenerator'; 3 | import type BaseGenerator from './generators/BaseGenerator'; 4 | import NumberGenerator from './generators/NumberGenerator'; 5 | import BooleanGenerator from './generators/BooleanGenerator'; 6 | import LiteralGenerator from './generators/LiteralGenerator'; 7 | import DateGenerator from './generators/DateGenerator'; 8 | import NullGenerator from './generators/NullGenerator'; 9 | import UndefinedGenerator from './generators/UndefinedGenerator'; 10 | import ObjectGenerator from './generators/ObjectGenerator'; 11 | import ArrayGenerator from './generators/ArrayGenerator'; 12 | import UnionGenerator from './generators/UnionGenerator'; 13 | import TuppleGenerator from './generators/TuppleGenerator'; 14 | import EffectsGenerator from './generators/EffectsGenerator'; 15 | import OptionalGenerator from './generators/OptionalGenerator'; 16 | import NaNGenerator from './generators/NaNGenerator'; 17 | import BigIntGenerator from './generators/BigIntGenerator'; 18 | import SymbolGenerator from './generators/SymbolGenerator'; 19 | import VoidGenerator from './generators/VoidGenerator'; 20 | import EnumGenerator from './generators/EnumGenerator'; 21 | import NativeEnumGenerator from './generators/NativeEnumGenerator'; 22 | import NullableGenerator from './generators/NullableGenerator'; 23 | import DiscriminatedUnionGenerator from './generators/DiscriminatedUnionGenerator'; 24 | import IntersectionGenerator from './generators/IntersectionGenerator'; 25 | import DefaultGenerator from './generators/DefaultGenerator'; 26 | import CatchGenerator from './generators/CatchGenerator'; 27 | import PromiseGenerator from './generators/PromiseGenerator'; 28 | import MapGenerator from './generators/MapGenerator'; 29 | import SetGenerator from './generators/SetGenerator'; 30 | import RecordGenerator from './generators/RecordGenerator'; 31 | import PipelineGenerator from './generators/PipelineGenerator'; 32 | import BrandedGenerator from './generators/BrandedGenerator'; 33 | import FunctionGenerator from './generators/FunctionGenerator'; 34 | import LazyGenerator from './generators/LazyGenerator'; 35 | import ReadonlyGenerator from './generators/ReadonlyGenerator'; 36 | import { DepthLimitError } from './errors/DepthLimitError'; 37 | 38 | const _schemasCache = new WeakMap(); 39 | export default class MockGenerator { 40 | private generator: BaseGenerator>; 41 | private schema: T; 42 | private readonly MAX_DEPTH = 3; 43 | 44 | constructor(schema: T) { 45 | this.schema = schema; 46 | 47 | const generatorMap: Partial> = { 48 | ZodString: StringGenerator, 49 | ZodNumber: NumberGenerator, 50 | ZodBoolean: BooleanGenerator, 51 | ZodLiteral: LiteralGenerator, 52 | ZodDate: DateGenerator, 53 | ZodNull: NullGenerator, 54 | ZodUndefined: UndefinedGenerator, 55 | ZodAny: StringGenerator, 56 | ZodUnknown: StringGenerator, 57 | ZodObject: ObjectGenerator, 58 | ZodArray: ArrayGenerator, 59 | ZodUnion: UnionGenerator, 60 | ZodTuple: TuppleGenerator, 61 | ZodEffects: EffectsGenerator, 62 | ZodOptional: OptionalGenerator, 63 | ZodNaN: NaNGenerator, 64 | ZodBigInt: BigIntGenerator, 65 | ZodSymbol: SymbolGenerator, 66 | ZodVoid: VoidGenerator, 67 | ZodEnum: EnumGenerator, 68 | ZodNativeEnum: NativeEnumGenerator, 69 | ZodNullable: NullableGenerator, 70 | ZodDiscriminatedUnion: DiscriminatedUnionGenerator, 71 | ZodIntersection: IntersectionGenerator, 72 | ZodDefault: DefaultGenerator, 73 | ZodCatch: CatchGenerator, 74 | ZodPromise: PromiseGenerator, 75 | ZodMap: MapGenerator, 76 | ZodSet: SetGenerator, 77 | ZodRecord: RecordGenerator, 78 | ZodPipeline: PipelineGenerator, 79 | ZodBranded: BrandedGenerator, 80 | ZodFunction: FunctionGenerator, 81 | ZodLazy: LazyGenerator, 82 | ZodReadonly: ReadonlyGenerator, 83 | }; 84 | 85 | if (this.schema._def.typeName in generatorMap) { 86 | this.generator = new generatorMap[this.schema._def.typeName as ZodFirstPartyTypeKind](); 87 | return; 88 | } 89 | 90 | throw new TypeError(`Unsupported schema type: ${this.schema.constructor.name}`); 91 | } 92 | 93 | public generate(): z.infer { 94 | this.incrementRecursionCount(); 95 | 96 | try { 97 | const generated = this.generator.generate(this.schema); 98 | return generated; 99 | } 100 | finally { 101 | this.decrementRecursionCount(); 102 | } 103 | } 104 | 105 | private incrementRecursionCount(): void { 106 | const recursionCount = _schemasCache.get(this.schema) ?? 0; 107 | if (recursionCount > this.MAX_DEPTH) { 108 | throw new DepthLimitError(); 109 | } 110 | 111 | _schemasCache.set(this.schema, recursionCount + 1); 112 | } 113 | 114 | private decrementRecursionCount(): void { 115 | const recursionCount = _schemasCache.get(this.schema) ?? 0; 116 | _schemasCache.set(this.schema, recursionCount - 1); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/errors/DepthLimitError.ts: -------------------------------------------------------------------------------- 1 | export class DepthLimitError extends Error { 2 | constructor() { 3 | super('Depth limit reached'); 4 | this.name = 'DepthLimitError'; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/generators/ArrayGenerator.ts: -------------------------------------------------------------------------------- 1 | import type { z } from 'zod'; 2 | import MockGenerator from '../MockGenerator'; 3 | import { DepthLimitError } from '../errors/DepthLimitError'; 4 | import type BaseGenerator from './BaseGenerator'; 5 | 6 | const DEFAULT_LENGTH = 3; 7 | export default class ArrayGenerator> implements BaseGenerator { 8 | public generate(schema: T) { 9 | let length = DEFAULT_LENGTH; 10 | if (schema._def.minLength) { 11 | length = schema._def.minLength.value + 1; 12 | } 13 | if (schema._def.maxLength) { 14 | length = schema._def.maxLength.value - 1; 15 | } 16 | if (schema._def.exactLength) { 17 | length = schema._def.exactLength.value; 18 | } 19 | 20 | try { 21 | const mockGenerator = new MockGenerator(schema.element); 22 | return Array.from({ length }, () => mockGenerator.generate()); 23 | } 24 | catch (e) { 25 | if (e instanceof DepthLimitError) { 26 | return []; 27 | } 28 | throw e; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/generators/BaseGenerator.ts: -------------------------------------------------------------------------------- 1 | import type { z } from 'zod'; 2 | 3 | export default abstract class BaseGenerator { 4 | public abstract generate(schema: T): z.infer; 5 | } 6 | -------------------------------------------------------------------------------- /src/generators/BigIntGenerator.ts: -------------------------------------------------------------------------------- 1 | import type { z } from 'zod'; 2 | import type BaseGenerator from './BaseGenerator'; 3 | 4 | export default class BigIntGenerator implements BaseGenerator { 5 | public generate(schema: T) { 6 | let bigInt: z.infer = BigInt(1); 7 | 8 | if (schema._def.checks && schema._def.checks.length > 0) { 9 | for (const check of schema._def.checks) { 10 | switch (check.kind) { 11 | case 'min': 12 | bigInt = check.value + BigInt(1); 13 | break; 14 | case 'max': 15 | bigInt = check.value - BigInt(1); 16 | break; 17 | case 'multipleOf': 18 | bigInt = check.value; 19 | break; 20 | } 21 | } 22 | } 23 | 24 | return bigInt; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/generators/BooleanGenerator.ts: -------------------------------------------------------------------------------- 1 | import type { z } from 'zod'; 2 | import type BaseGenerator from './BaseGenerator'; 3 | 4 | export default class BooleanGenerator implements BaseGenerator { 5 | public generate() { 6 | return Math.random() >= 0.5; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/generators/BrandedGenerator.ts: -------------------------------------------------------------------------------- 1 | import type { z } from 'zod'; 2 | import MockGenerator from '../MockGenerator'; 3 | import type BaseGenerator from './BaseGenerator'; 4 | 5 | export default class BrandedGenerator> implements BaseGenerator { 6 | public generate(schema: T): z.infer { 7 | const mockGenerator = new MockGenerator(schema.unwrap()); 8 | return mockGenerator.generate(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/generators/CatchGenerator.ts: -------------------------------------------------------------------------------- 1 | import type { z } from 'zod'; 2 | import MockGenerator from '../MockGenerator'; 3 | import type BaseGenerator from './BaseGenerator'; 4 | 5 | export default class CatchGenerator> implements BaseGenerator { 6 | public generate(schema: T) { 7 | const mockGenerator = new MockGenerator(schema._def.innerType); 8 | return mockGenerator.generate(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/generators/DateGenerator.ts: -------------------------------------------------------------------------------- 1 | import type { z } from 'zod'; 2 | import type BaseGenerator from './BaseGenerator'; 3 | 4 | export default class DateGenerator implements BaseGenerator { 5 | public generate(schema: T) { 6 | let date: z.infer = new Date(); 7 | 8 | if (schema._def.checks && schema._def.checks.length > 0) { 9 | for (const check of schema._def.checks) { 10 | switch (check.kind) { 11 | case 'min': 12 | date = new Date(check.value + 1); 13 | break; 14 | case 'max': 15 | date = new Date(check.value - 1); 16 | break; 17 | } 18 | } 19 | } 20 | 21 | return date; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/generators/DefaultGenerator.ts: -------------------------------------------------------------------------------- 1 | import type { z } from 'zod'; 2 | import type BaseGenerator from './BaseGenerator'; 3 | 4 | export default class DefaultGenerator> implements BaseGenerator { 5 | generate(schema: T) { 6 | return schema._def.defaultValue(); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/generators/DiscriminatedUnionGenerator.ts: -------------------------------------------------------------------------------- 1 | import type { ZodDiscriminatedUnionOption, z } from 'zod'; 2 | import MockGenerator from '../MockGenerator'; 3 | import type BaseGenerator from './BaseGenerator'; 4 | 5 | export default class DiscriminatedUnionGenerator[]>> implements BaseGenerator { 6 | public generate(schema: T) { 7 | const { optionsMap } = schema._def; 8 | const keys = Array.from(optionsMap.keys()); 9 | const randomKey = keys[Math.floor(Math.random() * keys.length)]; 10 | 11 | const mockGenerator = new MockGenerator(optionsMap.get(randomKey)!); 12 | return mockGenerator.generate(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/generators/EffectsGenerator.ts: -------------------------------------------------------------------------------- 1 | import type { z } from 'zod'; 2 | import MockGenerator from '../MockGenerator'; 3 | import type BaseGenerator from './BaseGenerator'; 4 | 5 | export default class EffectsGenerator> implements BaseGenerator { 6 | public generate(schema: T) { 7 | if (schema._def.effect.type === 'refinement') { 8 | schema._def.effect.refinement = () => true; 9 | } 10 | 11 | const mockGenerator = new MockGenerator(schema.innerType()); 12 | return mockGenerator.generate(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/generators/EnumGenerator.ts: -------------------------------------------------------------------------------- 1 | import type { z } from 'zod'; 2 | import type BaseGenerator from './BaseGenerator'; 3 | 4 | export default class EnumGenerator> implements BaseGenerator { 5 | public generate(schema: T) { 6 | const { values } = schema._def; 7 | return values[Math.floor(Math.random() * values.length)]; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/generators/FunctionGenerator.ts: -------------------------------------------------------------------------------- 1 | import type { z } from 'zod'; 2 | import MockGenerator from '../MockGenerator'; 3 | import type BaseGenerator from './BaseGenerator'; 4 | 5 | export default class FunctionGenerator, z.ZodTypeAny>> implements BaseGenerator { 6 | public generate(schema: T): z.infer { 7 | const mockGenerator = new MockGenerator(schema._def.returns); 8 | return () => mockGenerator.generate(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/generators/IntersectionGenerator.ts: -------------------------------------------------------------------------------- 1 | import type { z } from 'zod'; 2 | import MockGenerator from '../MockGenerator'; 3 | import type BaseGenerator from './BaseGenerator'; 4 | 5 | export default class IntersectionGenerator> implements BaseGenerator { 6 | public generate(schema: T) { 7 | const { _def: leftDef } = schema._def.left; 8 | const { _def: rightDef } = schema._def.right; 9 | 10 | if ('typeName' in leftDef && 'typeName' in rightDef) { 11 | if (leftDef.typeName === 'ZodUnion' && rightDef.typeName === 'ZodUnion') { 12 | const sharedOptions = leftDef.options.filter((leftOption: z.ZodTypeAny) => { 13 | return rightDef.options.some((rightOption: z.ZodTypeAny) => rightOption._def.typeName === leftOption._def.typeName); 14 | }); 15 | const randomIndex = Math.floor(Math.random() * sharedOptions.length); 16 | const randomOption = sharedOptions[randomIndex]; 17 | 18 | const mockGenerator = new MockGenerator(randomOption); 19 | return mockGenerator.generate(); 20 | } 21 | } 22 | 23 | const leftGenerated = new MockGenerator(schema._def.left).generate(); 24 | const rightGenerated = new MockGenerator(schema._def.right).generate(); 25 | const merged = this.mergeValues(leftGenerated, rightGenerated); 26 | return merged; 27 | } 28 | 29 | private mergeValues(a: any, b: any): any { 30 | if (Array.isArray(a) && Array.isArray(b)) { 31 | const newArray = []; 32 | for (let i = 0; i < a.length; i++) { 33 | newArray.push(this.mergeValues(a[i], b[i])); 34 | } 35 | return newArray; 36 | } 37 | else if (a instanceof Date && b instanceof Date) { 38 | return a; 39 | } 40 | else if (typeof a === 'object' && typeof b === 'object') { 41 | return { ...a, ...b }; 42 | } 43 | else { 44 | return a; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/generators/LazyGenerator.ts: -------------------------------------------------------------------------------- 1 | import type { z } from 'zod'; 2 | import MockGenerator from '../MockGenerator'; 3 | import type BaseGenerator from './BaseGenerator'; 4 | 5 | export default class LazyGenerator> implements BaseGenerator { 6 | public generate(schema: T): z.infer { 7 | const mockGenerator = new MockGenerator(schema._def.getter()); 8 | return mockGenerator.generate(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/generators/LiteralGenerator.ts: -------------------------------------------------------------------------------- 1 | import type { z } from 'zod'; 2 | import type BaseGenerator from './BaseGenerator'; 3 | 4 | export default class LiteralGenerator> implements BaseGenerator { 5 | public generate(schema: T) { 6 | return schema._def.value; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/generators/MapGenerator.ts: -------------------------------------------------------------------------------- 1 | import type { z } from 'zod'; 2 | import MockGenerator from '../MockGenerator'; 3 | import type BaseGenerator from './BaseGenerator'; 4 | 5 | export default class MapGenerator implements BaseGenerator { 6 | public generate(schema: T) { 7 | const keyGenerator = new MockGenerator(schema._def.keyType); 8 | const generatedKey = keyGenerator.generate(); 9 | 10 | const valueGenerator = new MockGenerator(schema._def.valueType); 11 | const generatedValue = valueGenerator.generate(); 12 | 13 | return new Map([[generatedKey, generatedValue]]); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/generators/NaNGenerator.ts: -------------------------------------------------------------------------------- 1 | import type { z } from 'zod'; 2 | import type BaseGenerator from './BaseGenerator'; 3 | 4 | export default class NaNGenerator implements BaseGenerator { 5 | public generate(): number { 6 | return NaN; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/generators/NativeEnumGenerator.ts: -------------------------------------------------------------------------------- 1 | import type { z } from 'zod'; 2 | import type BaseGenerator from './BaseGenerator'; 3 | 4 | export default class NativeEnumGenerator> implements BaseGenerator { 5 | public generate(schema: T) { 6 | const values = Object.values(schema._def.values); 7 | return values[Math.floor(Math.random() * values.length)] as z.infer; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/generators/NullGenerator.ts: -------------------------------------------------------------------------------- 1 | import type { z } from 'zod'; 2 | import type BaseGenerator from './BaseGenerator'; 3 | 4 | export default class NullGenerator implements BaseGenerator { 5 | public generate() { 6 | return null; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/generators/NullableGenerator.ts: -------------------------------------------------------------------------------- 1 | import type { z } from 'zod'; 2 | import MockGenerator from '../MockGenerator'; 3 | import type BaseGenerator from './BaseGenerator'; 4 | 5 | export default class NullableGenerator> implements BaseGenerator { 6 | public generate(schema: T) { 7 | if (Math.random() > 0.5) { 8 | return null; 9 | } 10 | 11 | const generator = new MockGenerator(schema._def.innerType); 12 | return generator.generate(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/generators/NumberGenerator.ts: -------------------------------------------------------------------------------- 1 | import type { z } from 'zod'; 2 | import type BaseGenerator from './BaseGenerator'; 3 | 4 | export default class NumberGenerator implements BaseGenerator { 5 | public generate(schema: T) { 6 | let number: z.infer = this.randomInt(); 7 | 8 | if (schema._def.checks && schema._def.checks.length > 0) { 9 | for (const check of schema._def.checks) { 10 | switch (check.kind) { 11 | case 'int': 12 | case 'finite': 13 | number = this.randomInt(); 14 | break; 15 | case 'min': 16 | number = check.value + 1; 17 | break; 18 | case 'max': 19 | number = check.value - 1; 20 | break; 21 | case 'multipleOf': 22 | number = check.value; 23 | break; 24 | } 25 | } 26 | } 27 | 28 | return number; 29 | } 30 | 31 | private randomInt() { 32 | return Math.floor(Math.random() * 1000); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/generators/ObjectGenerator.ts: -------------------------------------------------------------------------------- 1 | import type { ZodRawShape, z } from 'zod'; 2 | import MockGenerator from '../MockGenerator'; 3 | import { DepthLimitError } from '../errors/DepthLimitError'; 4 | import type BaseGenerator from './BaseGenerator'; 5 | 6 | export default class ObjectGenerator> implements BaseGenerator { 7 | public generate(schema: U) { 8 | const generated: z.infer = {} as z.infer; 9 | Object.entries(schema._def.shape()).forEach(([key, value]) => { 10 | try { 11 | const mockGenerator = new MockGenerator(value); 12 | generated[key as keyof z.infer] = mockGenerator.generate(); 13 | } 14 | catch (e) { 15 | if (e instanceof DepthLimitError) { 16 | return; 17 | } 18 | throw e; 19 | } 20 | }); 21 | 22 | return generated; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/generators/OptionalGenerator.ts: -------------------------------------------------------------------------------- 1 | import type { z } from 'zod'; 2 | import type BaseGenerator from './BaseGenerator'; 3 | 4 | export default class OptionalGenerator> implements BaseGenerator { 5 | public generate() { 6 | return undefined; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/generators/PipelineGenerator.ts: -------------------------------------------------------------------------------- 1 | import type { z } from 'zod'; 2 | import MockGenerator from '../MockGenerator'; 3 | import type BaseGenerator from './BaseGenerator'; 4 | 5 | export default class PipelineGenerator> implements BaseGenerator { 6 | public generate(schema: T): z.TypeOf { 7 | const { out: outSchema } = schema._def; 8 | const outGenerated = new MockGenerator(outSchema).generate(); 9 | return outGenerated; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/generators/PromiseGenerator.ts: -------------------------------------------------------------------------------- 1 | import type { z } from 'zod'; 2 | import MockGenerator from '../MockGenerator'; 3 | import type BaseGenerator from './BaseGenerator'; 4 | 5 | export default class PromiseGenerator> implements BaseGenerator { 6 | public generate(schema: T) { 7 | const mockGenerator = new MockGenerator(schema._def.type); 8 | const generated = mockGenerator.generate(); 9 | return Promise.resolve(generated); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/generators/ReadonlyGenerator.ts: -------------------------------------------------------------------------------- 1 | import type { ZodReadonly, ZodTypeAny } from 'zod'; 2 | import MockGenerator from '../MockGenerator'; 3 | import type BaseGenerator from './BaseGenerator'; 4 | 5 | export default class ReadonlyGenerator> implements BaseGenerator { 6 | public generate(schema: U) { 7 | const mockGenerator = new MockGenerator(schema._def.innerType); 8 | return Object.freeze(mockGenerator.generate()); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/generators/RecordGenerator.ts: -------------------------------------------------------------------------------- 1 | import type { z } from 'zod'; 2 | import MockGenerator from '../MockGenerator'; 3 | import type BaseGenerator from './BaseGenerator'; 4 | 5 | export default class RecordGenerator implements BaseGenerator { 6 | public generate(schema: T) { 7 | const keyGenerated = new MockGenerator(schema._def.keyType).generate(); 8 | const valueGenerated = new MockGenerator(schema._def.valueType).generate(); 9 | 10 | return { [keyGenerated]: valueGenerated }; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/generators/SetGenerator.ts: -------------------------------------------------------------------------------- 1 | import type { z } from 'zod'; 2 | import MockGenerator from '../MockGenerator'; 3 | import type BaseGenerator from './BaseGenerator'; 4 | 5 | export default class SetGenerator implements BaseGenerator { 6 | public generate(schema: T) { 7 | const valueGenerator = new MockGenerator(schema._def.valueType); 8 | const generatedValue = valueGenerator.generate(); 9 | 10 | if (schema._def.minSize) { 11 | const set = new Set([generatedValue]); 12 | while (set.size < schema._def.minSize.value) { 13 | set.add(valueGenerator.generate()); 14 | } 15 | return set; 16 | } 17 | else if (schema._def.maxSize) { 18 | const set = new Set(); 19 | while (set.size < schema._def.maxSize.value) { 20 | set.add(valueGenerator.generate()); 21 | } 22 | return set; 23 | } 24 | 25 | return new Set([generatedValue]); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/generators/StringGenerator.ts: -------------------------------------------------------------------------------- 1 | import type { z } from 'zod'; 2 | import type BaseGenerator from './BaseGenerator'; 3 | 4 | export default class StringGenerator implements BaseGenerator { 5 | public generate(schema: T) { 6 | let string: z.infer = this.getRandomString(); 7 | 8 | if (schema._def.checks && schema._def.checks.length > 0) { 9 | for (const check of schema._def.checks) { 10 | switch (check.kind) { 11 | case 'uuid': 12 | string = this.getRandomUUID(); 13 | break; 14 | case 'email': 15 | string = this.getRandomEmail(); 16 | break; 17 | case 'datetime': 18 | string = new Date().toISOString(); 19 | break; 20 | case 'url': 21 | string = `https://${this.getRandomString()}.com`; 22 | break; 23 | case 'emoji': 24 | string = '😀'; 25 | break; 26 | case 'ip': 27 | string = this.getRandomIP(check.version!); 28 | break; 29 | case 'includes': 30 | case 'startsWith': 31 | string = `${check.value}${string}`; 32 | break; 33 | case 'endsWith': 34 | string = `${string}${check.value}`; 35 | break; 36 | case 'min': 37 | case 'max': 38 | case 'length': 39 | string = this.getRandomString().substring(0, check.value); 40 | break; 41 | } 42 | } 43 | } 44 | 45 | return string; 46 | } 47 | 48 | public getRandomEmail(): z.infer { 49 | const email = `${this.getRandomString()}@${this.getRandomString()}.com`; 50 | return email; 51 | } 52 | 53 | public getRandomString(): string { 54 | return Array.from({ length: 50 }, () => Math.floor(Math.random() * 36).toString(36)).join(''); 55 | } 56 | 57 | public getRandomUUID(): string { 58 | return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => { 59 | const r = (Math.random() * 16) | 0; 60 | const v = c === 'x' ? r : (r & 0x3) | 0x8; 61 | return v.toString(16); 62 | }); 63 | } 64 | 65 | public getRandomIP(version: 'v4' | 'v6'): string { 66 | if (version === 'v4') { 67 | return [0, 0, 0, 0].map(() => Math.floor(Math.random() * 256)).join('.'); 68 | } 69 | return [0, 0, 0, 0, 0, 0, 0, 0].map(() => Math.floor(Math.random() * 65536).toString(16)).join(':'); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/generators/SymbolGenerator.ts: -------------------------------------------------------------------------------- 1 | import type { z } from 'zod'; 2 | import type BaseGenerator from './BaseGenerator'; 3 | 4 | export default class SymbolGenerator implements BaseGenerator { 5 | public generate() { 6 | return Symbol('symbol'); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/generators/TuppleGenerator.ts: -------------------------------------------------------------------------------- 1 | import type { z } from 'zod'; 2 | import MockGenerator from '../MockGenerator'; 3 | import type BaseGenerator from './BaseGenerator'; 4 | 5 | export default class TuppleGenerator implements BaseGenerator { 6 | public generate(schema: T) { 7 | return schema._def.items.map((item) => { 8 | const mockGenerator = new MockGenerator(item); 9 | return mockGenerator.generate(); 10 | }) as z.infer; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/generators/UndefinedGenerator.ts: -------------------------------------------------------------------------------- 1 | import type { z } from 'zod'; 2 | import type BaseGenerator from './BaseGenerator'; 3 | 4 | export default class UndefinedGenerator implements BaseGenerator { 5 | public generate() { 6 | return undefined; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/generators/UnionGenerator.ts: -------------------------------------------------------------------------------- 1 | import type { z } from 'zod'; 2 | import MockGenerator from '../MockGenerator'; 3 | import type BaseGenerator from './BaseGenerator'; 4 | 5 | export default class UnionGenerator> implements BaseGenerator { 6 | public generate(schema: T) { 7 | const { options } = schema._def; 8 | const randomIndex = Math.floor(Math.random() * options.length); 9 | const randomOption = options[randomIndex]; 10 | 11 | const mockGenerator = new MockGenerator(randomOption); 12 | return mockGenerator.generate(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/generators/VoidGenerator.ts: -------------------------------------------------------------------------------- 1 | import type { z } from 'zod'; 2 | import type BaseGenerator from './BaseGenerator'; 3 | 4 | export default class VoidGenerator implements BaseGenerator { 5 | public generate() { 6 | void 0; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import type { z } from 'zod'; 2 | import MockGenerator from './MockGenerator'; 3 | 4 | function createMock(schema: Schema): z.infer { 5 | if (typeof schema === 'function') { 6 | throw new TypeError('You must pass a schema to createMock'); 7 | } 8 | 9 | const mockGenerator = new MockGenerator(schema); 10 | return schema.parse(mockGenerator.generate()); 11 | } 12 | 13 | export { createMock }; 14 | -------------------------------------------------------------------------------- /tests/anyValues.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test } from 'vitest'; 2 | import { z } from 'zod'; 3 | import { expect } from './utils/expect'; 4 | 5 | describe('Any values', () => { 6 | test('any', () => { 7 | const schema = z.any(); 8 | 9 | expect(schema); 10 | }); 11 | test('unknown', () => { 12 | const schema = z.unknown(); 13 | 14 | expect(schema); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /tests/array.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test } from 'vitest'; 2 | import { z } from 'zod'; 3 | import { expect } from './utils/expect'; 4 | 5 | describe('Array', () => { 6 | test('base', () => { 7 | const schema = z.array(z.string()); 8 | 9 | expect(schema); 10 | }); 11 | test('alternatives', () => { 12 | const schema = z.array(z.string().or(z.number())); 13 | 14 | expect(schema); 15 | }); 16 | test('nonempty', () => { 17 | const schema = z.array(z.string()).nonempty(); 18 | 19 | expect(schema); 20 | }); 21 | test('min', () => { 22 | const schema = z.array(z.string()).min(10); 23 | 24 | expect(schema); 25 | }); 26 | test('max', () => { 27 | const schema = z.array(z.string()).max(10); 28 | 29 | expect(schema); 30 | }); 31 | test('length', () => { 32 | const schema = z.array(z.string()).length(10); 33 | 34 | expect(schema); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /tests/bigInt.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test } from 'vitest'; 2 | import { z } from 'zod'; 3 | import { expect } from './utils/expect'; 4 | 5 | describe('BigInt', () => { 6 | test('base', () => { 7 | const schema = z.bigint(); 8 | 9 | expect(schema); 10 | }); 11 | test('min or gt/gte', () => { 12 | const schema = z.bigint().min(10n); 13 | 14 | expect(schema); 15 | }); 16 | test('max or lt/lte', () => { 17 | const schema = z.bigint().max(10n); 18 | 19 | expect(schema); 20 | }); 21 | test('positive', () => { 22 | const schema = z.bigint().positive(); 23 | 24 | expect(schema); 25 | }); 26 | test('nonpositive', () => { 27 | const schema = z.bigint().nonpositive(); 28 | 29 | expect(schema); 30 | }); 31 | test('negative', () => { 32 | const schema = z.bigint().negative(); 33 | 34 | expect(schema); 35 | }); 36 | test('nonnegative', () => { 37 | const schema = z.bigint().nonnegative(); 38 | 39 | expect(schema); 40 | }); 41 | test('multipleOf', () => { 42 | const schema = z.bigint().multipleOf(10n); 43 | 44 | expect(schema); 45 | }); 46 | }); 47 | -------------------------------------------------------------------------------- /tests/boolean.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test } from 'vitest'; 2 | import { z } from 'zod'; 3 | import { expect } from './utils/expect'; 4 | 5 | describe('Boolean', () => { 6 | test('base', () => { 7 | const schema = z.boolean(); 8 | 9 | expect(schema); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /tests/branded.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test } from 'vitest'; 2 | import { z } from 'zod'; 3 | import { expect } from './utils/expect'; 4 | 5 | describe('Branded', () => { 6 | test('string', () => { 7 | const schema = z.string().brand('myBrand'); 8 | 9 | expect(schema); 10 | }); 11 | test('object', () => { 12 | const schema = z.object({ 13 | foo: z.string().brand('brandKey'), 14 | }).brand('brandObject'); 15 | 16 | expect(schema); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /tests/catch.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test } from 'vitest'; 2 | import { z } from 'zod'; 3 | import { expect } from './utils/expect'; 4 | 5 | describe('Catch', () => { 6 | test('string', () => { 7 | const schema = z.string().catch('error'); 8 | 9 | expect(schema); 10 | }); 11 | test('number', () => { 12 | const schema = z.number().catch(1); 13 | 14 | expect(schema); 15 | }); 16 | test('boolean', () => { 17 | const schema = z.boolean().catch(true); 18 | 19 | expect(schema); 20 | }); 21 | test('date', () => { 22 | const schema = z.date().catch(new Date()); 23 | 24 | expect(schema); 25 | }); 26 | test('object', () => { 27 | const schema = z.object({ foo: z.string().catch('') }).catch({ foo: '' }); 28 | 29 | expect(schema); 30 | }); 31 | test('array', () => { 32 | const schema = z.array(z.string().catch('')).catch(['']); 33 | 34 | expect(schema); 35 | }); 36 | test('union', () => { 37 | const schema = z.union([z.string().catch(''), z.number().catch(1)]).catch(''); 38 | 39 | expect(schema); 40 | }); 41 | test('tuple', () => { 42 | const schema = z.tuple([z.string().catch(''), z.number().catch(1)]).catch(['', 1]); 43 | 44 | expect(schema); 45 | }); 46 | test('optional', () => { 47 | const schema = z.string().optional().catch(''); 48 | 49 | expect(schema); 50 | }); 51 | test('nullable', () => { 52 | const schema = z.string().nullable().catch(''); 53 | 54 | expect(schema); 55 | }); 56 | test('undefined', () => { 57 | const schema = z.undefined().catch(undefined); 58 | 59 | expect(schema); 60 | }); 61 | }); 62 | -------------------------------------------------------------------------------- /tests/date.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test } from 'vitest'; 2 | import { z } from 'zod'; 3 | import { expect } from './utils/expect'; 4 | 5 | describe('Date', () => { 6 | test('base', () => { 7 | const schema = z.date(); 8 | 9 | expect(schema); 10 | }); 11 | test('min', () => { 12 | const now = new Date(); 13 | const endOfTomorrow = new Date(0); 14 | endOfTomorrow.setFullYear(now.getFullYear(), now.getMonth(), now.getDate() + 1); 15 | endOfTomorrow.setHours(23, 59, 59, 999); 16 | 17 | const schema = z.date().min(endOfTomorrow); 18 | 19 | expect(schema); 20 | }); 21 | test('max', () => { 22 | const now = new Date(); 23 | const endOfYesterday = new Date(0); 24 | endOfYesterday.setFullYear(now.getFullYear(), now.getMonth(), now.getDate() - 1); 25 | endOfYesterday.setHours(23, 59, 59, 999); 26 | 27 | const schema = z.date().max(endOfYesterday); 28 | 29 | expect(schema); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /tests/default.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test } from 'vitest'; 2 | import { z } from 'zod'; 3 | import { expect } from './utils/expect'; 4 | 5 | describe('Default', () => { 6 | test('string', () => { 7 | const schema = z.string().default('foo'); 8 | 9 | expect(schema); 10 | }); 11 | test('number', () => { 12 | const schema = z.number().default(42); 13 | 14 | expect(schema); 15 | }); 16 | test('boolean', () => { 17 | const schema = z.boolean().default(true); 18 | 19 | expect(schema); 20 | }); 21 | test('date', () => { 22 | const schema = z.date().default(new Date()); 23 | 24 | expect(schema); 25 | }); 26 | test('object', () => { 27 | const schema = z.object({ foo: z.string().default('foo') }).default({ foo: 'foo' }); 28 | 29 | expect(schema); 30 | }); 31 | test('array', () => { 32 | const schema = z.array(z.string()).default(['foo']); 33 | 34 | expect(schema); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /tests/discriminatedUnion.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test } from 'vitest'; 2 | import { z } from 'zod'; 3 | import { expect } from './utils/expect'; 4 | 5 | describe('Discriminated Union', () => { 6 | test('base', () => { 7 | const schema = z.discriminatedUnion('status', [ 8 | z.object({ status: z.literal('success'), data: z.string() }), 9 | z.object({ status: z.literal('failed'), error: z.number() }), 10 | ]); 11 | 12 | expect(schema); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /tests/effects.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test, expect as viExpect } from 'vitest'; 2 | import { z } from 'zod'; 3 | import { createMock } from '../src'; 4 | import { expect } from './utils/expect'; 5 | 6 | describe('Effects', () => { 7 | test('transform string', () => { 8 | const schema = z.string().transform(val => val.toUpperCase()); 9 | 10 | expect(schema); 11 | }); 12 | test('transform object', () => { 13 | const schema = z.object({ active: z.boolean() }).transform(val => ({ isActive: val.active })); 14 | 15 | expect(schema.sourceType()); 16 | }); 17 | test('transform object keys', () => { 18 | const schema = z.object({ active: z.boolean().transform(val => val ? 'yes' : 'no'), date: z.date().transform(val => val.toISOString()) }).transform(val => val); 19 | 20 | viExpect(createMock(schema).active).oneOf(['yes', 'no']); 21 | viExpect(createMock(schema).date).toMatch(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z$/); 22 | }); 23 | test('transform array', () => { 24 | const schema = z.array(z.string()).transform(val => val.join('')); 25 | 26 | expect(schema.sourceType()); 27 | }); 28 | test('multiple transform', () => { 29 | const schemaBase = z.object({ 30 | string: z.string(), 31 | data: z.object({ foo: z.string(), bar: z.string() }).transform(({ foo, bar }) => ({ bar, baz: foo })), 32 | }); 33 | const schemaExtended = schemaBase 34 | .extend({ type: z.string(), forTransform: z.string() }) 35 | .transform(({ forTransform, ...rest }) => ({ transformed: forTransform, ...rest })); 36 | 37 | viExpect(createMock(schemaExtended).transformed).toBeDefined(); 38 | viExpect(createMock(schemaExtended).data.baz).toBeDefined(); 39 | }); 40 | 41 | test('refine', () => { 42 | const isValidId = (id: string): boolean => id.length > 100; 43 | const schema = z.string().refine(isValidId); 44 | 45 | expect(schema.sourceType()); 46 | }); 47 | 48 | test('preprocess', () => { 49 | const schema = z.preprocess(val => String(val), z.string()); 50 | 51 | expect(schema.sourceType()); 52 | }); 53 | }); 54 | -------------------------------------------------------------------------------- /tests/empty.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test } from 'vitest'; 2 | import { z } from 'zod'; 3 | import { expect } from './utils/expect'; 4 | 5 | describe('Empty types', () => { 6 | test('null', () => { 7 | const schema = z.null(); 8 | 9 | expect(schema); 10 | }); 11 | test('undefined', () => { 12 | const schema = z.undefined(); 13 | 14 | expect(schema); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /tests/enum.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test } from 'vitest'; 2 | import { z } from 'zod'; 3 | import { expect } from './utils/expect'; 4 | 5 | describe('Enum', () => { 6 | test('base', () => { 7 | const schema = z.enum(['a', 'b', 'c']); 8 | 9 | expect(schema); 10 | }); 11 | test('by variable', () => { 12 | const values = ['a', 'b', 'c'] as const; 13 | const schema = z.enum(values); 14 | 15 | expect(schema); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /tests/function.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test } from 'vitest'; 2 | import { z } from 'zod'; 3 | import { expect } from './utils/expect'; 4 | 5 | describe('Function', () => { 6 | test('base', () => { 7 | const schema = z.function(); 8 | 9 | expect(schema); 10 | }); 11 | test('with args as param', () => { 12 | const schema = z.function(z.tuple([z.string(), z.number()]), z.boolean()); 13 | 14 | expect(schema); 15 | }); 16 | test('with args as method', () => { 17 | const schema = z.function().args(z.string(), z.number()); 18 | 19 | expect(schema); 20 | }); 21 | test('with returns as param', () => { 22 | const schema = z.function(z.tuple([z.string(), z.number()]), z.boolean()); 23 | 24 | expect(schema); 25 | }); 26 | test('with returns as method', () => { 27 | const schema = z.function().returns(z.boolean()); 28 | 29 | expect(schema); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /tests/intersection.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test } from 'vitest'; 2 | import { z } from 'zod'; 3 | import { expect } from './utils/expect'; 4 | 5 | describe('Intersection', () => { 6 | test('object', () => { 7 | const obj1 = z.object({ name: z.string() }); 8 | const obj2 = z.object({ role: z.string() }); 9 | 10 | const schema = z.intersection(obj1, obj2); 11 | 12 | expect(schema); 13 | }); 14 | test('array', () => { 15 | const arr1 = z.array(z.string()); 16 | const arr2 = z.array(z.string()); 17 | 18 | const schema = z.intersection(arr1, arr2); 19 | 20 | expect(schema); 21 | }); 22 | test('date', () => { 23 | const date1 = z.date(); 24 | const date2 = z.date(); 25 | 26 | const schema = z.intersection(date1, date2); 27 | 28 | expect(schema); 29 | }); 30 | test('union', () => { 31 | const union1 = z.union([z.number(), z.string()]); 32 | const union2 = z.union([z.number(), z.boolean()]); 33 | const schema = z.intersection(union1, union2); 34 | 35 | expect(schema); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /tests/lazy.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test } from 'vitest'; 2 | import { z } from 'zod'; 3 | import { expect } from './utils/expect'; 4 | 5 | describe('Lazy', () => { 6 | test('primitive', () => { 7 | const schema = z.lazy(() => z.string()); 8 | 9 | expect(schema); 10 | }); 11 | 12 | test('recursive', () => { 13 | const baseCategorySchema = z.object({ name: z.string() }); 14 | type Category = z.infer & { 15 | subcategories: Category[] 16 | }; 17 | const categorySchema: z.ZodType = baseCategorySchema.extend({ 18 | subcategories: z.array(z.lazy(() => categorySchema)), 19 | }); 20 | 21 | expect(categorySchema); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /tests/literal.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test } from 'vitest'; 2 | import { z } from 'zod'; 3 | import { expect } from './utils/expect'; 4 | 5 | describe('Literal', () => { 6 | test('string', () => { 7 | const schema = z.literal('literal'); 8 | 9 | expect(schema); 10 | }); 11 | test('number', () => { 12 | const schema = z.literal(1); 13 | 14 | expect(schema); 15 | }); 16 | test('boolean', () => { 17 | const schema = z.literal(true); 18 | 19 | expect(schema); 20 | }); 21 | test('null', () => { 22 | const schema = z.literal(null); 23 | 24 | expect(schema); 25 | }); 26 | test('undefined', () => { 27 | const schema = z.literal(undefined); 28 | 29 | expect(schema); 30 | }); 31 | test('bigint', () => { 32 | const schema = z.literal(1n); 33 | 34 | expect(schema); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /tests/map.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test } from 'vitest'; 2 | import { z } from 'zod'; 3 | import { expect } from './utils/expect'; 4 | 5 | describe('Map', () => { 6 | test('primitive', () => { 7 | const schema = z.map(z.string(), z.number()); 8 | 9 | expect(schema); 10 | }); 11 | test('object value', () => { 12 | const schema = z.map(z.string(), z.object({ foo: z.string() })); 13 | 14 | expect(schema); 15 | }); 16 | test('object key', () => { 17 | const schema = z.map(z.object({ foo: z.string() }), z.number()); 18 | 19 | expect(schema); 20 | }); 21 | test('array value', () => { 22 | const schema = z.map(z.string(), z.array(z.string())); 23 | 24 | expect(schema); 25 | }); 26 | test('array key', () => { 27 | const schema = z.map(z.array(z.string()), z.number()); 28 | 29 | expect(schema); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /tests/nan.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test } from 'vitest'; 2 | import { z } from 'zod'; 3 | import { expect } from './utils/expect'; 4 | 5 | describe('NaN', () => { 6 | test('base', () => { 7 | const schema = z.nan(); 8 | 9 | expect(schema); 10 | }); 11 | test('in object', () => { 12 | const schema = z.object({ foo: z.nan() }); 13 | 14 | expect(schema); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /tests/nativeEnum.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test } from 'vitest'; 2 | import { z } from 'zod'; 3 | import { expect } from './utils/expect'; 4 | 5 | describe('Native enum', () => { 6 | test('base', () => { 7 | enum NativeEnum { 8 | A = 'a', 9 | B = 'b', 10 | } 11 | const schema = z.nativeEnum(NativeEnum); 12 | 13 | expect(schema); 14 | }); 15 | test('by variable', () => { 16 | const Enum = { 17 | Apple: 'apple', 18 | Banana: 'banana', 19 | Cantaloupe: 3, 20 | } as const; 21 | const schema = z.nativeEnum(Enum); 22 | 23 | expect(schema); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /tests/nullable.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test } from 'vitest'; 2 | import { z } from 'zod'; 3 | import { expect } from './utils/expect'; 4 | 5 | describe('Nullable', () => { 6 | test('string', () => { 7 | const schema = z.string().nullable(); 8 | 9 | expect(schema); 10 | }); 11 | test('object values', () => { 12 | const schema = z.object({ 13 | foo: z.string().nullable(), 14 | }); 15 | 16 | expect(schema); 17 | }); 18 | test('array values', () => { 19 | const schema = z.array(z.string().nullable()); 20 | 21 | expect(schema); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /tests/number.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test } from 'vitest'; 2 | import { z } from 'zod'; 3 | import { expect } from './utils/expect'; 4 | 5 | describe('Number', () => { 6 | test('base', () => { 7 | const schema = z.number(); 8 | 9 | expect(schema); 10 | }); 11 | test('min or gt/gte', () => { 12 | const schema = z.number().min(10); 13 | 14 | expect(schema); 15 | }); 16 | test('max or lt/lte', () => { 17 | const schema = z.number().max(10); 18 | 19 | expect(schema); 20 | }); 21 | test('integer', () => { 22 | const schema = z.number().int().min(50); 23 | 24 | expect(schema); 25 | }); 26 | test('finite', () => { 27 | const schema = z.number().finite(); 28 | 29 | expect(schema); 30 | }); 31 | test('positive', () => { 32 | const schema = z.number().positive(); 33 | 34 | expect(schema); 35 | }); 36 | test('nonpositive', () => { 37 | const schema = z.number().nonpositive(); 38 | 39 | expect(schema); 40 | }); 41 | test('negative', () => { 42 | const schema = z.number().negative(); 43 | 44 | expect(schema); 45 | }); 46 | test('nonnegative', () => { 47 | const schema = z.number().nonnegative(); 48 | 49 | expect(schema); 50 | }); 51 | test('multipleOf', () => { 52 | const schema = z.number().multipleOf(10); 53 | 54 | expect(schema); 55 | }); 56 | }); 57 | -------------------------------------------------------------------------------- /tests/object.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test } from 'vitest'; 2 | import { z } from 'zod'; 3 | import { expect } from './utils/expect'; 4 | 5 | describe('Object', () => { 6 | test('base', () => { 7 | const schema = z.object({ foo: z.string(), bar: z.number() }); 8 | 9 | expect(schema); 10 | }); 11 | test('partial', () => { 12 | const schema = z.object({ foo: z.string(), bar: z.number() }).partial(); 13 | 14 | expect(schema); 15 | }); 16 | test('strict', () => { 17 | const schema = z.object({ foo: z.string(), bar: z.number() }).strict(); 18 | 19 | expect(schema); 20 | }); 21 | test('nonstrict', () => { 22 | const schema = z.object({ foo: z.string(), bar: z.number() }).nonstrict(); 23 | 24 | expect(schema); 25 | }); 26 | test('passthrough', () => { 27 | const schema = z.object({ foo: z.string(), bar: z.number() }).passthrough(); 28 | 29 | expect(schema); 30 | }); 31 | test('array', () => { 32 | const schema = z.object({ foo: z.string(), bar: z.number() }).array(); 33 | 34 | expect(schema); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /tests/optional.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test } from 'vitest'; 2 | import { z } from 'zod'; 3 | import { expect } from './utils/expect'; 4 | 5 | describe('Optional', () => { 6 | test('string', () => { 7 | const schema = z.string().optional(); 8 | 9 | expect(schema); 10 | }); 11 | test('number', () => { 12 | const schema = z.number().optional(); 13 | 14 | expect(schema); 15 | }); 16 | test('boolean', () => { 17 | const schema = z.boolean().optional(); 18 | 19 | expect(schema); 20 | }); 21 | test('date', () => { 22 | const schema = z.date().optional(); 23 | 24 | expect(schema); 25 | }); 26 | test('object', () => { 27 | const schema = z.object({ foo: z.string().optional() }).optional(); 28 | 29 | expect(schema); 30 | }); 31 | test('array', () => { 32 | const schema = z.array(z.string().optional()).optional(); 33 | 34 | expect(schema); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /tests/pipeline.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test } from 'vitest'; 2 | import { z } from 'zod'; 3 | import { expect } from './utils/expect'; 4 | 5 | describe('Pipeline', () => { 6 | test('with transform', () => { 7 | const schema = z.string() 8 | .transform(val => val.length) 9 | .pipe(z.number().min(10)); 10 | 11 | expect(schema._def.out); 12 | }); 13 | test('with coerse', () => { 14 | const dateLike = z.union([z.number(), z.string(), z.date()]); 15 | const schema = dateLike.pipe(z.coerce.date()); 16 | 17 | expect(schema._def.out); 18 | }); 19 | test('with chain coerse', () => { 20 | const toNumber = z.number().or(z.string()).pipe(z.coerce.number()); 21 | const toBigInt = z.bigint().or(toNumber).pipe(z.coerce.bigint()); 22 | 23 | expect(toBigInt._def.out); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /tests/promise.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test } from 'vitest'; 2 | import { z } from 'zod'; 3 | import { expect } from './utils/expect'; 4 | 5 | describe('Promise', () => { 6 | test('string', () => { 7 | const schema = z.promise(z.string()); 8 | 9 | expect(schema); 10 | }); 11 | test('number', () => { 12 | const schema = z.promise(z.number()); 13 | 14 | expect(schema); 15 | }); 16 | test('boolean', () => { 17 | const schema = z.promise(z.boolean()); 18 | 19 | expect(schema); 20 | }); 21 | test('object', () => { 22 | const schema = z.promise(z.object({ foo: z.string() })); 23 | 24 | expect(schema); 25 | }); 26 | test('nullable', () => { 27 | const schema = z.promise(z.string()).nullable(); 28 | 29 | expect(schema); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /tests/readonly.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test } from 'vitest'; 2 | import { z } from 'zod'; 3 | import { expect } from './utils/expect'; 4 | 5 | describe('Readonly', () => { 6 | test('base', () => { 7 | const object = z.object({ foo: z.string(), bar: z.number() }).readonly(); 8 | expect(object); 9 | 10 | const array = z.array(z.string()).readonly(); 11 | expect(array); 12 | 13 | const string = z.string().readonly(); 14 | expect(string); 15 | 16 | const number = z.number().readonly(); 17 | expect(number); 18 | 19 | const boolean = z.boolean().readonly(); 20 | expect(boolean); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /tests/record.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test } from 'vitest'; 2 | import { z } from 'zod'; 3 | import { expect } from './utils/expect'; 4 | 5 | describe('Record', () => { 6 | test('base', () => { 7 | const schema = z.record(z.string()); 8 | 9 | expect(schema); 10 | }); 11 | test('with key', () => { 12 | const schema = z.record(z.string(), z.number()); 13 | 14 | expect(schema); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /tests/set.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test } from 'vitest'; 2 | import { z } from 'zod'; 3 | import { expect } from './utils/expect'; 4 | 5 | describe('Set', () => { 6 | test('primitive', () => { 7 | const schema = z.set(z.string()); 8 | 9 | expect(schema); 10 | }); 11 | test('object', () => { 12 | const schema = z.set(z.object({ a: z.string() })); 13 | 14 | expect(schema); 15 | }); 16 | test('with min', () => { 17 | const schema = z.set(z.string()).min(2); 18 | 19 | expect(schema); 20 | }); 21 | test('with max', () => { 22 | const schema = z.set(z.string()).max(2); 23 | 24 | expect(schema); 25 | }); 26 | test('with size', () => { 27 | const schema = z.set(z.string()).size(5); 28 | 29 | expect(schema); 30 | }); 31 | test('nonempty', () => { 32 | const schema = z.set(z.string()).nonempty(); 33 | 34 | expect(schema); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /tests/string.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test } from 'vitest'; 2 | import { z } from 'zod'; 3 | import { expect } from './utils/expect'; 4 | 5 | describe('String', () => { 6 | test('base', () => { 7 | const schema = z.string(); 8 | 9 | expect(schema); 10 | }); 11 | test('uuid', () => { 12 | const schema = z.string().uuid(); 13 | 14 | expect(schema); 15 | }); 16 | test('email', () => { 17 | const schema = z.string().email(); 18 | 19 | expect(schema); 20 | }); 21 | test('min', () => { 22 | const schema = z.string().min(10); 23 | 24 | expect(schema); 25 | }); 26 | test('max', () => { 27 | const schema = z.string().max(10); 28 | 29 | expect(schema); 30 | }); 31 | test('array', () => { 32 | const schema = z.string().array(); 33 | 34 | expect(schema); 35 | }); 36 | test('datetime', () => { 37 | const schema = z.string().datetime(); 38 | 39 | expect(schema); 40 | }); 41 | test('length', () => { 42 | const schema = z.string().length(10); 43 | 44 | expect(schema); 45 | }); 46 | test('url', () => { 47 | const schema = z.string().url(); 48 | 49 | expect(schema); 50 | }); 51 | test('emoji', () => { 52 | const schema = z.string().emoji(); 53 | 54 | expect(schema); 55 | }); 56 | test('ip', () => { 57 | const schemaV4 = z.string().ip({ version: 'v4' }); 58 | const schemaV6 = z.string().ip({ version: 'v6' }); 59 | 60 | expect(schemaV4); 61 | expect(schemaV6); 62 | }); 63 | test('startsWith', () => { 64 | const schema = z.string().startsWith('__MARK__'); 65 | 66 | expect(schema); 67 | }); 68 | test('endsWith', () => { 69 | const schema = z.string().endsWith('__MARK__'); 70 | 71 | expect(schema); 72 | }); 73 | test('includes', () => { 74 | const schema = z.string().includes('__MARK__'); 75 | 76 | expect(schema); 77 | }); 78 | }); 79 | -------------------------------------------------------------------------------- /tests/symbol.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test } from 'vitest'; 2 | import { z } from 'zod'; 3 | import { expect } from './utils/expect'; 4 | 5 | describe('Symbol', () => { 6 | test('base', () => { 7 | const schema = z.symbol(); 8 | 9 | expect(schema); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /tests/tuple.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test } from 'vitest'; 2 | import { z } from 'zod'; 3 | import { expect } from './utils/expect'; 4 | 5 | describe('Tuple', () => { 6 | test('base', () => { 7 | const schema = z.tuple([z.string(), z.number(), z.boolean()]); 8 | 9 | expect(schema); 10 | }); 11 | test('rest', () => { 12 | const schema = z.tuple([z.string(), z.number()]).rest(z.boolean()); 13 | 14 | expect(schema); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /tests/union.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test } from 'vitest'; 2 | import { z } from 'zod'; 3 | import { expect } from './utils/expect'; 4 | 5 | describe('Union', () => { 6 | test('base', () => { 7 | const schema = z.union([z.string(), z.number(), z.boolean(), z.literal('')]); 8 | 9 | expect(schema); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /tests/utils/expect.ts: -------------------------------------------------------------------------------- 1 | import type { z } from 'zod'; 2 | import { expect as viExpect } from 'vitest'; 3 | import { createMock } from '../../src'; 4 | 5 | export function expect(schema: T) { 6 | return viExpect(schema.safeParse(createMock(schema)).success).toBe(true); 7 | } 8 | -------------------------------------------------------------------------------- /tests/void.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test } from 'vitest'; 2 | import { z } from 'zod'; 3 | import { expect } from './utils/expect'; 4 | 5 | describe('Void', () => { 6 | test('base', () => { 7 | const schema = z.void(); 8 | 9 | expect(schema); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "esnext", 4 | "target": "esnext", 5 | "lib": [ 6 | "DOM", 7 | "ESNext" 8 | ], 9 | "strict": true, 10 | "esModuleInterop": true, 11 | "skipLibCheck": true, 12 | "moduleResolution": "node", 13 | "resolveJsonModule": true, 14 | "noUnusedLocals": true, 15 | "strictNullChecks": true 16 | } 17 | } 18 | --------------------------------------------------------------------------------