Skip to content
Closed
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
159 changes: 81 additions & 78 deletions packages/route/test/route-validation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,103 +2,106 @@ import { expect, test } from "vitest";
import z from "zod";
import { dredgeRoute } from "../source/route";
import { useValidate } from "../source/route-invocation";
import { describe } from "node:test";

test("simple validation", async () => {
const route = dredgeRoute()
.path("/a/:string/:number/:boolean")
.params({
string: z.string(),
number: z.number(),
boolean: z.boolean(),
})
.queries({
sstring: z.string(),
snumber: z.number(),
sboolean: z.boolean(),
})
.post()
.input(z.enum(["a", "b", "c"]));
describe("useValidate", () => {
test("resolves", async () => {
const route = dredgeRoute()
.path("/a/:string/:number/:boolean")
.params({
string: z.string(),
number: z.number(),
boolean: z.boolean(),
})
.queries({
sstring: z.string(),
snumber: z.number(),
sboolean: z.boolean(),
})
.post()
.input(z.enum(["a", "b", "c"]));

const validated = await useValidate(route)({
method: "POST",
url: "",
queries: {
sstring: ["world"],
snumber: [2],
sboolean: [false],
},
data: "a",
params: {
const validated = await useValidate(route)({
method: "POST",
url: "",
queries: {
sstring: ["world"],
snumber: [2],
sboolean: [false],
},
data: "a",
params: {
string: "hello",
number: 1,
boolean: true,
},
headers: {},
});

expect(validated.params).toStrictEqual({
string: "hello",
number: 1,
boolean: true,
},
headers: {},
});
});

expect(validated.params).toStrictEqual({
string: "hello",
number: 1,
boolean: true,
expect(validated.queries).toStrictEqual({
sstring: ["world"],
snumber: [2],
sboolean: [false],
});
});

expect(validated.queries).toStrictEqual({
sstring: ["world"],
snumber: [2],
sboolean: [false],
test("resolves given the optional searchParam", async () => {
const route = dredgeRoute()
.path("/test")
.queries({
required: z.string(),
optional: z.string().optional(),
})
.get();

expect(
useValidate(route)({
method: "GET",
url: "/test?required=i am required",
queries: {
required: ["i am required"],
},
params: {},
headers: {},
}),
).resolves.toMatchObject({
queries: {
required: ["i am required"],
},
});
});
});

test("optional searchParam should work", async () => {
const route = dredgeRoute()
.path("/test")
.queries({
required: z.string(),
optional: z.string().optional(),
})
.get();
test("returns along with unspecified query in schema", async () => {
const route = dredgeRoute()
.path("/test")
.queries({
i: z.number(),
o: z.string().optional(),
})
.get();

expect(
useValidate(route)({
const validated = await useValidate(route)({
method: "GET",
url: "/test?required=i am required",
url: "/test",
queries: {
required: ["i am required"],
i: [1],
a: ["apple"],
b: ["ball"],
},
params: {},
headers: {},
}),
).resolves.toMatchObject({
queries: {
required: ["i am required"],
},
});
});

test("unSpecified searchParam should work", async () => {
const route = dredgeRoute()
.path("/test")
.queries({
i: z.number(),
o: z.string().optional(),
})
.get();
});

const validated = await useValidate(route)({
method: "GET",
url: "/test",
queries: {
expect(validated.queries).toStrictEqual({
i: [1],
a: ["apple"],
b: ["ball"],
},
params: {},
headers: {},
});

expect(validated.queries).toStrictEqual({
i: [1],
a: ["apple"],
b: ["ball"],
});
});
});
45 changes: 32 additions & 13 deletions packages/types/test/route.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,16 @@ describe("route.options()", () => {
});
});

describe("req", () => {
test("data should be any, if middleware is defined before defining the method", () => {
describe("req.data", () => {
test("infers `any` when middleware is defined before defining method", () => {
dredgeRoute()
.path("/test")
.use((req) => {
expectTypeOf(req.data).toBeAny();
});
});

test("req.data for get, delete and head should be undefined", () => {
test("infers `undefined` when method is get, delete or head", () => {
dredgeRoute()
.path("/test")
.get()
Expand Down Expand Up @@ -84,7 +84,7 @@ describe("req", () => {
});
});

test("req.data should always be any in error for method which takes data", () => {
test("infers `any` for error middleware", () => {
dredgeRoute()
.path("/test")
.error((_err, req) => {
Expand Down Expand Up @@ -119,7 +119,7 @@ describe("req", () => {
});
});

test("req.data for post, put and patch should be any, if parser is not given", () => {
test("infers `any` when parser is not provided and method is post, put or patch", () => {
dredgeRoute()
.path("/test")
.post()
Expand All @@ -145,7 +145,7 @@ describe("req", () => {
});
});

test("req.data should have correct type", () => {
test("infers the type provided to input for usual middleware", () => {
dredgeRoute()
.path("/test")
.post()
Expand Down Expand Up @@ -173,7 +173,9 @@ describe("req", () => {
expectTypeOf(req.data).toBeNull();
});
});
});

describe("req", () => {
test("req.param()", () => {
dredgeRoute()
.path("/test/:paramI/a/:paramII")
Expand Down Expand Up @@ -340,16 +342,23 @@ describe("req", () => {
});

describe("res", () => {
test("res.header", () => {
test("res.header() returns `Record<string, string>` when given no argument", () => {
dredgeRoute()
.use((_req, res) => {
expectTypeOf(res.header()).toEqualTypeOf<Record<string, string>>();
})
.error((_err, _req, res) => {
expectTypeOf(res.header()).toEqualTypeOf<Record<string, string>>();
});
});
test("res.header() returns `string | undefined` when given a string argument", () => {
dredgeRoute()
.use((_req, res) => {
expectTypeOf(res.header("content-type")).toEqualTypeOf<
string | undefined
>();
})
.error((_err, _req, res) => {
expectTypeOf(res.header()).toEqualTypeOf<Record<string, string>>();
expectTypeOf(res.header("content-type")).toEqualTypeOf<
string | undefined
>();
Expand Down Expand Up @@ -638,7 +647,7 @@ describe("res", () => {
expectTypeOf<EDataIV>().toBeNever();
});

test("res.end and responseData", () => {
test("responseData infers the type provided to res.end() when output has not been called", () => {
const route = dredgeRoute()
.path("/test")
.get()
Expand All @@ -652,7 +661,7 @@ describe("res", () => {
expectTypeOf<OData>().toEqualTypeOf<"this is string">();
});

test("route.output and responseData", () => {
test("responseData infers the type provided to route.output()", () => {
const route = dredgeRoute()
.path("/test")
.get()
Expand All @@ -667,7 +676,7 @@ describe("res", () => {
expectTypeOf<OData>().toEqualTypeOf<"a" | "b" | "c">();
});

test("res.data should always be `any`", () => {
test("res.data infers `any`", () => {
dredgeRoute()
.path("/test")
.get()
Expand Down Expand Up @@ -707,16 +716,26 @@ describe("res", () => {
});
});

test("res.status and res.statusText", () => {
test("res.status infers `number | undefined`", () => {
dredgeRoute()
.path("/test")
.get()
.use((_req, res) => {
expectTypeOf(res.status).toEqualTypeOf<number | undefined>();
expectTypeOf(res.statusText).toEqualTypeOf<string | undefined>();
})
.error((_err, _req, res) => {
expectTypeOf(res.status).toEqualTypeOf<number | undefined>();
});
});

test("res.statusText infers `string | undefined`", () => {
dredgeRoute()
.path("/test")
.get()
.use((_req, res) => {
expectTypeOf(res.statusText).toEqualTypeOf<string | undefined>();
})
.error((_err, _req, res) => {
expectTypeOf(res.statusText).toEqualTypeOf<string | undefined>();
});
});
Expand Down
Loading