diff --git a/packages/features/availability/lib/getAggregatedAvailability/getAggregatedAvailability.test.ts b/packages/features/availability/lib/getAggregatedAvailability/getAggregatedAvailability.test.ts index 539c0100ec..5781360925 100644 --- a/packages/features/availability/lib/getAggregatedAvailability/getAggregatedAvailability.test.ts +++ b/packages/features/availability/lib/getAggregatedAvailability/getAggregatedAvailability.test.ts @@ -1,8 +1,6 @@ -import { describe, it, expect } from "vitest"; - import type { Dayjs } from "@calcom/dayjs"; import dayjs from "@calcom/dayjs"; - +import { describe, expect, it } from "vitest"; import { getAggregatedAvailability } from "./getAggregatedAvailability"; // Helper to check if a time range overlaps with availability @@ -13,6 +11,87 @@ const isAvailable = (availability: { start: Dayjs; end: Dayjs }[], range: { star }; describe("getAggregatedAvailability", () => { + it("exposes round robin availability when at least one non-fixed host is available", () => { + const userAvailability = [ + { + dateRanges: [], + oooExcludedDateRanges: [ + { start: dayjs("2025-01-23T11:00:00.000Z"), end: dayjs("2025-01-23T11:30:00.000Z") }, + ], + user: { isFixed: false }, + }, + { + dateRanges: [], + oooExcludedDateRanges: [], + user: { isFixed: false }, + }, + ]; + + const result = getAggregatedAvailability(userAvailability, "ROUND_ROBIN"); + + expect( + isAvailable(result, { + start: dayjs("2025-01-23T11:00:00.000Z"), + end: dayjs("2025-01-23T11:30:00.000Z"), + }) + ).toBe(true); + }); + + it("exposes collective availability only when every host is available", () => { + const userAvailability = [ + { + dateRanges: [{ start: dayjs("2025-01-23T11:00:00.000Z"), end: dayjs("2025-01-23T12:00:00.000Z") }], + oooExcludedDateRanges: [ + { start: dayjs("2025-01-23T11:00:00.000Z"), end: dayjs("2025-01-23T12:00:00.000Z") }, + ], + user: { isFixed: true }, + }, + { + dateRanges: [{ start: dayjs("2025-01-23T11:30:00.000Z"), end: dayjs("2025-01-23T12:30:00.000Z") }], + oooExcludedDateRanges: [ + { start: dayjs("2025-01-23T11:30:00.000Z"), end: dayjs("2025-01-23T12:30:00.000Z") }, + ], + user: { isFixed: true }, + }, + ]; + + const result = getAggregatedAvailability(userAvailability, "COLLECTIVE"); + + expect(result).toEqual([ + { + start: dayjs("2025-01-23T11:30:00.000Z"), + end: dayjs("2025-01-23T12:00:00.000Z"), + }, + ]); + }); + + it("removes a busy round robin host from eligibility while preserving another available host", () => { + const userAvailability = [ + { + dateRanges: [{ start: dayjs("2025-01-23T11:00:00.000Z"), end: dayjs("2025-01-23T12:00:00.000Z") }], + // Busy-calendar filtering happens before aggregation, leaving no eligible range for this host. + oooExcludedDateRanges: [], + user: { isFixed: false }, + }, + { + dateRanges: [{ start: dayjs("2025-01-23T11:00:00.000Z"), end: dayjs("2025-01-23T12:00:00.000Z") }], + oooExcludedDateRanges: [ + { start: dayjs("2025-01-23T11:00:00.000Z"), end: dayjs("2025-01-23T12:00:00.000Z") }, + ], + user: { isFixed: false }, + }, + ]; + + const result = getAggregatedAvailability(userAvailability, "ROUND_ROBIN"); + + expect( + isAvailable(result, { + start: dayjs("2025-01-23T11:00:00.000Z"), + end: dayjs("2025-01-23T12:00:00.000Z"), + }) + ).toBe(true); + }); + // rr-host availability used to combine into erroneous slots, this confirms it no longer happens it("should not merge RR availability resulting in an unavailable slot due to overlap", () => { const userAvailability = [