217 lines
6.7 KiB
TypeScript
217 lines
6.7 KiB
TypeScript
import { Booking, WebhookTriggerEvents } from "@prisma/client";
|
|
import { Request, Response } from "express";
|
|
import { NextApiRequest, NextApiResponse } from "next";
|
|
import { createMocks } from "node-mocks-http";
|
|
|
|
import sendPayload from "@calcom/api/lib/utils/sendPayload";
|
|
import handler from "@calcom/api/pages/api/bookings/_post";
|
|
import dayjs from "@calcom/dayjs";
|
|
import { buildEventType, buildWebhook, buildBooking } from "@calcom/lib/test/builder";
|
|
import prisma from "@calcom/prisma";
|
|
|
|
import { prismaMock } from "../../../../../tests/config/singleton";
|
|
|
|
type CustomNextApiRequest = NextApiRequest & Request;
|
|
type CustomNextApiResponse = NextApiResponse & Response;
|
|
jest.mock("@calcom/api/lib/utils/sendPayload");
|
|
|
|
describe("POST /api/bookings", () => {
|
|
describe("Errors", () => {
|
|
test("Missing required data", async () => {
|
|
const { req, res } = createMocks<CustomNextApiRequest, CustomNextApiResponse>({
|
|
method: "POST",
|
|
body: {},
|
|
});
|
|
|
|
await handler(req, res);
|
|
|
|
expect(res._getStatusCode()).toBe(400);
|
|
expect(JSON.parse(res._getData())).toEqual(
|
|
expect.objectContaining({
|
|
message:
|
|
"'invalid_type' in 'eventTypeId': Required; 'invalid_type' in 'title': Required; 'invalid_type' in 'startTime': Required; 'invalid_type' in 'startTime': Required; 'invalid_type' in 'endTime': Required; 'invalid_type' in 'endTime': Required",
|
|
})
|
|
);
|
|
});
|
|
|
|
test("Invalid eventTypeId", async () => {
|
|
const { req, res } = createMocks<CustomNextApiRequest, CustomNextApiResponse>({
|
|
method: "POST",
|
|
body: {
|
|
title: "test",
|
|
eventTypeId: 2,
|
|
startTime: dayjs().toDate(),
|
|
endTime: dayjs().add(1, "day").toDate(),
|
|
},
|
|
prisma,
|
|
});
|
|
|
|
prismaMock.eventType.findUnique.mockResolvedValue(null);
|
|
|
|
await handler(req, res);
|
|
|
|
expect(res._getStatusCode()).toBe(400);
|
|
expect(JSON.parse(res._getData())).toEqual(
|
|
expect.objectContaining({
|
|
message: "Invalid eventTypeId.",
|
|
})
|
|
);
|
|
});
|
|
|
|
test("Missing recurringCount", async () => {
|
|
const { req, res } = createMocks<CustomNextApiRequest, CustomNextApiResponse>({
|
|
method: "POST",
|
|
body: {
|
|
title: "test",
|
|
eventTypeId: 2,
|
|
startTime: dayjs().toDate(),
|
|
endTime: dayjs().add(1, "day").toDate(),
|
|
},
|
|
prisma,
|
|
});
|
|
|
|
prismaMock.eventType.findUnique.mockResolvedValue(
|
|
buildEventType({ recurringEvent: { freq: 2, count: 12, interval: 1 } })
|
|
);
|
|
|
|
await handler(req, res);
|
|
|
|
expect(res._getStatusCode()).toBe(400);
|
|
expect(JSON.parse(res._getData())).toEqual(
|
|
expect.objectContaining({
|
|
message: "Missing recurringCount.",
|
|
})
|
|
);
|
|
});
|
|
|
|
test("Invalid recurringCount", async () => {
|
|
const { req, res } = createMocks<CustomNextApiRequest, CustomNextApiResponse>({
|
|
method: "POST",
|
|
body: {
|
|
title: "test",
|
|
eventTypeId: 2,
|
|
startTime: dayjs().toDate(),
|
|
endTime: dayjs().add(1, "day").toDate(),
|
|
recurringCount: 15,
|
|
},
|
|
prisma,
|
|
});
|
|
|
|
prismaMock.eventType.findUnique.mockResolvedValue(
|
|
buildEventType({ recurringEvent: { freq: 2, count: 12, interval: 1 } })
|
|
);
|
|
|
|
await handler(req, res);
|
|
|
|
expect(res._getStatusCode()).toBe(400);
|
|
expect(JSON.parse(res._getData())).toEqual(
|
|
expect.objectContaining({
|
|
message: "Invalid recurringCount.",
|
|
})
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("Success", () => {
|
|
describe("Regular event-type", () => {
|
|
test("Creates one single booking", async () => {
|
|
const { req, res } = createMocks<CustomNextApiRequest, CustomNextApiResponse>({
|
|
method: "POST",
|
|
body: {
|
|
title: "test",
|
|
eventTypeId: 2,
|
|
startTime: dayjs().toDate(),
|
|
endTime: dayjs().add(1, "day").toDate(),
|
|
},
|
|
prisma,
|
|
});
|
|
|
|
prismaMock.eventType.findUnique.mockResolvedValue(buildEventType());
|
|
|
|
await handler(req, res);
|
|
|
|
expect(prismaMock.booking.create).toHaveBeenCalledTimes(1);
|
|
});
|
|
});
|
|
|
|
describe("Recurring event-type", () => {
|
|
test("Creates multiple bookings", async () => {
|
|
const { req, res } = createMocks<CustomNextApiRequest, CustomNextApiResponse>({
|
|
method: "POST",
|
|
body: {
|
|
title: "test",
|
|
eventTypeId: 2,
|
|
startTime: dayjs().toDate(),
|
|
endTime: dayjs().add(1, "day").toDate(),
|
|
recurringCount: 12,
|
|
},
|
|
prisma,
|
|
});
|
|
|
|
prismaMock.eventType.findUnique.mockResolvedValue(
|
|
buildEventType({ recurringEvent: { freq: 2, count: 12, interval: 1 } })
|
|
);
|
|
|
|
Array.from(Array(12).keys()).map(async () => {
|
|
prismaMock.booking.create.mockResolvedValue(buildBooking());
|
|
});
|
|
|
|
prismaMock.webhook.findMany.mockResolvedValue([]);
|
|
|
|
await handler(req, res);
|
|
const data = JSON.parse(res._getData());
|
|
|
|
expect(prismaMock.booking.create).toHaveBeenCalledTimes(12);
|
|
expect(res._getStatusCode()).toBe(201);
|
|
expect(data.message).toEqual("Bookings created successfully.");
|
|
expect(data.bookings.length).toEqual(12);
|
|
});
|
|
});
|
|
test("Notifies multiple bookings", async () => {
|
|
const { req, res } = createMocks<CustomNextApiRequest, CustomNextApiResponse>({
|
|
method: "POST",
|
|
body: {
|
|
title: "test",
|
|
eventTypeId: 2,
|
|
startTime: dayjs().toDate(),
|
|
endTime: dayjs().add(1, "day").toDate(),
|
|
recurringCount: 12,
|
|
},
|
|
prisma,
|
|
});
|
|
|
|
prismaMock.eventType.findUnique.mockResolvedValue(
|
|
buildEventType({ recurringEvent: { freq: 2, count: 12, interval: 1 } })
|
|
);
|
|
|
|
const createdAt = new Date();
|
|
Array.from(Array(12).keys()).map(async () => {
|
|
prismaMock.booking.create.mockResolvedValue(buildBooking({ createdAt }));
|
|
});
|
|
|
|
const mockedWebhooks = [
|
|
buildWebhook({
|
|
subscriberUrl: "http://mockedURL1.com",
|
|
createdAt,
|
|
eventTypeId: 1,
|
|
secret: "secret1",
|
|
}),
|
|
buildWebhook({
|
|
subscriberUrl: "http://mockedURL2.com",
|
|
createdAt,
|
|
eventTypeId: 2,
|
|
secret: "secret2",
|
|
}),
|
|
];
|
|
prismaMock.webhook.findMany.mockResolvedValue(mockedWebhooks);
|
|
|
|
await handler(req, res);
|
|
const data = JSON.parse(res._getData());
|
|
|
|
expect(sendPayload).toHaveBeenCalledTimes(24);
|
|
expect(data.message).toEqual("Bookings created successfully.");
|
|
expect(data.bookings.length).toEqual(12);
|
|
});
|
|
});
|
|
});
|