* Add credits section to billing * create seperate router for credits * add stripe checkout session * schema changes + code improvements * rename to creditBalance * custom quantify input with error message * add checkout session completed webhook endpoint * fix typo * UI fixes * add payCredits handler * add error toast message * allow scheduling sms up as close to 15 minutes in the future * schedule at most 2 hours in advance * webhook to pay for sent sms * continued work on twilio callback * code clean up * further implementation for credit handling * add migration * object as param for scheduleSMS * object as param for sendSMS * fix TrpcSessionUser imports * fix imports * add db changes * add cron job for price setting * twilio status callback to create expense log * remove unused code * set up low credit balance email * fixes for buying credits * fixes in api/twilio/webhook * add test to save credits to credits balance * fix typos * add new helper function chargeCredits * expand twilioProvider * fix type errors * adjust tests * type errors * clean up * clean up * fix subscription active check * remove some user/org related code * more changes to remove user/org support * send emails seperatly to admins * fixes for team billing page * fix stripe success url * fixes to creating expense log * email imrovements and more * get monthly team price from stripe * fix import * fix monthly credits calculation * finsih low credit balance warning email * credit balance limit reached email * create CreditService * cancel SMS and send as email instead * add messageDispatcher * fix type error * fix type error * fix type error * fix import * fix unit test * clean up twilioProvider * clean up chckSmsPrices/route * add missing translations * add skeleton loader * add admin check to get handler * code clean up + fixes * improve scheduling with fallback * fix type error * add bookingUid to handleSendingSMS * add unit tests for creditService * add more tests to credit-service.test.ts * add test for cancelScheduledMessagesAndScheduleEmails * fix test and type error * add back resolve * fix empty resolve * adjust limitReachedAt logic * address mrge comment on styling * add getAdminMembership to repository * twilio/webhook clean up (feedback) * feedback - clean up * remove todo comment * clean up twilio/webhook * code clean up * add use client * add createOneTimeCheckout to stripe service * refactor repository pattern * small fixes + clean up * fix type error * add missing import * fix hasAvailableCredits for user * force-dynamic * rename credits to creditBalance * fix stripe import * remove not needed code * fix e2e tests * improve low balance warning email * dynamic-import CreditService * index.ts * add user logic checkSmsPrices endpoint * fix e2e tests * remove dynamic import CreditService * Revert "remove dynamic import CreditService" This reverts commit e272978a7ff3fc5a04139e656c9f8d2c84a40dda. * no need to dynamic-import credit service * Revert "no need to dynamic-import credit service" This reverts commit ba5ae488d08979a65fb47b5d0722cda9f45d6ea0. * fix twilio webhook * add userId support in checkout.session.completed * clean up code * only select id in getAdminMembership * revert billing/package.json * fix type checks * fix type checks * adjust hasAvailableCredits function * fixes for checkout sessioned completed * add UI for user * fix type errors * adds requires credits badge * remove team check from update.handler * clean up inlcude statements * fix credit-service tests * add tests * fix type errors * fix type errors * fix and add tests * imrove badge * code clean up * add reminderScheduler test * add additional credits as title * fixes for warningSentAt and limitReachedAt * mock stripe --------- Co-authored-by: CarinaWolli <wollencarina@gmail.com> Co-authored-by: hbjORbj <sldisek783@gmail.com> Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com> Co-authored-by: Peer Richelsen <peeroke@gmail.com>
131 lines
3.9 KiB
TypeScript
131 lines
3.9 KiB
TypeScript
import prismaMock from "../../../../../../tests/libs/__mocks__/prismaMock";
|
|
|
|
import { describe, it, expect, beforeEach, vi } from "vitest";
|
|
|
|
import { WorkflowMethods } from "@calcom/prisma/enums";
|
|
|
|
import { sendOrScheduleWorkflowEmails } from "./providers/emailProvider";
|
|
import * as twilioProvider from "./providers/twilioProvider";
|
|
import { cancelScheduledMessagesAndScheduleEmails } from "./reminderScheduler";
|
|
|
|
vi.mock("@calcom/features/ee/workflows/lib/reminders/providers/twilioProvider", () => ({
|
|
cancelSMS: vi.fn(),
|
|
getMessageBody: vi.fn().mockResolvedValue("Test message body"),
|
|
}));
|
|
|
|
vi.mock("@calcom/features/ee/workflows/lib/reminders/providers/emailProvider", () => ({
|
|
sendOrScheduleWorkflowEmails: vi.fn(),
|
|
}));
|
|
|
|
describe("reminderScheduler", () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
describe("cancelScheduledMessagesAndScheduleEmails", () => {
|
|
it("should cancel SMS messages and schedule emails for team", async () => {
|
|
prismaMock.membership.findMany.mockResolvedValue([]);
|
|
|
|
const mockScheduledMessages = [
|
|
{
|
|
id: 1,
|
|
referenceId: "sms-123",
|
|
workflowStep: {
|
|
action: "SMS_ATTENDEE",
|
|
},
|
|
scheduledDate: new Date(),
|
|
uuid: "uuid-123",
|
|
booking: {
|
|
attendees: [
|
|
{
|
|
email: "attendee@example.com",
|
|
locale: "en",
|
|
},
|
|
],
|
|
user: {
|
|
email: "organizer@example.com",
|
|
},
|
|
},
|
|
},
|
|
];
|
|
|
|
prismaMock.workflowReminder.findMany.mockResolvedValue(mockScheduledMessages);
|
|
|
|
prismaMock.workflowReminder.updateMany.mockResolvedValue({ count: 1 });
|
|
|
|
await cancelScheduledMessagesAndScheduleEmails({ teamId: 10 });
|
|
|
|
expect(twilioProvider.cancelSMS).toHaveBeenCalledWith("sms-123");
|
|
|
|
expect(sendOrScheduleWorkflowEmails).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
to: ["attendee@example.com"],
|
|
replyTo: "organizer@example.com",
|
|
referenceUid: "uuid-123",
|
|
})
|
|
);
|
|
|
|
const callArgs = prismaMock.workflowReminder.findMany.mock.calls[0][0];
|
|
expect(callArgs.where.workflowStep.workflow.OR).toEqual([{ userId: { in: [] } }, { teamId: 10 }]);
|
|
});
|
|
|
|
it("should cancel SMS messages and schedule emails for user", async () => {
|
|
prismaMock.membership.findMany.mockResolvedValue([]);
|
|
|
|
const mockScheduledMessages = [
|
|
{
|
|
id: 1,
|
|
referenceId: "sms-456",
|
|
workflowStep: {
|
|
action: "SMS_ATTENDEE",
|
|
},
|
|
scheduledDate: new Date(),
|
|
uuid: "uuid-456",
|
|
booking: {
|
|
attendees: [
|
|
{
|
|
email: "user-attendee@example.com",
|
|
locale: "en",
|
|
},
|
|
],
|
|
user: {
|
|
email: "user-organizer@example.com",
|
|
},
|
|
},
|
|
},
|
|
];
|
|
|
|
prismaMock.workflowReminder.findMany.mockResolvedValue(mockScheduledMessages);
|
|
|
|
prismaMock.workflowReminder.updateMany.mockResolvedValue({ count: 1 });
|
|
|
|
await cancelScheduledMessagesAndScheduleEmails({ userId: 11 });
|
|
|
|
const callArgs = prismaMock.workflowReminder.findMany.mock.calls[0][0];
|
|
expect(callArgs.where.workflowStep.workflow.OR).toEqual([{ userId: { in: [11] } }]);
|
|
|
|
expect(twilioProvider.cancelSMS).toHaveBeenCalledWith("sms-456");
|
|
|
|
expect(sendOrScheduleWorkflowEmails).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
to: ["user-attendee@example.com"],
|
|
replyTo: "user-organizer@example.com",
|
|
referenceUid: "uuid-456",
|
|
})
|
|
);
|
|
|
|
expect(prismaMock.workflowReminder.updateMany).toHaveBeenCalledWith({
|
|
where: {
|
|
id: {
|
|
in: [1],
|
|
},
|
|
},
|
|
data: {
|
|
method: WorkflowMethods.EMAIL,
|
|
referenceId: null,
|
|
},
|
|
});
|
|
});
|
|
});
|
|
});
|