* feat: RECORDING_TRANSCRIPTION_READY webhook * refactor: split into diff files and restructuring * feat: finish batch processor finished * chore: types * fix: type error * chore: change name of triggger * test: add unit test * fix: type * fix: type err * chore: test * feat: add booking reference repository and other imp * chore: log * fix: import * chore: type error * fix: update test * fix: test * fix: test * fix: add timeout * chore: move beforeEach * Mock missing env variables to test. These vars are not set in CI --------- Co-authored-by: Hariom <hariombalhara@gmail.com>
245 lines
6.8 KiB
TypeScript
245 lines
6.8 KiB
TypeScript
import {
|
|
createBookingScenario,
|
|
getScenarioData,
|
|
TestData,
|
|
getDate,
|
|
getMockBookingAttendee,
|
|
getOrganizer,
|
|
getBooker,
|
|
} from "@calcom/web/test/utils/bookingScenario/bookingScenario";
|
|
import { expectWebhookToHaveBeenCalledWith } from "@calcom/web/test/utils/bookingScenario/expects";
|
|
|
|
import type { Request, Response } from "express";
|
|
import type { NextApiRequest, NextApiResponse } from "next";
|
|
import { createMocks } from "node-mocks-http";
|
|
import { describe, afterEach, test, vi, beforeEach, beforeAll } from "vitest";
|
|
|
|
import { appStoreMetadata } from "@calcom/app-store/apps.metadata.generated";
|
|
import { getRoomNameFromRecordingId, getBatchProcessorJobAccessLink } from "@calcom/app-store/dailyvideo/lib";
|
|
import { getDownloadLinkOfCalVideoByRecordingId } from "@calcom/core/videoClient";
|
|
import prisma from "@calcom/prisma";
|
|
import { WebhookTriggerEvents } from "@calcom/prisma/enums";
|
|
import { BookingStatus } from "@calcom/prisma/enums";
|
|
import handler from "@calcom/web/pages/api/recorded-daily-video";
|
|
|
|
type CustomNextApiRequest = NextApiRequest & Request;
|
|
type CustomNextApiResponse = NextApiResponse & Response;
|
|
beforeAll(() => {
|
|
// Setup env vars
|
|
vi.stubEnv("SENDGRID_API_KEY", "FAKE_SENDGRID_API_KEY");
|
|
vi.stubEnv("SENDGRID_EMAIL", "FAKE_SENDGRID_EMAIL");
|
|
});
|
|
|
|
vi.mock("@calcom/app-store/dailyvideo/lib", () => {
|
|
return {
|
|
getRoomNameFromRecordingId: vi.fn(),
|
|
getBatchProcessorJobAccessLink: vi.fn(),
|
|
};
|
|
});
|
|
|
|
vi.mock("@calcom/core/videoClient", () => {
|
|
return {
|
|
getDownloadLinkOfCalVideoByRecordingId: vi.fn(),
|
|
};
|
|
});
|
|
|
|
const BATCH_PROCESSOR_JOB_FINSISHED_PAYLOAD = {
|
|
version: "1.1.0",
|
|
type: "batch-processor.job-finished",
|
|
id: "77b1cb9e-cd79-43cd-bad6-3ccaccba26be",
|
|
payload: {
|
|
id: "77b1cb9e-cd79-43cd-bad6-3ccaccba26be",
|
|
status: "finished",
|
|
input: {
|
|
sourceType: "recordingId",
|
|
recordingId: "eb9e84de-783e-4e14-875d-94700ee4b976",
|
|
},
|
|
output: {
|
|
transcription: [
|
|
{
|
|
format: "json",
|
|
s3Config: {
|
|
key: "transcript.json",
|
|
bucket: "daily-bucket",
|
|
region: "us-west-2",
|
|
},
|
|
},
|
|
{
|
|
format: "srt",
|
|
s3Config: {
|
|
key: "transcript.srt",
|
|
bucket: "daily-bucket",
|
|
region: "us-west-2",
|
|
},
|
|
},
|
|
{
|
|
format: "txt",
|
|
s3Config: {
|
|
key: "transcript.txt",
|
|
bucket: "daily-bucket",
|
|
region: "us-west-2",
|
|
},
|
|
},
|
|
{
|
|
format: "vtt",
|
|
s3Config: {
|
|
key: "transcript.vtt",
|
|
bucket: "daily-bucket",
|
|
region: "us-west-2",
|
|
},
|
|
},
|
|
],
|
|
},
|
|
},
|
|
event_ts: 1717688213.803,
|
|
};
|
|
|
|
const timeout = process.env.CI ? 5000 : 20000;
|
|
|
|
const TRANSCRIPTION_ACCESS_LINK = {
|
|
id: "MOCK_ID",
|
|
preset: "transcript",
|
|
status: "finished",
|
|
transcription: [
|
|
{
|
|
format: "json",
|
|
link: "https://download.json",
|
|
},
|
|
{
|
|
format: "srt",
|
|
link: "https://download.srt",
|
|
},
|
|
],
|
|
};
|
|
|
|
describe("Handler: /api/recorded-daily-video", () => {
|
|
beforeEach(() => {
|
|
fetchMock.resetMocks();
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.resetAllMocks();
|
|
fetchMock.resetMocks();
|
|
});
|
|
|
|
test(
|
|
`Batch Processor Job finished triggers RECORDING_TRANSCRIPTION_GENERATED webhooks`,
|
|
async () => {
|
|
const organizer = getOrganizer({
|
|
name: "Organizer",
|
|
email: "organizer@example.com",
|
|
id: 101,
|
|
schedules: [TestData.schedules.IstWorkHours],
|
|
});
|
|
|
|
const bookingUid = "n5Wv3eHgconAED2j4gcVhP";
|
|
const iCalUID = `${bookingUid}@Cal.com`;
|
|
const subscriberUrl = "http://my-webhook.example.com";
|
|
const recordingDownloadLink = "https://download-link.com";
|
|
|
|
const { dateString: plus1DateString } = getDate({ dateIncrement: 1 });
|
|
const booker = getBooker({
|
|
email: "booker@example.com",
|
|
name: "Booker",
|
|
});
|
|
|
|
await createBookingScenario(
|
|
getScenarioData({
|
|
webhooks: [
|
|
{
|
|
userId: organizer.id,
|
|
eventTriggers: [WebhookTriggerEvents.RECORDING_TRANSCRIPTION_GENERATED],
|
|
subscriberUrl,
|
|
active: true,
|
|
eventTypeId: 1,
|
|
appId: null,
|
|
},
|
|
],
|
|
eventTypes: [
|
|
{
|
|
id: 1,
|
|
slotInterval: 15,
|
|
length: 15,
|
|
users: [
|
|
{
|
|
id: 101,
|
|
},
|
|
],
|
|
},
|
|
],
|
|
bookings: [
|
|
{
|
|
uid: bookingUid,
|
|
eventTypeId: 1,
|
|
status: BookingStatus.ACCEPTED,
|
|
startTime: `${plus1DateString}T05:00:00.000Z`,
|
|
endTime: `${plus1DateString}T05:15:00.000Z`,
|
|
userId: organizer.id,
|
|
metadata: {
|
|
videoCallUrl: "https://existing-daily-video-call-url.example.com",
|
|
},
|
|
references: [
|
|
{
|
|
type: appStoreMetadata.dailyvideo.type,
|
|
uid: "MOCK_ID",
|
|
meetingId: "MOCK_ID",
|
|
meetingPassword: "MOCK_PASS",
|
|
meetingUrl: "http://mock-dailyvideo.example.com",
|
|
credentialId: null,
|
|
},
|
|
],
|
|
attendees: [
|
|
getMockBookingAttendee({
|
|
id: 2,
|
|
name: booker.name,
|
|
email: booker.email,
|
|
locale: "en",
|
|
timeZone: "Asia/Kolkata",
|
|
noShow: false,
|
|
}),
|
|
],
|
|
iCalUID,
|
|
},
|
|
],
|
|
organizer,
|
|
apps: [TestData.apps["daily-video"]],
|
|
})
|
|
);
|
|
|
|
vi.mocked(getRoomNameFromRecordingId).mockResolvedValue("MOCK_ID");
|
|
vi.mocked(getBatchProcessorJobAccessLink).mockResolvedValue(TRANSCRIPTION_ACCESS_LINK);
|
|
vi.mocked(getDownloadLinkOfCalVideoByRecordingId).mockResolvedValue({
|
|
download_link: recordingDownloadLink,
|
|
});
|
|
|
|
const { req, res } = createMocks<CustomNextApiRequest, CustomNextApiResponse>({
|
|
method: "POST",
|
|
body: BATCH_PROCESSOR_JOB_FINSISHED_PAYLOAD,
|
|
prisma,
|
|
});
|
|
|
|
await handler(req, res);
|
|
|
|
await expectWebhookToHaveBeenCalledWith(subscriberUrl, {
|
|
triggerEvent: WebhookTriggerEvents.RECORDING_TRANSCRIPTION_GENERATED,
|
|
payload: {
|
|
type: "Test Booking Title",
|
|
uid: bookingUid,
|
|
downloadLinks: {
|
|
transcription: TRANSCRIPTION_ACCESS_LINK.transcription,
|
|
recording: recordingDownloadLink,
|
|
},
|
|
organizer: {
|
|
email: organizer.email,
|
|
name: organizer.name,
|
|
timeZone: organizer.timeZone,
|
|
language: { locale: "en" },
|
|
utcOffset: 330,
|
|
},
|
|
},
|
|
});
|
|
},
|
|
timeout
|
|
);
|
|
});
|