feat: adds tests for api keys endpoints

This commit is contained in:
Agusti Fernandez Pardo
2022-03-26 01:40:43 +01:00
parent 9e8be659c5
commit 12a7129e5a
10 changed files with 115 additions and 20 deletions
@@ -0,0 +1,92 @@
import handleapiKeyEdit from "@api/api-keys/[id]/edit";
import { createMocks } from "node-mocks-http";
import prisma from "@calcom/prisma";
import {stringifyISODate} from "@lib/utils/stringifyISODate";
describe("PATCH /api/api-keys/[id]/edit with valid id and body updates an apiKey-type", () => {
it("returns a message with the specified apiKeys", async () => {
const { req, res } = createMocks({
method: "PATCH",
query: {
id: "cl16zg6860000wwylnsgva00b",
},
body: {
note: "Updated note",
},
});
const apiKey = await prisma.apiKey.findUnique({ where: { id: req.query.id } });
await handleapiKeyEdit(req, res);
expect(res._getStatusCode()).toBe(200);
expect(JSON.parse(res._getData())).toEqual({ data: {...apiKey, createdAt: stringifyISODate(apiKey?.createdAt), expiresAt: stringifyISODate(apiKey?.expiresAt)} });
});
});
// describe("PATCH /api/api-keys/[id]/edit with invalid id returns 404", () => {
// it("returns a message with the specified apiKeys", async () => {
// const { req, res } = createMocks({
// method: "PATCH",
// query: {
// id: "cl16zg6860000wwylnsgva00a",
// },
// body: {
// note: "Updated note",
// },
// });
// const apiKey = await prisma.apiKey.findUnique({ where: { id: req.query.id } });
// await handleapiKeyEdit(req, res);
// expect(res._getStatusCode()).toBe(404);
// if (apiKey) apiKey.note = "Updated note";
// expect(JSON.parse(res._getData())).toStrictEqual({ "error": {
// "clientVersion": "3.10.0",
// "code": "P2025",
// "meta": {
// "cause": "Record to update not found.",
// },
// },
// "message": "apiKey with ID cl16zg6860000wwylnsgva00a not found and wasn't updated", });
// });
// });
describe("PATCH /api/api-keys/[id]/edit with valid id and no body returns 200 with an apiKey with no note and default expireAt", () => {
it("returns a message with the specified apiKeys", async () => {
const apiKey = await prisma.apiKey.create({data:{} });
const { req, res } = createMocks({
method: "PATCH",
query: {
id: apiKey?.id,
},
});
await handleapiKeyEdit(req, res);
expect(apiKey?.note).toBeNull();
expect(res._getStatusCode()).toBe(200);
expect(JSON.parse(res._getData())).toEqual({ data: {...apiKey, createdAt: stringifyISODate(apiKey?.createdAt), expiresAt: stringifyISODate(apiKey?.expiresAt)} });
});
});
describe("POST /api/api-keys/[id]/edit fails, only PATCH allowed", () => {
it("returns a message with the specified apiKeys", async () => {
const { req, res } = createMocks({
method: "POST", // This POST method is not allowed
query: {
id: "cl16zg6860000wwylnsgva00b",
},
body: {
note: "Updated note",
},
});
await handleapiKeyEdit(req, res);
expect(res._getStatusCode()).toBe(405);
expect(JSON.parse(res._getData())).toStrictEqual({ message: "Only PATCH Method allowed for updating API keys" });
});
});
afterAll((done) => {
prisma.$disconnect().then();
done();
});
+1 -3
View File
@@ -2,10 +2,8 @@ import handleApiKey from "@api/api-keys/[id]";
import { createMocks } from "node-mocks-http";
import prisma from "@calcom/prisma";
import {stringifyISODate} from "@lib/utils/stringifyISODate";
const stringifyISODate = (date: Date|undefined): string => {
return `${date?.toISOString()}`
}
describe("GET /api/api-keys/[id] with valid id as string returns an apiKey", () => {
it("returns a message with the specified apiKeys", async () => {
const { req, res } = createMocks({
@@ -16,7 +16,7 @@ describe("PATCH /api/event-types/[id]/edit with valid id and body updates an eve
length: 1,
},
});
const event = await prisma.eventType.findUnique({ where: { id: 2 } });
const event = await prisma.eventType.findUnique({ where: { id: parseInt(req.query.id) } });
await handleEventTypeEdit(req, res);
expect(res._getStatusCode()).toBe(200);
@@ -38,7 +38,7 @@ describe("PATCH /api/event-types/[id]/edit with invalid id returns 404", () => {
length: 1,
},
});
const event = await prisma.eventType.findUnique({ where: { id: 2 } });
const event = await prisma.eventType.findUnique({ where: { id: parseInt(req.query.id) } });
await handleEventTypeEdit(req, res);
expect(res._getStatusCode()).toBe(404);
+3
View File
@@ -0,0 +1,3 @@
export const stringifyISODate = (date: Date|undefined): string => {
return `${date?.toISOString()}`
}
+1 -1
View File
@@ -3,7 +3,7 @@ import { z } from "zod";
const schemaApiKey = z
.object({
expiresAt: z.string().optional(), // default is 30 days
expiresAt: z.date().optional(), // default is 30 days
note: z.string().min(1).optional(),
})
.strict(); // Adding strict so that we can disallow passing in extra fields
+3 -3
View File
@@ -3,7 +3,7 @@ import { z } from "zod";
// Extracted out as utility function so can be reused
// at different endpoints that require this validation.
const schemaQueryId = z
const schemaQueryIdAsString = z
.object({
// since nextjs parses query params as strings,
// we need to cast them to numbers using z.transform() and parseInt()
@@ -12,9 +12,9 @@ const schemaQueryId = z
.strict();
const withValidQueryIdString = withValidation({
schema: schemaQueryId,
schema: schemaQueryIdAsString,
type: "Zod",
mode: "query",
});
export { schemaQueryId, withValidQueryIdString };
export { schemaQueryIdAsString, withValidQueryIdString };
+6 -5
View File
@@ -1,10 +1,10 @@
import prisma from "@calcom/prisma";
import { ApiKey } from "@calcom/prisma/client";
import { ApiKey } from "@prisma/client";
import type { NextApiRequest, NextApiResponse } from "next";
import { schemaApiKey, withValidApiKey } from "@lib/validations/apiKey";
import { schemaQueryId, withValidQueryIdString } from "@lib/validations/queryIdString";
import { schemaQueryIdAsString, withValidQueryIdString } from "@lib/validations/queryIdString";
type ResponseData = {
data?: ApiKey;
@@ -14,7 +14,7 @@ type ResponseData = {
export async function editApiKey(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
const { query, body, method } = req;
const safeQuery = await schemaQueryId.safeParse(query);
const safeQuery = await schemaQueryIdAsString.safeParse(query);
const safeBody = await schemaApiKey.safeParse(body);
if (method === "PATCH") {
@@ -25,12 +25,13 @@ export async function editApiKey(req: NextApiRequest, res: NextApiResponse<Respo
}).then(apiKey => {
res.status(200).json({ data: apiKey });
}).catch(error => {
res.status(404).json({ message: `Event type with ID ${safeQuery.data.id} not found and wasn't updated`, error })
console.log(error)
res.status(404).json({ message: `apiKey with ID ${safeQuery.data.id} not found and wasn't updated`, error })
});
}
} else {
// Reject any other HTTP method than POST
res.status(405).json({ message: "Only PATCH Method allowed for updating apiKey-types" });
res.status(405).json({ message: "Only PATCH Method allowed for updating API keys" });
}
}
+3 -3
View File
@@ -1,9 +1,9 @@
import prisma from "@calcom/prisma";
import { ApiKey } from "@calcom/prisma/client";
import { ApiKey } from "@prisma/client";
import type { NextApiRequest, NextApiResponse } from "next";
import { schemaQueryId, withValidQueryIdString } from "@lib/validations/queryIdString";
import { schemaQueryIdAsString, withValidQueryIdString } from "@lib/validations/queryIdString";
type ResponseData = {
data?: ApiKey;
@@ -13,7 +13,7 @@ type ResponseData = {
export async function apiKey(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
const { query, method } = req;
const safe = await schemaQueryId.safeParse(query);
const safe = await schemaQueryIdAsString.safeParse(query);
if (safe.success) {
if (method === "GET") {
const apiKey = await prisma.apiKey.findUnique({ where: { id: safe.data.id } });
+1 -1
View File
@@ -12,7 +12,7 @@ export default async function apiKey(req: NextApiRequest, res: NextApiResponse<R
const apiKeys = await prisma.apiKey.findMany({});
res.status(200).json({ data: { ...apiKeys } });
} catch (error) {
console.log(error);
// console.log(error);
// FIXME: Add zod for validation/error handling
res.status(400).json({ error: error });
}
+3 -2
View File
@@ -1,6 +1,7 @@
import prisma from "@calcom/prisma";
import { ApiKey } from "@calcom/prisma/client";import type { NextApiRequest, NextApiResponse } from "next";
import { ApiKey } from "@calcom/prisma/client";
import type { NextApiRequest, NextApiResponse } from "next";
import { schemaApiKey, withValidApiKey } from "@lib/validations/apiKey";
@@ -23,7 +24,7 @@ async function createApiKey(req: NextApiRequest, res: NextApiResponse<ResponseDa
})
.then((apiKey) => res.status(201).json({ data: apiKey }))
.catch((error) => {
console.log(error);
// console.log(error);
res.status(400).json({ message: "Could not create apiKey", error: error })
}
)