* refactor: apply biome formatting to apps/web (batch 1) Formats apps/web non-modules directories: - apps/web/app - apps/web/lib - apps/web/pages - apps/web/styles - apps/web/server - apps/web/test - Root-level .ts and .mjs files Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: apply biome formatting to apps/web/modules (batch 2) Formats smaller apps/web/modules directories: - onboarding, data-table, users, apps, auth - integration-attribute-sync, shell, availability - feature-flags, team, webhooks, getting-started - feature-opt-in, troubleshooter, schedules, notifications - signup-view.tsx Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: apply biome formatting to apps/web/modules (batch 3) Formats medium apps/web/modules directories: - bookings - event-types - insights - embed Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: apply biome formatting to apps/web/modules/ee (batch 4) Formats apps/web/modules/ee directory. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: apply biome formatting to apps/web (batch 5) Formats remaining apps/web directories: - apps/web/modules/settings - apps/web/modules/booking-audit - apps/web/playwright Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: apply biome formatting to apps/web/components (batch 6) Formats remaining apps/web/components files. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: apply biome formatting to new apps/web files from main Formats newly added/modified files from main merge: - WorkflowStepContainer.tsx (resolved merge conflicts) - Newly moved files (blocklist, form-builder, schedules, etc.) - Other files modified in main Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: apply biome formatting to new apps/web files from main Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
116 lines
3.6 KiB
TypeScript
116 lines
3.6 KiB
TypeScript
import { describe, expect, it, vi } from "vitest";
|
|
|
|
import dayjs from "@calcom/dayjs";
|
|
import { getCheckBookingLimitsService } from "@calcom/features/di/containers/BookingLimits";
|
|
import type { IntervalLimit } from "@calcom/lib/intervalLimits/intervalLimitSchema";
|
|
import { validateIntervalLimitOrder } from "@calcom/lib/intervalLimits/validateIntervalLimitOrder";
|
|
|
|
const mockCountBookingsByEventTypeAndDateRange = vi.fn();
|
|
vi.mock("@calcom/features/bookings/repositories/BookingRepository", () => ({
|
|
BookingRepository: vi.fn().mockImplementation(function () {
|
|
return {
|
|
countBookingsByEventTypeAndDateRange: mockCountBookingsByEventTypeAndDateRange,
|
|
};
|
|
}),
|
|
}));
|
|
|
|
type Mockdata = {
|
|
id: number;
|
|
startDate: Date;
|
|
bookingLimits: IntervalLimit;
|
|
};
|
|
|
|
const MOCK_DATA: Mockdata = {
|
|
id: 1,
|
|
startDate: dayjs("2022-09-30T09:00:00+01:00").toDate(),
|
|
bookingLimits: {
|
|
PER_DAY: 1,
|
|
},
|
|
};
|
|
|
|
const checkBookingLimitsService = getCheckBookingLimitsService();
|
|
|
|
describe("Check Booking Limits Tests", () => {
|
|
it("Should return no errors", async () => {
|
|
mockCountBookingsByEventTypeAndDateRange.mockResolvedValue(0);
|
|
expect(
|
|
checkBookingLimitsService.checkBookingLimits(MOCK_DATA.bookingLimits, MOCK_DATA.startDate, MOCK_DATA.id)
|
|
).resolves.toBeTruthy();
|
|
});
|
|
it("Should throw an error", async () => {
|
|
mockCountBookingsByEventTypeAndDateRange.mockResolvedValue(2);
|
|
expect(
|
|
checkBookingLimitsService.checkBookingLimits(MOCK_DATA.bookingLimits, MOCK_DATA.startDate, MOCK_DATA.id)
|
|
).rejects.toThrowError();
|
|
});
|
|
|
|
it("Should pass with multiple booking limits", async () => {
|
|
mockCountBookingsByEventTypeAndDateRange.mockResolvedValue(0);
|
|
expect(
|
|
checkBookingLimitsService.checkBookingLimits(
|
|
{
|
|
PER_DAY: 1,
|
|
PER_WEEK: 2,
|
|
},
|
|
MOCK_DATA.startDate,
|
|
MOCK_DATA.id
|
|
)
|
|
).resolves.toBeTruthy();
|
|
});
|
|
it("Should pass with multiple booking limits with one undefined", async () => {
|
|
mockCountBookingsByEventTypeAndDateRange.mockResolvedValue(0);
|
|
|
|
expect(
|
|
checkBookingLimitsService.checkBookingLimits(
|
|
{
|
|
PER_DAY: 1,
|
|
PER_WEEK: undefined,
|
|
},
|
|
MOCK_DATA.startDate,
|
|
MOCK_DATA.id
|
|
)
|
|
).resolves.toBeTruthy();
|
|
});
|
|
it("Should handle multiple limits correctly", async () => {
|
|
mockCountBookingsByEventTypeAndDateRange.mockResolvedValue(1);
|
|
expect(
|
|
checkBookingLimitsService.checkBookingLimit({
|
|
key: "PER_DAY",
|
|
limitingNumber: 2,
|
|
eventStartDate: MOCK_DATA.startDate,
|
|
eventId: MOCK_DATA.id,
|
|
})
|
|
).resolves.not.toThrow();
|
|
mockCountBookingsByEventTypeAndDateRange.mockResolvedValue(3);
|
|
expect(
|
|
checkBookingLimitsService.checkBookingLimit({
|
|
key: "PER_WEEK",
|
|
limitingNumber: 2,
|
|
eventStartDate: MOCK_DATA.startDate,
|
|
eventId: MOCK_DATA.id,
|
|
})
|
|
).rejects.toThrowError();
|
|
});
|
|
});
|
|
|
|
describe("Booking limit validation", () => {
|
|
it("Should validate a correct limit", () => {
|
|
expect(validateIntervalLimitOrder({ PER_DAY: 3, PER_MONTH: 5 })).toBe(true);
|
|
});
|
|
|
|
it("Should invalidate an incorrect limit", () => {
|
|
expect(validateIntervalLimitOrder({ PER_DAY: 9, PER_MONTH: 5 })).toBe(false);
|
|
});
|
|
|
|
it("Should validate a correct limit with 'gaps' ", () => {
|
|
expect(validateIntervalLimitOrder({ PER_DAY: 9, PER_YEAR: 25 })).toBe(true);
|
|
});
|
|
|
|
it("Should validate a correct limit with equal values ", () => {
|
|
expect(validateIntervalLimitOrder({ PER_DAY: 1, PER_YEAR: 1 })).toBe(true);
|
|
});
|
|
it("Should validate a correct with empty", () => {
|
|
expect(validateIntervalLimitOrder({})).toBe(true);
|
|
});
|
|
});
|