From 389dac8f6d2622b75d8115f689ac0e1c7a159c8a Mon Sep 17 00:00:00 2001 From: Luca De Santis Date: Fri, 3 Feb 2023 18:59:19 +0100 Subject: [PATCH 1/7] Increment email validation Supported: - local-part -> Dot-string / Quoted-string - domain -> latin letters, numbers, "-" / IPv4 address Unsupported: - domain -> IPv6 --- deno/lib/__tests__/string.test.ts | 56 ++++++++++++++++++++++++------- deno/lib/types.ts | 20 ++++++----- src/__tests__/string.test.ts | 56 ++++++++++++++++++++++++------- src/types.ts | 20 ++++++----- 4 files changed, 112 insertions(+), 40 deletions(-) diff --git a/deno/lib/__tests__/string.test.ts b/deno/lib/__tests__/string.test.ts index a03a864c7..55ee9224a 100644 --- a/deno/lib/__tests__/string.test.ts +++ b/deno/lib/__tests__/string.test.ts @@ -42,22 +42,54 @@ test("email validations", () => { expect(() => email.parse("asdf@-asdf.com")).toThrow(); expect(() => email.parse("asdf@-a(sdf.com")).toThrow(); expect(() => email.parse("asdf@-asdf.com(")).toThrow(); + expect(() => + email.parse("pawan.anand@%9y83&#$%R&#$%R&%#$R%%^^%5rw3ewe.d.d.aaaa.wef.co") + ).toThrow(); }); test("more email validations", () => { - const data = [ - `"josé.arrañoça"@domain.com`, - `"сайт"@domain.com`, - `"💩"@domain.com`, - `"🍺🕺🎉"@domain.com`, - `poop@💩.la`, - `"🌮"@i❤️tacos.ws`, - "sss--asd@i❤️tacos.ws", + const validEmails = [ + `very.common@example.com`, + `disposable.style.email.with+symbol@example.com`, + `other.email-with-hyphen@example.com`, + `fully-qualified-domain@example.com`, + `user.name+tag+sorting@example.com`, + `x@example.com`, + `example-indeed@strange-example.com`, + `test/test@test.com`, + `example@s.example`, + `" "@example.org`, + `"john..doe"@example.org`, + `mailhost!username@example.org`, + `"very.(),:;<>[]\".VERY.\"very@\\ \"very\".unusual"@strange.example.com`, + `user%example.com@example.org`, + `user-@example.org`, + `postmaster@[123.123.123.123]`, + `user@my-example.com`, + `a@b.cd`, ]; - const email = z.string().email(); - for (const datum of data) { - email.parse(datum); - } + const invalidEmails = [ + `Abc.example.com`, + `A@b@c@example.com`, + `a"b(c)d,e:f;gi[j\k]l@example.com`, + `just"not"right@example.com`, + `this is"not\allowed@example.com`, + `this\ still\"not\\allowed@example.com`, + `i_like_underscore@but_its_not_allowed_in_this_part.example.com`, + `QA[icon]CHOCOLATE[icon]@test.com`, + `invalid@-start.com`, + `invalid@end.com-`, + `a.b@c.d`, + ]; + const emailSchema = z.string().email(); + expect( + validEmails.every((email) => emailSchema.safeParse(email).success) + ).toBe(true); + expect( + invalidEmails.every( + (email) => emailSchema.safeParse(email).success === false + ) + ).toBe(true); }); test("url validations", () => { diff --git a/deno/lib/types.ts b/deno/lib/types.ts index 737c61fb8..fefe986f2 100644 --- a/deno/lib/types.ts +++ b/deno/lib/types.ts @@ -519,10 +519,11 @@ const uuidRegex = // from https://stackoverflow.com/a/46181/1550155 // old version: too slow, didn't support unicode // const emailRegex = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i; +//old email regex +// const emailRegex = /^(([^<>()[\].,;:\s@"]+(\.[^<>()[\].,;:\s@"]+)*)|(".+"))@((?!-)([^<>()[\].,;:\s@"]+\.)+[^<>()[\].,;:\s@"]{1,})[^-<>()[\].,;:\s@"]$/i; // eslint-disable-next-line const emailRegex = - /^(([^<>()[\].,;:\s@"]+(\.[^<>()[\].,;:\s@"]+)*)|(".+"))@((?!-)([^<>()[\].,;:\s@"]+\.)+[^<>()[\].,;:\s@"]{1,})[^-<>()[\].,;:\s@"]$/i; - + /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|([^-]([a-zA-Z0-9-]*\.)+[a-zA-Z]{2,}))$/; // interface IsDateStringOptions extends StringDateOptions { /** * Match any configuration @@ -3382,7 +3383,7 @@ export class ZodFunction< return this._def.returns; } - args[0]>( + args[0]>( ...items: Items ): ZodFunction, Returns> { return new ZodFunction({ @@ -4471,15 +4472,18 @@ const oboolean = () => booleanType().optional(); export const coerce = { string: ((arg) => - ZodString.create({ ...arg, coerce: true })) as typeof ZodString["create"], + ZodString.create({ ...arg, coerce: true })) as (typeof ZodString)["create"], number: ((arg) => - ZodNumber.create({ ...arg, coerce: true })) as typeof ZodNumber["create"], + ZodNumber.create({ ...arg, coerce: true })) as (typeof ZodNumber)["create"], boolean: ((arg) => - ZodBoolean.create({ ...arg, coerce: true })) as typeof ZodBoolean["create"], + ZodBoolean.create({ + ...arg, + coerce: true, + })) as (typeof ZodBoolean)["create"], bigint: ((arg) => - ZodBigInt.create({ ...arg, coerce: true })) as typeof ZodBigInt["create"], + ZodBigInt.create({ ...arg, coerce: true })) as (typeof ZodBigInt)["create"], date: ((arg) => - ZodDate.create({ ...arg, coerce: true })) as typeof ZodDate["create"], + ZodDate.create({ ...arg, coerce: true })) as (typeof ZodDate)["create"], }; export { diff --git a/src/__tests__/string.test.ts b/src/__tests__/string.test.ts index 9e5a8893e..4f1c04226 100644 --- a/src/__tests__/string.test.ts +++ b/src/__tests__/string.test.ts @@ -41,22 +41,54 @@ test("email validations", () => { expect(() => email.parse("asdf@-asdf.com")).toThrow(); expect(() => email.parse("asdf@-a(sdf.com")).toThrow(); expect(() => email.parse("asdf@-asdf.com(")).toThrow(); + expect(() => + email.parse("pawan.anand@%9y83&#$%R&#$%R&%#$R%%^^%5rw3ewe.d.d.aaaa.wef.co") + ).toThrow(); }); test("more email validations", () => { - const data = [ - `"josé.arrañoça"@domain.com`, - `"сайт"@domain.com`, - `"💩"@domain.com`, - `"🍺🕺🎉"@domain.com`, - `poop@💩.la`, - `"🌮"@i❤️tacos.ws`, - "sss--asd@i❤️tacos.ws", + const validEmails = [ + `very.common@example.com`, + `disposable.style.email.with+symbol@example.com`, + `other.email-with-hyphen@example.com`, + `fully-qualified-domain@example.com`, + `user.name+tag+sorting@example.com`, + `x@example.com`, + `example-indeed@strange-example.com`, + `test/test@test.com`, + `example@s.example`, + `" "@example.org`, + `"john..doe"@example.org`, + `mailhost!username@example.org`, + `"very.(),:;<>[]\".VERY.\"very@\\ \"very\".unusual"@strange.example.com`, + `user%example.com@example.org`, + `user-@example.org`, + `postmaster@[123.123.123.123]`, + `user@my-example.com`, + `a@b.cd`, ]; - const email = z.string().email(); - for (const datum of data) { - email.parse(datum); - } + const invalidEmails = [ + `Abc.example.com`, + `A@b@c@example.com`, + `a"b(c)d,e:f;gi[j\k]l@example.com`, + `just"not"right@example.com`, + `this is"not\allowed@example.com`, + `this\ still\"not\\allowed@example.com`, + `i_like_underscore@but_its_not_allowed_in_this_part.example.com`, + `QA[icon]CHOCOLATE[icon]@test.com`, + `invalid@-start.com`, + `invalid@end.com-`, + `a.b@c.d`, + ]; + const emailSchema = z.string().email(); + expect( + validEmails.every((email) => emailSchema.safeParse(email).success) + ).toBe(true); + expect( + invalidEmails.every( + (email) => emailSchema.safeParse(email).success === false + ) + ).toBe(true); }); test("url validations", () => { diff --git a/src/types.ts b/src/types.ts index 7250ce93f..4ecca578d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -519,10 +519,11 @@ const uuidRegex = // from https://stackoverflow.com/a/46181/1550155 // old version: too slow, didn't support unicode // const emailRegex = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i; +//old email regex +// const emailRegex = /^(([^<>()[\].,;:\s@"]+(\.[^<>()[\].,;:\s@"]+)*)|(".+"))@((?!-)([^<>()[\].,;:\s@"]+\.)+[^<>()[\].,;:\s@"]{1,})[^-<>()[\].,;:\s@"]$/i; // eslint-disable-next-line const emailRegex = - /^(([^<>()[\].,;:\s@"]+(\.[^<>()[\].,;:\s@"]+)*)|(".+"))@((?!-)([^<>()[\].,;:\s@"]+\.)+[^<>()[\].,;:\s@"]{1,})[^-<>()[\].,;:\s@"]$/i; - + /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|([^-]([a-zA-Z0-9-]*\.)+[a-zA-Z]{2,}))$/; // interface IsDateStringOptions extends StringDateOptions { /** * Match any configuration @@ -3382,7 +3383,7 @@ export class ZodFunction< return this._def.returns; } - args[0]>( + args[0]>( ...items: Items ): ZodFunction, Returns> { return new ZodFunction({ @@ -4471,15 +4472,18 @@ const oboolean = () => booleanType().optional(); export const coerce = { string: ((arg) => - ZodString.create({ ...arg, coerce: true })) as typeof ZodString["create"], + ZodString.create({ ...arg, coerce: true })) as (typeof ZodString)["create"], number: ((arg) => - ZodNumber.create({ ...arg, coerce: true })) as typeof ZodNumber["create"], + ZodNumber.create({ ...arg, coerce: true })) as (typeof ZodNumber)["create"], boolean: ((arg) => - ZodBoolean.create({ ...arg, coerce: true })) as typeof ZodBoolean["create"], + ZodBoolean.create({ + ...arg, + coerce: true, + })) as (typeof ZodBoolean)["create"], bigint: ((arg) => - ZodBigInt.create({ ...arg, coerce: true })) as typeof ZodBigInt["create"], + ZodBigInt.create({ ...arg, coerce: true })) as (typeof ZodBigInt)["create"], date: ((arg) => - ZodDate.create({ ...arg, coerce: true })) as typeof ZodDate["create"], + ZodDate.create({ ...arg, coerce: true })) as (typeof ZodDate)["create"], }; export { From 799e50cc53160ebe3472fd56444781aba88187c5 Mon Sep 17 00:00:00 2001 From: Luca De Santis Date: Fri, 3 Feb 2023 19:44:47 +0100 Subject: [PATCH 2/7] Fix import type in some test files The error generated is: TS2307: Cannot find module '@jest/globals' or its corresponding type declarations. --- deno/lib/__tests__/discriminatedUnions.test.ts | 1 + deno/lib/__tests__/firstparty.test.ts | 1 + deno/lib/__tests__/unions.test.ts | 1 + src/__tests__/discriminatedUnions.test.ts | 1 + src/__tests__/firstparty.test.ts | 1 + src/__tests__/object-in-es5-env.test.ts | 1 + src/__tests__/unions.test.ts | 1 + 7 files changed, 7 insertions(+) diff --git a/deno/lib/__tests__/discriminatedUnions.test.ts b/deno/lib/__tests__/discriminatedUnions.test.ts index cc0f3bd28..4e472c8a8 100644 --- a/deno/lib/__tests__/discriminatedUnions.test.ts +++ b/deno/lib/__tests__/discriminatedUnions.test.ts @@ -1,3 +1,4 @@ +// @ts-ignore TS6133 import { expect } from "https://deno.land/x/expect@v0.2.6/mod.ts"; const test = Deno.test; diff --git a/deno/lib/__tests__/firstparty.test.ts b/deno/lib/__tests__/firstparty.test.ts index 4e49d1397..66ed29bdb 100644 --- a/deno/lib/__tests__/firstparty.test.ts +++ b/deno/lib/__tests__/firstparty.test.ts @@ -1,3 +1,4 @@ +// @ts-ignore TS6133 import { expect } from "https://deno.land/x/expect@v0.2.6/mod.ts"; const test = Deno.test; diff --git a/deno/lib/__tests__/unions.test.ts b/deno/lib/__tests__/unions.test.ts index 83475e171..3a73d975f 100644 --- a/deno/lib/__tests__/unions.test.ts +++ b/deno/lib/__tests__/unions.test.ts @@ -1,3 +1,4 @@ +// @ts-ignore TS6133 import { expect } from "https://deno.land/x/expect@v0.2.6/mod.ts"; const test = Deno.test; diff --git a/src/__tests__/discriminatedUnions.test.ts b/src/__tests__/discriminatedUnions.test.ts index dbce353e9..68a3f8fb9 100644 --- a/src/__tests__/discriminatedUnions.test.ts +++ b/src/__tests__/discriminatedUnions.test.ts @@ -1,3 +1,4 @@ +// @ts-ignore TS6133 import { expect, test } from "@jest/globals"; import * as z from "../index"; diff --git a/src/__tests__/firstparty.test.ts b/src/__tests__/firstparty.test.ts index b8b51dec3..bd5f6986d 100644 --- a/src/__tests__/firstparty.test.ts +++ b/src/__tests__/firstparty.test.ts @@ -1,3 +1,4 @@ +// @ts-ignore TS6133 import { test } from "@jest/globals"; import { util } from "../helpers/util"; diff --git a/src/__tests__/object-in-es5-env.test.ts b/src/__tests__/object-in-es5-env.test.ts index bfd3ad9c3..6d17a0964 100644 --- a/src/__tests__/object-in-es5-env.test.ts +++ b/src/__tests__/object-in-es5-env.test.ts @@ -1,3 +1,4 @@ +// @ts-ignore TS6133 import { expect, test } from "@jest/globals"; import * as z from "../index"; diff --git a/src/__tests__/unions.test.ts b/src/__tests__/unions.test.ts index fcae2459a..e7b30bcef 100644 --- a/src/__tests__/unions.test.ts +++ b/src/__tests__/unions.test.ts @@ -1,3 +1,4 @@ +// @ts-ignore TS6133 import { expect, test } from "@jest/globals"; import * as z from "../index"; From ec4497077405bc50ba2eabcfc25fe03603c7f2da Mon Sep 17 00:00:00 2001 From: Luca De Santis Date: Sat, 4 Feb 2023 16:32:53 +0100 Subject: [PATCH 3/7] Format code with prettier config --- deno/lib/__tests__/object.test.ts | 4 ++-- deno/lib/__tests__/transformer.test.ts | 2 +- deno/lib/benchmarks/primitives.ts | 16 +++++++++++++--- src/__tests__/object.test.ts | 4 ++-- src/__tests__/transformer.test.ts | 2 +- src/benchmarks/primitives.ts | 16 +++++++++++++--- 6 files changed, 32 insertions(+), 12 deletions(-) diff --git a/deno/lib/__tests__/object.test.ts b/deno/lib/__tests__/object.test.ts index 99b81c95d..3090fb6ac 100644 --- a/deno/lib/__tests__/object.test.ts +++ b/deno/lib/__tests__/object.test.ts @@ -111,8 +111,8 @@ test("catchall inference", () => { .catchall(z.number()); const d1 = o1.parse({ first: "asdf", num: 1243 }); - util.assertEqual(true); - util.assertEqual(true); + util.assertEqual(true); + util.assertEqual(true); }); test("catchall overrides strict", () => { diff --git a/deno/lib/__tests__/transformer.test.ts b/deno/lib/__tests__/transformer.test.ts index 9a1f92951..818aa49cb 100644 --- a/deno/lib/__tests__/transformer.test.ts +++ b/deno/lib/__tests__/transformer.test.ts @@ -202,7 +202,7 @@ test("preprocess", () => { const value = schema.parse("asdf"); expect(value).toEqual(["asdf"]); - util.assertEqual(true); + util.assertEqual<(typeof schema)["_input"], unknown>(true); }); test("async preprocess", async () => { diff --git a/deno/lib/benchmarks/primitives.ts b/deno/lib/benchmarks/primitives.ts index 734dfe2bb..c91b50114 100644 --- a/deno/lib/benchmarks/primitives.ts +++ b/deno/lib/benchmarks/primitives.ts @@ -79,7 +79,10 @@ numberSuite const dateSuite = new Benchmark.Suite("z.date"); const plainDate = z.date(); -const minMaxDate = z.date().min(new Date("2021-01-01")).max(new Date("2030-01-01")); +const minMaxDate = z + .date() + .min(new Date("2021-01-01")) + .max(new Date("2030-01-01")); dateSuite .add("valid", () => { @@ -112,7 +115,7 @@ const symbolSchema = z.symbol(); symbolSuite .add("valid", () => { - symbolSchema.parse(val.symbol) + symbolSchema.parse(val.symbol); }) .add("invalid", () => { try { @@ -124,5 +127,12 @@ symbolSuite }); export default { - suites: [enumSuite, undefinedSuite, literalSuite, numberSuite, dateSuite, symbolSuite], + suites: [ + enumSuite, + undefinedSuite, + literalSuite, + numberSuite, + dateSuite, + symbolSuite, + ], }; diff --git a/src/__tests__/object.test.ts b/src/__tests__/object.test.ts index e1e7fc532..3865127cf 100644 --- a/src/__tests__/object.test.ts +++ b/src/__tests__/object.test.ts @@ -110,8 +110,8 @@ test("catchall inference", () => { .catchall(z.number()); const d1 = o1.parse({ first: "asdf", num: 1243 }); - util.assertEqual(true); - util.assertEqual(true); + util.assertEqual(true); + util.assertEqual(true); }); test("catchall overrides strict", () => { diff --git a/src/__tests__/transformer.test.ts b/src/__tests__/transformer.test.ts index 4af6117f3..8e1f2a598 100644 --- a/src/__tests__/transformer.test.ts +++ b/src/__tests__/transformer.test.ts @@ -201,7 +201,7 @@ test("preprocess", () => { const value = schema.parse("asdf"); expect(value).toEqual(["asdf"]); - util.assertEqual(true); + util.assertEqual<(typeof schema)["_input"], unknown>(true); }); test("async preprocess", async () => { diff --git a/src/benchmarks/primitives.ts b/src/benchmarks/primitives.ts index 62809e275..5b0034f1d 100644 --- a/src/benchmarks/primitives.ts +++ b/src/benchmarks/primitives.ts @@ -79,7 +79,10 @@ numberSuite const dateSuite = new Benchmark.Suite("z.date"); const plainDate = z.date(); -const minMaxDate = z.date().min(new Date("2021-01-01")).max(new Date("2030-01-01")); +const minMaxDate = z + .date() + .min(new Date("2021-01-01")) + .max(new Date("2030-01-01")); dateSuite .add("valid", () => { @@ -112,7 +115,7 @@ const symbolSchema = z.symbol(); symbolSuite .add("valid", () => { - symbolSchema.parse(val.symbol) + symbolSchema.parse(val.symbol); }) .add("invalid", () => { try { @@ -124,5 +127,12 @@ symbolSuite }); export default { - suites: [enumSuite, undefinedSuite, literalSuite, numberSuite, dateSuite, symbolSuite], + suites: [ + enumSuite, + undefinedSuite, + literalSuite, + numberSuite, + dateSuite, + symbolSuite, + ], }; From 70d38532b8c9e74a1786f256f68da0c566474973 Mon Sep 17 00:00:00 2001 From: Luca De Santis Date: Sat, 4 Feb 2023 19:44:59 +0100 Subject: [PATCH 4/7] Add more IPv4 test --- deno/lib/__tests__/string.test.ts | 6 ++++++ src/__tests__/string.test.ts | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/deno/lib/__tests__/string.test.ts b/deno/lib/__tests__/string.test.ts index 55ee9224a..32b0d1e23 100644 --- a/deno/lib/__tests__/string.test.ts +++ b/deno/lib/__tests__/string.test.ts @@ -67,6 +67,10 @@ test("more email validations", () => { `postmaster@[123.123.123.123]`, `user@my-example.com`, `a@b.cd`, + `work+user@mail.com`, + `user@[68.185.127.196]`, + `ipv4@[85.129.96.247]`, + `valid@[79.208.229.53]`, ]; const invalidEmails = [ `Abc.example.com`, @@ -80,6 +84,8 @@ test("more email validations", () => { `invalid@-start.com`, `invalid@end.com-`, `a.b@c.d`, + `invalid@[1.1.1.-1]`, + `invalid@[68.185.127.196.55]`, ]; const emailSchema = z.string().email(); expect( diff --git a/src/__tests__/string.test.ts b/src/__tests__/string.test.ts index 4f1c04226..d05f39411 100644 --- a/src/__tests__/string.test.ts +++ b/src/__tests__/string.test.ts @@ -66,6 +66,10 @@ test("more email validations", () => { `postmaster@[123.123.123.123]`, `user@my-example.com`, `a@b.cd`, + `work+user@mail.com`, + `user@[68.185.127.196]`, + `ipv4@[85.129.96.247]`, + `valid@[79.208.229.53]`, ]; const invalidEmails = [ `Abc.example.com`, @@ -79,6 +83,8 @@ test("more email validations", () => { `invalid@-start.com`, `invalid@end.com-`, `a.b@c.d`, + `invalid@[1.1.1.-1]`, + `invalid@[68.185.127.196.55]`, ]; const emailSchema = z.string().email(); expect( From 5fe0c7b4379a4ee27b69cf75d97caacc60eda653 Mon Sep 17 00:00:00 2001 From: Luca De Santis Date: Sun, 5 Feb 2023 00:21:11 +0100 Subject: [PATCH 5/7] Add Invalid IPv4 tests --- deno/lib/__tests__/string.test.ts | 2 ++ src/__tests__/string.test.ts | 2 ++ 2 files changed, 4 insertions(+) diff --git a/deno/lib/__tests__/string.test.ts b/deno/lib/__tests__/string.test.ts index 32b0d1e23..8cac57112 100644 --- a/deno/lib/__tests__/string.test.ts +++ b/deno/lib/__tests__/string.test.ts @@ -86,6 +86,8 @@ test("more email validations", () => { `a.b@c.d`, `invalid@[1.1.1.-1]`, `invalid@[68.185.127.196.55]`, + `temp@[192.168.1]`, + `temp@[9.18.122.]`, ]; const emailSchema = z.string().email(); expect( diff --git a/src/__tests__/string.test.ts b/src/__tests__/string.test.ts index d05f39411..cb075cf75 100644 --- a/src/__tests__/string.test.ts +++ b/src/__tests__/string.test.ts @@ -85,6 +85,8 @@ test("more email validations", () => { `a.b@c.d`, `invalid@[1.1.1.-1]`, `invalid@[68.185.127.196.55]`, + `temp@[192.168.1]`, + `temp@[9.18.122.]`, ]; const emailSchema = z.string().email(); expect( From b5528c0954ce4dc72bc539605fa96feb43b46da4 Mon Sep 17 00:00:00 2001 From: Colin McDonnell Date: Tue, 7 Feb 2023 23:44:25 -0800 Subject: [PATCH 6/7] Fix tests --- deno/lib/__tests__/partials.test.ts | 11 +++++++---- deno/lib/types.ts | 12 ++++++------ src/__tests__/partials.test.ts | 8 ++++++-- src/types.ts | 12 ++++++------ 4 files changed, 25 insertions(+), 18 deletions(-) diff --git a/deno/lib/__tests__/partials.test.ts b/deno/lib/__tests__/partials.test.ts index bb6eb355f..67fb82050 100644 --- a/deno/lib/__tests__/partials.test.ts +++ b/deno/lib/__tests__/partials.test.ts @@ -185,8 +185,13 @@ test("required with mask", () => { expect(requiredObject.shape.country).toBeInstanceOf(z.ZodOptional); }); - test("required with mask containing a nonexistent key", () => { + const object = z.object({ + name: z.string(), + age: z.number().optional(), + field: z.string().optional().default("asdf"), + country: z.string().optional(), + }); object.required({ age: true, // @ts-expect-error should not accept unexpected keys. @@ -201,17 +206,15 @@ test("required with mask -- ignore falsy values", () => { field: z.string().optional().default("asdf"), country: z.string().optional(), }); - + // @ts-expect-error const requiredObject = object.required({ age: true, country: false }); expect(requiredObject.shape.name).toBeInstanceOf(z.ZodString); expect(requiredObject.shape.age).toBeInstanceOf(z.ZodNumber); expect(requiredObject.shape.field).toBeInstanceOf(z.ZodDefault); expect(requiredObject.shape.country).toBeInstanceOf(z.ZodOptional); - }); - test("partial with mask", async () => { const object = z.object({ name: z.string(), diff --git a/deno/lib/types.ts b/deno/lib/types.ts index 496a5a62e..9029edf8d 100644 --- a/deno/lib/types.ts +++ b/deno/lib/types.ts @@ -3380,7 +3380,7 @@ export class ZodFunction< return this._def.returns; } - args[0]>( + args[0]>( ...items: Items ): ZodFunction, Returns> { return new ZodFunction({ @@ -4469,18 +4469,18 @@ const oboolean = () => booleanType().optional(); export const coerce = { string: ((arg) => - ZodString.create({ ...arg, coerce: true })) as (typeof ZodString)["create"], + ZodString.create({ ...arg, coerce: true })) as typeof ZodString["create"], number: ((arg) => - ZodNumber.create({ ...arg, coerce: true })) as (typeof ZodNumber)["create"], + ZodNumber.create({ ...arg, coerce: true })) as typeof ZodNumber["create"], boolean: ((arg) => ZodBoolean.create({ ...arg, coerce: true, - })) as (typeof ZodBoolean)["create"], + })) as typeof ZodBoolean["create"], bigint: ((arg) => - ZodBigInt.create({ ...arg, coerce: true })) as (typeof ZodBigInt)["create"], + ZodBigInt.create({ ...arg, coerce: true })) as typeof ZodBigInt["create"], date: ((arg) => - ZodDate.create({ ...arg, coerce: true })) as (typeof ZodDate)["create"], + ZodDate.create({ ...arg, coerce: true })) as typeof ZodDate["create"], }; export { diff --git a/src/__tests__/partials.test.ts b/src/__tests__/partials.test.ts index 448bdb22c..f6d7fcf7d 100644 --- a/src/__tests__/partials.test.ts +++ b/src/__tests__/partials.test.ts @@ -185,6 +185,12 @@ test("required with mask", () => { }); test("required with mask containing a nonexistent key", () => { + const object = z.object({ + name: z.string(), + age: z.number().optional(), + field: z.string().optional().default("asdf"), + country: z.string().optional(), + }); object.required({ age: true, // @ts-expect-error should not accept unexpected keys. @@ -193,7 +199,6 @@ test("required with mask containing a nonexistent key", () => { }); test("required with mask -- ignore falsy values", () => { - const object = z.object({ name: z.string(), age: z.number().optional(), @@ -201,7 +206,6 @@ test("required with mask -- ignore falsy values", () => { country: z.string().optional(), }); - // @ts-expect-error const requiredObject = object.required({ age: true, country: false }); expect(requiredObject.shape.name).toBeInstanceOf(z.ZodString); diff --git a/src/types.ts b/src/types.ts index 91c2d6c85..17d7c3fbb 100644 --- a/src/types.ts +++ b/src/types.ts @@ -3380,7 +3380,7 @@ export class ZodFunction< return this._def.returns; } - args[0]>( + args[0]>( ...items: Items ): ZodFunction, Returns> { return new ZodFunction({ @@ -4469,18 +4469,18 @@ const oboolean = () => booleanType().optional(); export const coerce = { string: ((arg) => - ZodString.create({ ...arg, coerce: true })) as (typeof ZodString)["create"], + ZodString.create({ ...arg, coerce: true })) as typeof ZodString["create"], number: ((arg) => - ZodNumber.create({ ...arg, coerce: true })) as (typeof ZodNumber)["create"], + ZodNumber.create({ ...arg, coerce: true })) as typeof ZodNumber["create"], boolean: ((arg) => ZodBoolean.create({ ...arg, coerce: true, - })) as (typeof ZodBoolean)["create"], + })) as typeof ZodBoolean["create"], bigint: ((arg) => - ZodBigInt.create({ ...arg, coerce: true })) as (typeof ZodBigInt)["create"], + ZodBigInt.create({ ...arg, coerce: true })) as typeof ZodBigInt["create"], date: ((arg) => - ZodDate.create({ ...arg, coerce: true })) as (typeof ZodDate)["create"], + ZodDate.create({ ...arg, coerce: true })) as typeof ZodDate["create"], }; export { From d912c3ea41dfa8f5597d0858a78ec8540cdd80d2 Mon Sep 17 00:00:00 2001 From: Colin McDonnell Date: Tue, 7 Feb 2023 23:48:23 -0800 Subject: [PATCH 7/7] Lint fix --- deno/lib/__tests__/object.test.ts | 4 ++-- deno/lib/__tests__/transformer.test.ts | 2 +- src/__tests__/object.test.ts | 4 ++-- src/__tests__/transformer.test.ts | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/deno/lib/__tests__/object.test.ts b/deno/lib/__tests__/object.test.ts index 3090fb6ac..99b81c95d 100644 --- a/deno/lib/__tests__/object.test.ts +++ b/deno/lib/__tests__/object.test.ts @@ -111,8 +111,8 @@ test("catchall inference", () => { .catchall(z.number()); const d1 = o1.parse({ first: "asdf", num: 1243 }); - util.assertEqual(true); - util.assertEqual(true); + util.assertEqual(true); + util.assertEqual(true); }); test("catchall overrides strict", () => { diff --git a/deno/lib/__tests__/transformer.test.ts b/deno/lib/__tests__/transformer.test.ts index 818aa49cb..9a1f92951 100644 --- a/deno/lib/__tests__/transformer.test.ts +++ b/deno/lib/__tests__/transformer.test.ts @@ -202,7 +202,7 @@ test("preprocess", () => { const value = schema.parse("asdf"); expect(value).toEqual(["asdf"]); - util.assertEqual<(typeof schema)["_input"], unknown>(true); + util.assertEqual(true); }); test("async preprocess", async () => { diff --git a/src/__tests__/object.test.ts b/src/__tests__/object.test.ts index 3865127cf..e1e7fc532 100644 --- a/src/__tests__/object.test.ts +++ b/src/__tests__/object.test.ts @@ -110,8 +110,8 @@ test("catchall inference", () => { .catchall(z.number()); const d1 = o1.parse({ first: "asdf", num: 1243 }); - util.assertEqual(true); - util.assertEqual(true); + util.assertEqual(true); + util.assertEqual(true); }); test("catchall overrides strict", () => { diff --git a/src/__tests__/transformer.test.ts b/src/__tests__/transformer.test.ts index 8e1f2a598..4af6117f3 100644 --- a/src/__tests__/transformer.test.ts +++ b/src/__tests__/transformer.test.ts @@ -201,7 +201,7 @@ test("preprocess", () => { const value = schema.parse("asdf"); expect(value).toEqual(["asdf"]); - util.assertEqual<(typeof schema)["_input"], unknown>(true); + util.assertEqual(true); }); test("async preprocess", async () => {