Adds tests for date overrides (#6027)

This commit is contained in:
Omar López
2022-12-15 13:19:35 -07:00
committed by GitHub
parent 987756c4d4
commit a54952b41a
5 changed files with 124 additions and 41 deletions
+4 -2
View File
@@ -74,7 +74,7 @@ const DateOverride = ({ workingHours }: { workingHours: WorkingHours[] }) => {
excludedDates={fields.map((field) => yyyymmdd(field.ranges[0].start))}
onChange={(ranges) => append({ ranges })}
Trigger={
<Button color="secondary" StartIcon={Icon.FiPlus}>
<Button color="secondary" StartIcon={Icon.FiPlus} data-testid="add-override">
Add an override
</Button>
}
@@ -128,7 +128,9 @@ export default function Availability({ schedule }: { schedule: number }) {
<Controller
control={form.control}
name="name"
render={({ field }) => <EditableHeading isReady={!isLoading} {...field} />}
render={({ field }) => (
<EditableHeading isReady={!isLoading} {...field} data-testid="availablity-title" />
)}
/>
}
subtitle={
+58 -37
View File
@@ -1,10 +1,10 @@
import { useState } from "react";
import dayjs from "@calcom/dayjs";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { RouterOutputs, trpc } from "@calcom/trpc/react";
import { Shell, SkeletonText } from "@calcom/ui";
import useRouterQuery from "@lib/hooks/useRouterQuery";
type User = RouterOutputs["viewer"]["me"];
export interface IBusySlot {
@@ -16,7 +16,9 @@ export interface IBusySlot {
const AvailabilityView = ({ user }: { user: User }) => {
const { t } = useLocale();
const [selectedDate, setSelectedDate] = useState(dayjs());
const { date, setQuery: setSelectedDate } = useRouterQuery("date");
const selectedDate = dayjs(date);
const formattedSelectedDate = selectedDate.format("YYYY-MM-DD");
const { data, isLoading } = trpc.viewer.availability.user.useQuery(
{
@@ -30,6 +32,17 @@ const AvailabilityView = ({ user }: { user: User }) => {
}
);
const overrides =
data?.dateOverrides.reduce((acc, override) => {
if (
formattedSelectedDate !== dayjs(override.start).format("YYYY-MM-DD") &&
formattedSelectedDate !== dayjs(override.end).format("YYYY-MM-DD")
)
return acc;
acc.push({ ...override, source: "Date override" });
return acc;
}, [] as IBusySlot[]) || [];
return (
<div className="max-w-xl overflow-hidden rounded-md bg-white shadow">
<div className="px-4 py-5 sm:p-6">
@@ -37,9 +50,9 @@ const AvailabilityView = ({ user }: { user: User }) => {
<input
type="date"
className="inline h-8 border-none p-0"
defaultValue={selectedDate.format("YYYY-MM-DD")}
defaultValue={formattedSelectedDate}
onChange={(e) => {
if (e.target.value) setSelectedDate(dayjs(e.target.value));
if (e.target.value) setSelectedDate(e.target.value);
}}
/>
<small className="block text-neutral-400">{t("hover_over_bold_times_tip")}</small>
@@ -49,39 +62,47 @@ const AvailabilityView = ({ user }: { user: User }) => {
{t("your_day_starts_at")} {convertMinsToHrsMins(user.startTime)}
</div>
</div>
{isLoading ? (
<>
<SkeletonText className="block h-16 w-full" />
<SkeletonText className="block h-16 w-full" />
</>
) : data && data.busy.length > 0 ? (
data.busy
.sort((a: IBusySlot, b: IBusySlot) => (a.start > b.start ? -1 : 1))
.map((slot: IBusySlot) => (
<div
key={dayjs(slot.start).format("HH:mm")}
className="overflow-hidden rounded-md bg-neutral-100">
<div className="px-4 py-5 text-black sm:p-6">
{t("calendar_shows_busy_between")}{" "}
<span className="font-medium text-neutral-800" title={dayjs(slot.start).format("HH:mm")}>
{dayjs(slot.start).format("HH:mm")}
</span>{" "}
{t("and")}{" "}
<span className="font-medium text-neutral-800" title={dayjs(slot.end).format("HH:mm")}>
{dayjs(slot.end).format("HH:mm")}
</span>{" "}
{t("on")} {dayjs(slot.start).format("D")}{" "}
{t(dayjs(slot.start).format("MMMM").toLowerCase())} {dayjs(slot.start).format("YYYY")}
{slot.title && ` - (${slot.title})`}
{slot.source && <small>{` - (source: ${slot.source})`}</small>}
{(() => {
if (isLoading)
return (
<>
<SkeletonText className="block h-16 w-full" />
<SkeletonText className="block h-16 w-full" />
</>
);
if (data && (data.busy.length > 0 || overrides.length > 0))
return [...data.busy, ...overrides]
.sort((a: IBusySlot, b: IBusySlot) => (a.start > b.start ? -1 : 1))
.map((slot: IBusySlot) => (
<div
key={dayjs(slot.start).format("HH:mm")}
className="overflow-hidden rounded-md bg-neutral-100"
data-testid="troubleshooter-busy-time">
<div className="px-4 py-5 text-black sm:p-6">
{t("calendar_shows_busy_between")}{" "}
<span
className="font-medium text-neutral-800"
title={dayjs(slot.start).format("HH:mm")}>
{dayjs(slot.start).format("HH:mm")}
</span>{" "}
{t("and")}{" "}
<span className="font-medium text-neutral-800" title={dayjs(slot.end).format("HH:mm")}>
{dayjs(slot.end).format("HH:mm")}
</span>{" "}
{t("on")} {dayjs(slot.start).format("D")}{" "}
{t(dayjs(slot.start).format("MMMM").toLowerCase())} {dayjs(slot.start).format("YYYY")}
{slot.title && ` - (${slot.title})`}
{slot.source && <small>{` - (source: ${slot.source})`}</small>}
</div>
</div>
</div>
))
) : (
<div className="overflow-hidden rounded-md bg-neutral-100">
<div className="px-4 py-5 text-black sm:p-6">{t("calendar_no_busy_slots")}</div>
</div>
)}
));
return (
<div className="overflow-hidden rounded-md bg-neutral-100">
<div className="px-4 py-5 text-black sm:p-6">{t("calendar_no_busy_slots")}</div>
</div>
);
})()}
<div className="bg-brand dark:bg-darkmodebrand overflow-hidden rounded-md">
<div className="text-brandcontrast dark:text-darkmodebrandcontrast px-4 py-2 sm:px-6">
+54
View File
@@ -0,0 +1,54 @@
import { expect } from "@playwright/test";
import dayjs from "@calcom/dayjs";
import { test } from "./lib/fixtures";
test.describe.configure({ mode: "parallel" });
test.describe("Availablity tests", () => {
test.beforeEach(async ({ page, users }) => {
const user = await users.create();
await user.login();
await page.goto("/availability");
// We wait until loading is finished
await page.waitForSelector('[data-testid="schedules"]');
});
test.afterEach(async ({ users }) => {
await users.deleteAll();
});
test("Date Overrides", async ({ page }) => {
await test.step("Can add a date override", async () => {
await page.locator('[data-testid="schedules"] > li a').click();
await page.locator('[data-testid="add-override"]').click();
await page.locator('[id="modal-title"]').waitFor();
await page.locator('[data-testid="incrementMonth"]').click();
await page.locator('[data-testid="day"][data-disabled="false"]').nth(0).click();
await page.locator('[data-testid="date-override-mark-unavailable"]').click();
await page.locator('[data-testid="add-override-submit-btn"]').click();
await expect(page.locator('[data-testid="date-overrides-list"] > li')).toHaveCount(1);
await page.locator('[form="availability-form"][type="submit"]').click();
});
await test.step("Date override is displayed in troubleshooter", async () => {
const response = await page.waitForResponse("**/api/trpc/viewer.availability.schedule.update?batch=1");
const json = await response.json();
// @ts-expect-error trust me bro
const date = json[0].result.data.json.schedule.availability.find((a) => !!a.date);
const troubleshooterURL = `/availability/troubleshoot?date=${dayjs(date.date).format("YYYY-MM-DD")}`;
await page.goto(troubleshooterURL);
await expect(page.locator('[data-testid="troubleshooter-busy-time"]')).toHaveCount(1);
});
});
test("Availablity pages", async ({ page }) => {
await test.step("Can add a new schedule", async () => {
await page.locator('[data-testid="new-schedule"]').click();
await page.locator('[id="name"]').fill("More working hours");
page.locator('[type="submit"]').click();
await expect(page.locator("[data-testid=availablity-title]")).toHaveValue("More working hours");
});
});
});
@@ -146,10 +146,16 @@ const DateOverrideForm = ({
label={t("date_overrides_mark_all_day_unavailable_one")}
checked={datesUnavailable}
onCheckedChange={setDatesUnavailable}
data-testid="date-override-mark-unavailable"
/>
</div>
<div className="flex flex-row-reverse">
<Button className="ml-2" color="primary" type="submit" disabled={!date}>
<Button
className="ml-2"
color="primary"
type="submit"
disabled={!date}
data-testid="add-override-submit-btn">
{value ? t("date_overrides_update_btn") : t("date_overrides_add_btn")}
</Button>
<DialogClose onClick={onClose} />
@@ -38,7 +38,7 @@ const DateOverrideList = ({
};
return (
<ul className="rounded border border-gray-200">
<ul className="rounded border border-gray-200" data-testid="date-overrides-list">
{items.map((item, index) => (
<li key={item.id} className="flex justify-between border-b px-5 py-4 last:border-b-0">
<div>