Skip to content

Commit d6cec25

Browse files
committed
chore: add tests
1 parent 89f8e05 commit d6cec25

File tree

8 files changed

+161
-53
lines changed

8 files changed

+161
-53
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,6 @@ UserInterfaceState.xcuserstate
2525
.rpt2_cache/
2626

2727
lib
28+
.pnpm-store
2829

2930
.rollup.cache

example/.eslintrc.json

Lines changed: 0 additions & 3 deletions
This file was deleted.

example/playwright.config.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import { defineConfig } from '@playwright/test';
1+
import { defineConfig } from "@playwright/test";
22

33
export default defineConfig({
44
// Run your local dev server before starting the tests
55
webServer: {
6-
command: 'pnpm dev',
7-
url: 'http://127.0.0.1:3000',
6+
command: "pnpm dev",
7+
url: "http://127.0.0.1:3000",
88
reuseExistingServer: !process.env.CI,
9-
stdout: "pipe",
109
},
10+
retries: 3,
1111
});

example/src/pages/api/zodRoute/[test].ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { z, zodRoute, zodRouteSchema } from "@ddadaal/next-typed-api-routes-runt
22

33
export const ZodRouteSchema = zodRouteSchema({
44
method: "POST",
5-
body: z.object({ info: z.string() }),
5+
body: z.object({ error: z.boolean() }),
66
query: z.object({ test: z.string() }),
77
responses: {
88
200: z.object({ hello: z.string() }),
@@ -11,5 +11,9 @@ export const ZodRouteSchema = zodRouteSchema({
1111
});
1212

1313
export default zodRoute(ZodRouteSchema, async (req) => {
14-
return { 200: { hello: `${req.body.info} + ${req.query.test}` } };
14+
if (req.body.error) {
15+
return { 404: { error: "error" }};
16+
} else {
17+
return { 200: { hello: `${req.query.test}` } };
18+
}
1519
});

example/src/pages/index.tsx

Lines changed: 74 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,52 +2,88 @@ import type { NextPage } from "next";
22
import { useState } from "react";
33
import { api } from "src/apis/api";
44

5-
const Home: NextPage = () => {
5+
export const ZodRouteTestDiv = () => {
6+
7+
const [resp, setResp] = useState("");
8+
9+
return (
10+
<div id="zodRoute">
11+
<button id="button" onClick={() => {
12+
api.zodRoute({ body: { error: false }, query: { test: "123" } })
13+
.then((resp) => {
14+
setResp(resp.hello);
15+
});
16+
}}>
17+
Call ZodRoute
18+
</button>
19+
<p id="p">
20+
{resp}
21+
</p>
22+
</div>
23+
);
24+
};
25+
26+
export const AjvRouteTestDiv = () => {
627

728
const [username, setUsername] = useState("");
829
const [password, setPassword] = useState("");
30+
const [result, setResult] = useState("");
31+
32+
return (
33+
<div id="ajvRoute">
34+
<p>To successfully login, the credentials must</p>
35+
<ul>
36+
<li>The username must be in email format.</li>
37+
<li>The password must be of length &gt;= 8</li>
38+
<li>The username and password must be equal.</li>
39+
</ul>
40+
<p>If the password === nullnull, response will be 403 with no body.</p>
41+
<form onSubmit={async (e) => {
42+
e.preventDefault();
43+
const resp = await api.login({ query: { username, password, testNumberQuery: 3 } })
44+
.httpError(401, ({ reason }) => {
45+
setResult(`401 ${reason}`);
46+
})
47+
.httpError(403, () => {
48+
setResult("403");
49+
});
50+
51+
setResult("Completed." + resp.token);
52+
}}
53+
>
54+
<label htmlFor="Email">Email</label>
55+
<input
56+
id="username"
57+
placeholder="Must be in email format"
58+
onChange={(e) => setUsername(e.target.value)}
59+
/>
60+
<label htmlFor="password">Password</label>
61+
<input
62+
id="password"
63+
placeholder="Must be of length >= 8"
64+
onChange={(e) => setPassword(e.target.value)}
65+
/>
66+
<button id="submit" type="submit">
67+
Submit
68+
</button>
69+
</form>
70+
<p id="result">{result}</p>
71+
</div>
72+
);
73+
};
74+
75+
const Home: NextPage = () => {
76+
977

1078
return (
1179
<div>
1280
<h1>next-typed-api-routes example</h1>
1381
<div>
14-
<p>To successfully login, the credentials must</p>
15-
<ul>
16-
<li>The username must be in email format.</li>
17-
<li>The password must be of length &gt;= 8</li>
18-
<li>The username and password must be equal.</li>
19-
</ul>
20-
<p>If the password === nullnull, response will be 403 with no body.</p>
21-
<form onSubmit={async (e) => {
22-
e.preventDefault();
23-
const resp = await
24-
api.login({ query: { username, password, testNumberQuery: 3 } })
25-
.httpError(401, ({ reason }) => {
26-
alert("401 Failed. Reason: " + reason);
27-
})
28-
.httpError(403, () => {
29-
alert("403");
30-
});
31-
32-
alert("Completed." + resp);
33-
}}
34-
>
35-
<label htmlFor="Email">Email</label>
36-
<input
37-
id="username"
38-
placeholder="Must be in email format"
39-
onChange={(e) => setUsername(e.target.value)}
40-
/>
41-
<label htmlFor="password">Password</label>
42-
<input
43-
id="password"
44-
placeholder="Must be of length >= 8"
45-
onChange={(e) => setPassword(e.target.value)}
46-
/>
47-
<button type="submit">
48-
Submit
49-
</button>
50-
</form>
82+
<AjvRouteTestDiv />
83+
</div>
84+
85+
<div>
86+
<ZodRouteTestDiv />
5187
</div>
5288
</div>
5389
);

example/tests/apis.test.ts

Lines changed: 74 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,78 @@
1+
import { expect, test } from "@playwright/test";
2+
13
import { api } from "../src/apis/api";
2-
import { test, expect } from '@playwright/test';
34

4-
test("should call zodRoute", async ({ page }) => {
5-
const resp = await api.zodRoute({ body: { info: "test" }, query: { test: "123" } });
5+
test("should call zodRoute", async () => {
6+
const resp = await api.zodRoute({ body: { error: false }, query: { test: "123" } });
7+
8+
expect(resp.hello).toBe("123");
9+
});
10+
11+
test("zodRoute should handler error", async () => {
12+
const error = await api.zodRoute({ body: { error: true }, query: { test: "123" } })
13+
.httpError(404, (err) => {
14+
expect(err.error).toBe("error");
15+
return err;
16+
})
17+
.then(() => undefined)
18+
.catch((e) => e);
19+
20+
expect(error).toBeDefined();
21+
});
22+
23+
test("should call zodRoute from browser", async ({ page }) => {
24+
await page.goto("http://localhost:3000");
25+
26+
await page.click("#zodRoute button");
27+
28+
const text = await page.$("#zodRoute p");
29+
30+
expect(await text?.innerText()).toBe("123");
31+
});
32+
33+
test("should call register", async () => {
34+
const resp = await api.register({ body: { username: "123", password: "123" } });
35+
36+
expect(resp.token).toBe("123123");
37+
});
38+
39+
test("should call login", async () => {
40+
const resp = await api.login({ query: { password: "[email protected]", username: "[email protected]" } });
41+
42+
expect(resp.token).toBe("[email protected]");
43+
});
44+
45+
test("should validate email", async () => {
46+
const resp = await api.login({ query: { password: "123", username: "123" } })
47+
.httpError(400, (err: any) => {
48+
expect(err.code).toBe("QUERY_VALIDATION_ERROR");
49+
return err;
50+
}).then(() => undefined, (e) => e);
51+
52+
expect(resp).toBeDefined();
53+
54+
});
55+
56+
test("should call login from browser", async ({ page }) => {
57+
await page.goto("http://localhost:3000");
58+
59+
await page.fill("#ajvRoute #username", "[email protected]");
60+
await page.fill("#ajvRoute #password", "[email protected]");
61+
await page.click("#ajvRoute #submit");
62+
63+
const text = await page.$("#ajvRoute #result");
64+
65+
expect(await text?.innerText()).toBe("[email protected]");
66+
});
67+
68+
test("should handle error in browser", async ({ page }) => {
69+
await page.goto("http://localhost:3000");
70+
71+
await page.fill("#ajvRoute #username", "[email protected]");
72+
await page.fill("#ajvRoute #password", "12312312");
73+
await page.click("#ajvRoute #submit");
74+
75+
const text = await page.$("#ajvRoute #result");
676

7-
expect(resp.hello).toBe("test 123");
77+
expect(await text?.innerText()).toBe("401 NotExists");
878
});

packages/runtime/src/route/ajvRoute.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ export function route<S extends AnySchema>(
8282
) => OrPromise<Partial<S["responses"]> | void>,
8383
): typeof handler {
8484

85-
if (validators) {
85+
if (!validators) {
8686
const schemas = JSON.parse(fs.readFileSync("./api-routes-schemas.json", "utf8"));
8787
validators = createValidatorsFromSchema(schemas);
8888
}

packages/runtime/src/route/zodRoute.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export function zodRoute<TSchema extends ZodRouteSchema>(
5151
}
5252

5353
if (schema.body) {
54-
const result = schema.body.safeParse(req.query);
54+
const result = schema.body.safeParse(req.body);
5555
if (!result.success) {
5656
returnError(res, "BODY", result.error);
5757
return;

0 commit comments

Comments
 (0)