Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch to Vitest #3563

Merged
merged 6 commits into from
Jun 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 0 additions & 13 deletions .configs/babel-jest.config.json

This file was deleted.

6 changes: 0 additions & 6 deletions .configs/babel.config.js

This file was deleted.

10 changes: 0 additions & 10 deletions .configs/jest.config.json

This file was deleted.

10 changes: 0 additions & 10 deletions .configs/swc-jest.config.json

This file was deleted.

10 changes: 0 additions & 10 deletions .configs/ts-jest.config.json

This file was deleted.

1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ coverage
.idea
*.log
playground.ts
# deno/lib
workspace.code-workspace
.netlify
bun.lockb
Expand Down
4 changes: 4 additions & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
link-workspace-packages=true
prefer-workspace-packages=true
hoist-workspace-packages=false
save-workspace-protocol=false
18 changes: 13 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,21 +50,29 @@ In the OSS version of VSCode the extension may be not available.

**`pnpm test`**

- runs all Jest tests and generates coverage badge
- runs all Vitest tests and generates coverage badge

**`pnpm test enum`**
**`pnpm test:watch`**

- runs a single test file (e.g. `enum.test.ts`)
- runs all Vitest tests and

**`pnpm test <file>`**

- runs all test files that match `<file>`

**`pnpm test --filter <ws> <file>`**

- runs all test files in `<ws>` that match `<file>` (e.g. `"enum"` will match `"enum.test.ts"`)

**`pnpm play`**

- executes [`playground.ts`](playground.ts), watches for changes. useful for experimentation

### Tests

Zod uses Jest for testing. After implementing your contribution, write tests for it. Just create a new file under `src/__tests__` or add additional tests to the appropriate existing file.
Zod uses Vitest for testing. After implementing your contribution, write tests for it. Just create a new file in the `tests` directory of any workspace, or add additional tests to an existing file if appropriate.

Before submitting your PR, run `pnpm test` to make sure there are no (unintended) breaking changes.
> Zod uses git hooks to execute tests before `git push`. Before submitting your PR, run `pnpm test` to make sure there are no (unintended) breaking changes.

### Documentation

Expand Down
4 changes: 2 additions & 2 deletions benchmarks/benchUtil.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const zNew = require("../../lib/index");
const zOld = require("../../node_modules/zod/lib/index");
const zNew = require("../zod/lib");
const zOld = require("../node_modules/zod/lib/index");

export function makeSchema<T>(factory: (z: typeof zNew) => T) {
return {
Expand Down
6 changes: 6 additions & 0 deletions benchmarks/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"private": true,
"devDependencies": {
"zod": "^3.0.0"
}
}
3 changes: 1 addition & 2 deletions effect-plugin/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"name": "@zod-plugin/effect",
"version": "0.1.0",
"type": "module",
"author": "Colin McDonnell <[email protected]>",
"files": ["src", "dist"],
"funding": "https://github.com/sponsors/colinhacks",
Expand Down Expand Up @@ -45,7 +44,7 @@
"build": "pnpm run clean && pnpm build:cjs && pnpm build:esm",
"build:esm": "pnpm tsc -p ./tsconfig.build.json --noEmit false --declaration --declarationMap --sourceMap --rootDir src --module esnext --moduleResolution node10 --outDir dist/esm",
"build:cjs": "pnpm tsc -p ./tsconfig.build.json --noEmit false --rootDir src --sourceMap --module commonjs --moduleResolution node10 --outDir dist/cjs",
"test": "tsx tests/*.ts",
"test": "vitest run",
"prepublishOnly": "pnpm test && pnpm build"
}
}
18 changes: 9 additions & 9 deletions effect-plugin/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import * as Effect from "effect/Effect";
import * as z from "zod";
import { ZodError, ZodType } from "zod";

function zodEffect(this: z.ZodType, data: unknown, params?: any) {
function zodEffect(this: ZodType, data: unknown, params?: any) {
return Effect.flatMap(
Effect.promise(() => this.safeParseAsync(data, params)),
(result) =>
result.success ? Effect.succeed(result.data) : Effect.fail(result.error)
);
}

function zodEffectSync(this: z.ZodType, data: unknown, params?: any) {
function zodEffectSync(this: ZodType, data: unknown, params?: any) {
return Effect.suspend(() => {
const result = this.safeParse(data, params);
return result.success
Expand All @@ -21,24 +21,24 @@ function zodEffectSync(this: z.ZodType, data: unknown, params?: any) {
const sym = Symbol.for("zod_effect_executed");
if (!(globalThis as { [k: symbol]: unknown })[sym]) {
(globalThis as { [k: symbol]: unknown })[sym] = true;
Object.defineProperty(z.ZodType.prototype, "effect", {
Object.defineProperty(ZodType.prototype, "effect", {
get() {
return {
parse: zodEffect.bind(this),
parseSync: zodEffectSync.bind(this),
};
},
});
z.ZodError.prototype._tag = "ZodError";
ZodError.prototype._tag = "ZodError";
}

interface EffectMethods<T> {
parse(
...args: Parameters<z.ZodType["parseAsync"]>
): Effect.Effect<T, z.ZodError<T>>;
...args: Parameters<ZodType["parseAsync"]>
): Effect.Effect<T, ZodError<T>>;
parseSync(
...args: Parameters<z.ZodType["parse"]>
): Effect.Effect<T, z.ZodError<T>>;
...args: Parameters<ZodType["parse"]>
): Effect.Effect<T, ZodError<T>>;
}
declare module "zod" {
interface ZodType {
Expand Down
81 changes: 42 additions & 39 deletions effect-plugin/tests/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,49 +1,52 @@
import "../src/index";

import assert from "node:assert";
import test from "node:test";
import { Cause, Effect, Exit } from "effect";
import { describe, expect, test } from "vitest";
import * as z from "zod";

const syncSchema = z.string();
const asyncSchema = z.string().refine(async () => true);

test("Sync schema should return the input value", () => {
const result = Effect.runSync(syncSchema.effect.parseSync("hello"));
assert.strict.equal(result, "hello");
});

test("Async schema should return the input value", async () => {
const result = await Effect.runPromise(asyncSchema.effect.parse("hello"));
assert.strict.equal(result, "hello");
});

test("Sync schema should return fail ZodError", async () => {
assert.throws(() => Effect.runSync(z.number().effect.parseSync("hello")));
});

test("ZodError should have the correct tag", () => {
const err = new z.ZodError([]);
assert.strict.equal(err._tag, "ZodError");
});

test("Pass parse params into .effect.parseSync as the second params", () => {
const schema = z.string().min(5);

const result = Effect.runSyncExit(
schema.effect.parseSync(5, {
errorMap() {
return { message: "CUSTOM" };
},
})
);
assert.strict.equal(Exit.isFailure(result), true);
if (Exit.isFailure(result)) {
const cause = result.cause;
assert.strict.equal(Cause.isFailType(cause), true);
if (Cause.isFailType(cause)) {
cause.error;
assert.strict.equal(cause.error.issues[0].message, "CUSTOM");
describe("Schema validation tests", () => {
test("Sync schema should return the input value", () => {
const result = Effect.runSync(syncSchema.effect.parseSync("hello"));
expect(result).toBe("hello");
});

test("Async schema should return the input value", async () => {
const result = await Effect.runPromise(asyncSchema.effect.parse("hello"));
expect(result).toBe("hello");
});

test("Sync schema should return fail ZodError", () => {
expect(() =>
Effect.runSync(z.number().effect.parseSync("hello"))
).toThrow();
});

test("ZodError should have the correct tag", () => {
const err = new z.ZodError([]);
expect(err._tag).toBe("ZodError");
});

test("Pass parse params into .effect.parseSync as the second params", () => {
const schema = z.string().min(5);

const result = Effect.runSyncExit(
schema.effect.parseSync(5, {
errorMap() {
return { message: "CUSTOM" };
},
})
);

expect(Exit.isFailure(result)).toBe(true);
if (Exit.isFailure(result)) {
const cause = result.cause;
expect(Cause.isFailType(cause)).toBe(true);
if (Cause.isFailType(cause)) {
expect(cause.error.issues[0].message).toBe("CUSTOM");
}
}
}
});
});
4 changes: 4 additions & 0 deletions effect-plugin/vitest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { defineConfig, mergeConfig } from "vitest/config";
import rootConfig from "../vitest.root";

export default mergeConfig(rootConfig, defineConfig({}));
10 changes: 0 additions & 10 deletions jest.config.json

This file was deleted.

25 changes: 4 additions & 21 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,41 +15,31 @@
},
"workspaces": ["zod", "effect-plugin"],
"devDependencies": {
"@babel/core": "^7.22.5",
"@babel/preset-env": "^7.22.5",
"@babel/preset-typescript": "^7.22.5",
"@biomejs/biome": "^1.7.3",
"@jest/globals": "^29.4.3",
"@rollup/plugin-commonjs": "^25.0.8",
"@rollup/plugin-node-resolve": "^15.2.3",
"@rollup/plugin-typescript": "^11.1.6",
"@swc/core": "^1.3.66",
"@swc/jest": "^0.2.26",
"@types/benchmark": "^2.1.5",
"@types/chalk": "^2.2.0",
"@types/jest": "^29.2.2",
"@types/node": "^20.0.0",
"@web-std/file": "^3.0.3",
"babel-jest": "^29.5.0",
"benchmark": "^2.1.4",
"chalk": "^5.3.0",
"console-table-printer": "^2.12.0",
"dependency-cruiser": "^9.19.0",
"execa": "^9.1.0",
"husky": "^7.0.4",
"jest": "^29.3.1",
"lint-staged": "^12.3.7",
"mitata": "^0.1.11",
"nodemon": "^2.0.22",
"prettier": "^3.2.5",
"rollup": "^4.18.0",
"tinybench": "^2.8.0",
"ts-jest": "^29.1.0",
"ts-morph": "^14.0.0",
"ts-node": "^10.9.1",
"ts-node": "^10.9.2",
"tslib": "^2.3.1",
"typescript": "next",
"vitest": "^0.32.2"
"vitest": "^1.6.0"
},
"lint-staged": {
"src/*.ts": ["biome format --write", "biome lint --apply"],
Expand All @@ -66,15 +56,8 @@
"build:esm": "rollup --config ./.configs/rollup.config.mjs",
"build:cjs": "tsc -p ./.configs/tsconfig.cjs.json --rootDir .",
"build:types": "tsc -p ./.configs/tsconfig.types.json",
"build:test": "tsc -p ./.configs/tsconfig.test.json",
"test:watch": "pnpm run test:ts-jest --watch",
"test": "pnpm run test:ts-jest",
"test:babel": "jest --coverage --config ./.configs/babel-jest.config.json",
"test:bun": "bun test src/",
"test:vitest": "npx vitest --config ./.configs/vitest.config.ts",
"test:ts-jest": "npx jest --config ./.configs/ts-jest.config.json",
"test:swc": "npx jest --config ./.configs/swc-jest.config.json",
"test:deno": "cd deno && deno test",
"test:watch": "pnpm vitest",
"test": "pnpm vitest run",
"prepublishOnly": "pnpm run test && pnpm run build && pnpm run build:deno",
"play": "nodemon -e ts,mts -w . -x ts-node playground.ts",
"depcruise": "depcruise -c .dependency-cruiser.js src",
Expand Down
Loading