UNPKG

devextreme

Version:

JavaScript/TypeScript Component Suite for Responsive Web Development

963 lines (962 loc) • 46.6 kB
/** * DevExtreme (esm/__internal/scheduler/appointment_popup/appointment_popup.test.js) * Version: 25.2.8 * Build date: Mon Jun 08 2026 * * Copyright (c) 2012 - 2026 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ import { afterEach, beforeEach, describe, expect, it, jest } from "@jest/globals"; import { loadMessages, locale } from "../../../localization"; import { fireEvent } from "@testing-library/dom"; import DOMComponent from "../../core/widget/dom_component"; import fx from "../../../common/core/animation/fx"; import { createAppointmentPopup, disposeAppointmentPopups } from "../__tests__/__mock__/create_appointment_popup"; import { setupSchedulerTestEnvironment } from "../__tests__/__mock__/m_mock_scheduler"; describe("Isolated AppointmentPopup environment", () => { beforeEach(() => { fx.off = true }); afterEach(() => { disposeAppointmentPopups(); fx.off = false }); it("should render popup with form fields", async () => { const { POM: POM } = await createAppointmentPopup(); expect(POM.element).toBeTruthy(); expect(POM.dxForm).toBeTruthy() }); it("should display appointment data in form", async () => { const { POM: POM } = await createAppointmentPopup({ appointmentData: { text: "My Meeting", startDate: new Date(2021, 3, 26, 9, 30), endDate: new Date(2021, 3, 26, 11, 0) } }); expect(POM.getInputValue("subjectEditor")).toBe("My Meeting") }); it("should have Save and Cancel buttons", async () => { const { POM: POM } = await createAppointmentPopup(); expect(POM.saveButton).toBeTruthy(); expect(POM.cancelButton).toBeTruthy() }); it("should call onSave callback on Save click", async () => { const { POM: POM, callbacks: callbacks } = await createAppointmentPopup({ appointmentData: { text: "New Appointment", startDate: new Date(2021, 3, 26, 9, 30), endDate: new Date(2021, 3, 26, 11, 0) } }); POM.saveButton.click(); await new Promise(process.nextTick); expect(callbacks.onSave).toHaveBeenCalledTimes(1); expect(callbacks.onSave).toHaveBeenCalledWith(expect.objectContaining({ text: "New Appointment", startDate: new Date(2021, 3, 26, 9, 30), endDate: new Date(2021, 3, 26, 11, 0) })) }); it("should not call addAppointment or updateAppointment directly", async () => { const { POM: POM, callbacks: callbacks } = await createAppointmentPopup({ appointmentData: { text: "Test", startDate: new Date(2021, 3, 26, 9, 30), endDate: new Date(2021, 3, 26, 11, 0) } }); POM.saveButton.click(); await new Promise(process.nextTick); expect(callbacks.addAppointment).not.toHaveBeenCalled(); expect(callbacks.updateAppointment).not.toHaveBeenCalled() }); it("should display title from config", async () => { const { POM: POM } = await createAppointmentPopup({ title: "Edit Appointment" }); const titleElement = POM.element.querySelector(".dx-toolbar-label"); expect(null === titleElement || void 0 === titleElement ? void 0 : titleElement.textContent).toBe("Edit Appointment") }); it("should hide Save button when readOnly is true", async () => { const { POM: POM } = await createAppointmentPopup({ readOnly: true }); const saveButtons = POM.element.querySelectorAll(".dx-popup-done"); expect(saveButtons.length).toBe(0) }); it("should show Save button when readOnly is false", async () => { const { POM: POM } = await createAppointmentPopup({ readOnly: false }); expect(POM.saveButton).toBeTruthy() }); it("should hide popup on Cancel click", async () => { const { popup: popup, POM: POM } = await createAppointmentPopup(); const visibleBefore = popup.visible; POM.cancelButton.click(); const visibleAfter = popup.visible; expect(visibleBefore).toBe(true); expect(visibleAfter).toBe(false) }); it("should support composite onSave for exclude-from-series scenario", async () => { const updateAppointment = jest.fn(); const addAppointment = jest.fn(() => Promise.resolve()); const sourceAppointment = { text: "Series", recurrenceRule: "FREQ=DAILY" }; const updatedAppointment = { text: "Series", recurrenceException: "20210426" }; const onSave = jest.fn(newAppointment => { updateAppointment(sourceAppointment, updatedAppointment); return addAppointment(newAppointment) }); const { POM: POM } = await createAppointmentPopup({ appointmentData: { text: "Single occurrence", startDate: new Date(2021, 3, 26, 9, 30), endDate: new Date(2021, 3, 26, 11, 0) }, title: "Edit Appointment", onSave: onSave }); POM.saveButton.click(); await new Promise(process.nextTick); expect(onSave).toHaveBeenCalledTimes(1); expect(updateAppointment).toHaveBeenCalledWith(sourceAppointment, updatedAppointment); expect(addAppointment).toHaveBeenCalledWith(expect.objectContaining({ text: "Single occurrence" })) }); describe("allDay switch", () => { const commonAppointment = { text: "common-app", startDate: new Date(2017, 4, 9, 9, 30), endDate: new Date(2017, 4, 9, 11) }; const allDayAppointment = { text: "all-day-app", startDate: new Date(2017, 4, 1), endDate: new Date(2017, 4, 1), allDay: true }; it("should be turned on when opening allDay appointment", async () => { const { POM: POM } = await createAppointmentPopup({ appointmentData: allDayAppointment }); expect(POM.getInputValue("allDayEditor")).toBe("true") }); it("should be turned off when opening non-allDay appointment", async () => { const { POM: POM } = await createAppointmentPopup({ appointmentData: commonAppointment }); expect(POM.getInputValue("allDayEditor")).toBe("false") }); it("should hide time editors when switched on", async () => { const { POM: POM } = await createAppointmentPopup({ appointmentData: commonAppointment }); const startTimeVisibleBefore = POM.isInputVisible("startTimeEditor"); const endTimeVisibleBefore = POM.isInputVisible("endTimeEditor"); POM.getInput("allDayEditor").click(); const startTimeVisibleAfter = POM.isInputVisible("startTimeEditor"); const endTimeVisibleAfter = POM.isInputVisible("endTimeEditor"); expect(startTimeVisibleBefore).toBe(true); expect(endTimeVisibleBefore).toBe(true); expect(startTimeVisibleAfter).toBe(false); expect(endTimeVisibleAfter).toBe(false) }); it("should show time editors when switched off", async () => { const { POM: POM } = await createAppointmentPopup({ appointmentData: allDayAppointment }); const startTimeVisibleBefore = POM.isInputVisible("startTimeEditor"); const endTimeVisibleBefore = POM.isInputVisible("endTimeEditor"); POM.getInput("allDayEditor").click(); const startTimeVisibleAfter = POM.isInputVisible("startTimeEditor"); const endTimeVisibleAfter = POM.isInputVisible("endTimeEditor"); expect(startTimeVisibleBefore).toBe(false); expect(endTimeVisibleBefore).toBe(false); expect(startTimeVisibleAfter).toBe(true); expect(endTimeVisibleAfter).toBe(true) }); it("should reset start to startDayHour and end via getCalculatedEndDate when switched off", async () => { const { POM: POM } = await createAppointmentPopup({ appointmentData: commonAppointment, startDayHour: 9 }); POM.getInput("allDayEditor").click(); POM.getInput("allDayEditor").click(); expect(POM.getInputValue("startDateEditor")).toBe("5/9/2017"); expect(POM.getInputValue("startTimeEditor")).toBe("9:00 AM"); expect(POM.getInputValue("endDateEditor")).toBe("5/9/2017"); expect(POM.getInputValue("endTimeEditor")).toBe("10:00 AM") }); it("should reset to date-only values when switched on after toggling off", async () => { const { POM: POM } = await createAppointmentPopup({ appointmentData: allDayAppointment }); POM.getInput("allDayEditor").click(); POM.getInput("allDayEditor").click(); expect(POM.getInputValue("startDateEditor")).toBe("5/1/2017"); expect(POM.isInputVisible("startTimeEditor")).toBeFalsy(); expect(POM.getInputValue("endDateEditor")).toBe("5/1/2017"); expect(POM.isInputVisible("endTimeEditor")).toBeFalsy() }) }); describe("startDate/endDate editors behavior", () => { const testAppointment = { text: "test app", startDate: new Date(2017, 4, 9, 9, 30), endDate: new Date(2017, 4, 9, 11) }; it("should update endDate when startDate is changed to a value greater than endDate", async () => { const { POM: POM } = await createAppointmentPopup({ appointmentData: testAppointment }); POM.setInputValue("startDateEditor", new Date(2017, 4, 10)); expect(POM.getInputValue("startTimeEditor")).toEqual("9:30 AM"); expect(POM.getInputValue("endDateEditor")).toEqual("5/10/2017"); expect(POM.getInputValue("endTimeEditor")).toEqual("11:00 AM") }); it("should update endDate when startTime is changed to a value greater than endDate time", async () => { const { POM: POM } = await createAppointmentPopup({ appointmentData: testAppointment }); POM.setInputValue("startTimeEditor", new Date(2017, 4, 9, 12)); expect(POM.getInputValue("startDateEditor")).toEqual("5/9/2017"); expect(POM.getInputValue("endDateEditor")).toEqual("5/9/2017"); expect(POM.getInputValue("endTimeEditor")).toEqual("1:30 PM") }); it("should update startDate when endDate is changed to a value less than startDate", async () => { const { POM: POM } = await createAppointmentPopup({ appointmentData: testAppointment }); POM.setInputValue("endDateEditor", new Date(2017, 4, 8)); expect(POM.getInputValue("startDateEditor")).toEqual("5/8/2017"); expect(POM.getInputValue("startTimeEditor")).toEqual("9:30 AM"); expect(POM.getInputValue("endTimeEditor")).toEqual("11:00 AM") }); it("should update startDate when endTime is changed to a value less than startDate time", async () => { const { POM: POM } = await createAppointmentPopup({ appointmentData: testAppointment }); POM.setInputValue("endTimeEditor", new Date(2017, 4, 9, 9, 0)); expect(POM.getInputValue("startDateEditor")).toEqual("5/9/2017"); expect(POM.getInputValue("startTimeEditor")).toEqual("7:30 AM"); expect(POM.getInputValue("endDateEditor")).toEqual("5/9/2017") }); it("should not update endDate when startDate is changed to a value less than endDate", async () => { const { POM: POM } = await createAppointmentPopup({ appointmentData: testAppointment }); POM.setInputValue("startDateEditor", new Date(2017, 4, 8)); expect(POM.getInputValue("startTimeEditor")).toEqual("9:30 AM"); expect(POM.getInputValue("endDateEditor")).toEqual("5/9/2017"); expect(POM.getInputValue("endTimeEditor")).toEqual("11:00 AM") }); it("should not update endDate when startTime is changed to a value less than endDate time", async () => { const { POM: POM } = await createAppointmentPopup({ appointmentData: testAppointment }); POM.setInputValue("startTimeEditor", new Date(2017, 4, 9, 10, 0)); expect(POM.getInputValue("startDateEditor")).toEqual("5/9/2017"); expect(POM.getInputValue("endDateEditor")).toEqual("5/9/2017"); expect(POM.getInputValue("endTimeEditor")).toEqual("11:00 AM") }); it("should not update startDate when endDate is changed to a value greater than startDate", async () => { const { POM: POM } = await createAppointmentPopup({ appointmentData: testAppointment }); POM.setInputValue("endDateEditor", new Date(2017, 4, 10)); expect(POM.getInputValue("startDateEditor")).toEqual("5/9/2017"); expect(POM.getInputValue("startTimeEditor")).toEqual("9:30 AM"); expect(POM.getInputValue("endTimeEditor")).toEqual("11:00 AM") }); it("should not update startDate when endTime is changed to a value greater than startDate time", async () => { const { POM: POM } = await createAppointmentPopup({ appointmentData: testAppointment }); POM.setInputValue("endTimeEditor", new Date(2017, 4, 9, 12)); expect(POM.getInputValue("startDateEditor")).toEqual("5/9/2017"); expect(POM.getInputValue("startTimeEditor")).toEqual("9:30 AM"); expect(POM.getInputValue("endDateEditor")).toEqual("5/9/2017") }) }); it("should propagate firstDayOfWeek to editor calendars and recurrence week day buttons", async () => { var _POM$dxForm$getEditor, _POM$dxForm$getEditor2, _POM$dxForm$getEditor3; const { POM: POM } = await createAppointmentPopup({ appointmentData: { text: "common-app", startDate: new Date(2017, 4, 9, 9, 30), endDate: new Date(2017, 4, 9, 11) }, firstDayOfWeek: 1 }); POM.selectRepeatValue("weekly"); const startDateFDOW = null === (_POM$dxForm$getEditor = POM.dxForm.getEditor("startDateEditor")) || void 0 === _POM$dxForm$getEditor ? void 0 : _POM$dxForm$getEditor.option("calendarOptions.firstDayOfWeek"); const endDateFDOW = null === (_POM$dxForm$getEditor2 = POM.dxForm.getEditor("endDateEditor")) || void 0 === _POM$dxForm$getEditor2 ? void 0 : _POM$dxForm$getEditor2.option("calendarOptions.firstDayOfWeek"); const recurrenceStartFDOW = null === (_POM$dxForm$getEditor3 = POM.dxForm.getEditor("recurrenceStartDateEditor")) || void 0 === _POM$dxForm$getEditor3 ? void 0 : _POM$dxForm$getEditor3.option("calendarOptions.firstDayOfWeek"); const weekDayButtonsText = POM.recurrenceWeekDayButtons.textContent; expect(startDateFDOW).toBe(1); expect(endDateFDOW).toBe(1); expect(recurrenceStartFDOW).toBe(1); expect(weekDayButtonsText).toBe("MTWTFSS") }); describe("Validation", () => { const commonAppointment = { text: "common-app", startDate: new Date(2017, 4, 9, 9, 30), endDate: new Date(2017, 4, 9, 11) }; it.each(["startDateEditor", "startTimeEditor", "endDateEditor", "endTimeEditor"])("should block save when %s is empty", async editorName => { const { POM: POM, callbacks: callbacks } = await createAppointmentPopup({ appointmentData: Object.assign({}, commonAppointment) }); POM.setInputValue(editorName, null); POM.saveButton.click(); await Promise.resolve(); expect(callbacks.onSave).not.toHaveBeenCalled() }); it.each(["startTimeEditor", "endDateEditor", "endTimeEditor"])("should block save in recurrence form when %s is empty", async editorName => { const { POM: POM, callbacks: callbacks } = await createAppointmentPopup({ appointmentData: Object.assign({}, commonAppointment) }); POM.setInputValue(editorName, null); POM.selectRepeatValue("daily"); POM.saveButton.click(); await Promise.resolve(); expect(callbacks.onSave).not.toHaveBeenCalled() }); it("should not block save in recurrence form when startDateEditor is empty", async () => { const { POM: POM, callbacks: callbacks } = await createAppointmentPopup({ appointmentData: Object.assign({}, commonAppointment) }); POM.setInputValue("startDateEditor", null); POM.selectRepeatValue("daily"); const recurrenceStartDate = POM.getInputValue("recurrenceStartDateEditor"); expect(recurrenceStartDate).toBe("5/9/2017"); POM.saveButton.click(); await Promise.resolve(); expect(callbacks.onSave).toHaveBeenCalledTimes(1) }) }); describe("Recurrence Form", () => { const recurringAppointment = { text: "recurring-app", startDate: new Date(2017, 4, 1, 9, 30), endDate: new Date(2017, 4, 1, 11), recurrenceRule: "FREQ=DAILY;COUNT=5" }; const baseAppointment = { text: "Meeting", startDate: new Date(2017, 4, 1, 10, 30), endDate: new Date(2017, 4, 1, 11) }; it("should allow opening recurrence settings when allowUpdating is false", async () => { const { POM: POM } = await createAppointmentPopup({ appointmentData: Object.assign({}, recurringAppointment), editing: { allowUpdating: false }, readOnly: true }); const visibleBefore = POM.isRecurrenceGroupVisible(); POM.recurrenceSettingsButton.click(); const visibleAfter = POM.isRecurrenceGroupVisible(); expect(visibleBefore).toBe(false); expect(visibleAfter).toBe(true) }); it("should close repeat selectbox popup when navigating to recurrence group via settings button", async () => { const { POM: POM } = await createAppointmentPopup({ appointmentData: Object.assign({}, recurringAppointment) }); const repeatEditor = POM.dxForm.getEditor("repeatEditor"); POM.getInput("repeatEditor").click(); const openedBefore = null === repeatEditor || void 0 === repeatEditor ? void 0 : repeatEditor.option("opened"); POM.recurrenceSettingsButton.click(); const openedAfter = null === repeatEditor || void 0 === repeatEditor ? void 0 : repeatEditor.option("opened"); expect(openedBefore).toBe(true); expect(openedAfter).toBe(false) }); it("should have disabled week day buttons when allowUpdating is false", async () => { const { POM: POM } = await createAppointmentPopup({ appointmentData: Object.assign({}, recurringAppointment, { recurrenceRule: "FREQ=WEEKLY;BYDAY=WE,TU,TH,FR,SA" }), editing: { allowUpdating: false }, readOnly: true }); POM.recurrenceSettingsButton.click(); const disabledButtons = POM.recurrenceWeekDayButtons.querySelectorAll(".dx-button.dx-state-disabled"); expect(disabledButtons.length).toBe(7) }); it("should show recurrence group when repeat value is selected", async () => { const { POM: POM } = await createAppointmentPopup(); POM.selectRepeatValue("weekly"); expect(POM.isMainGroupVisible()).toBe(false); expect(POM.isRecurrenceGroupVisible()).toBe(true) }); it("should restore main group when back button is clicked", async () => { const { POM: POM } = await createAppointmentPopup(); POM.selectRepeatValue("weekly"); POM.backButton.click(); expect(POM.isMainGroupVisible()).toBe(true); expect(POM.isRecurrenceGroupVisible()).toBe(false) }); it("should set inert attribute on hidden group when switching forms", async () => { const { POM: POM } = await createAppointmentPopup(); POM.selectRepeatValue("weekly"); expect(POM.mainGroup.getAttribute("inert")).toBe("true"); expect(POM.recurrenceGroup.getAttribute("inert")).toBeNull(); POM.backButton.click(); expect(POM.mainGroup.getAttribute("inert")).toBeNull(); expect(POM.recurrenceGroup.getAttribute("inert")).toBe("true") }); it("should adjust popup height when switching to recurrence form", async () => { const { POM: POM } = await createAppointmentPopup(); POM.selectRepeatValue("weekly"); expect(typeof POM.component.option("height")).toBe("number") }); it("should reset popup height to auto when returning to main form", async () => { const { POM: POM } = await createAppointmentPopup(); POM.selectRepeatValue("weekly"); POM.backButton.click(); expect(POM.component.option("height")).toBe("auto") }); it("should open main form when opening recurring appointment", async () => { const { POM: POM } = await createAppointmentPopup({ appointmentData: Object.assign({}, recurringAppointment) }); expect(POM.isMainGroupVisible()).toBe(true); expect(POM.isRecurrenceGroupVisible()).toBe(false) }); describe("State", () => { it("should have correct input values for appointment with hour frequency", async () => { const { POM: POM } = await createAppointmentPopup({ appointmentData: Object.assign({}, baseAppointment, { recurrenceRule: "FREQ=HOURLY;INTERVAL=2;COUNT=10" }) }); expect(POM.getInputValue("repeatEditor")).toBe("Hourly"); POM.recurrenceSettingsButton.click(); expect(POM.getInputValue("recurrenceStartDateEditor")).toBe("5/1/2017"); expect(POM.getInputValue("recurrenceCountEditor")).toBe("2"); expect(POM.getInputValue("recurrencePeriodEditor")).toBe("Hour(s)"); expect(POM.getInputValue("recurrenceEndCountEditor")).toBe("10 occurrence(s)") }); it("should have correct input values for appointment with daily frequency", async () => { const { POM: POM } = await createAppointmentPopup({ appointmentData: Object.assign({}, baseAppointment, { recurrenceRule: "FREQ=DAILY;INTERVAL=2;COUNT=10" }) }); expect(POM.getInputValue("repeatEditor")).toBe("Daily"); POM.recurrenceSettingsButton.click(); expect(POM.getInputValue("recurrenceStartDateEditor")).toBe("5/1/2017"); expect(POM.getInputValue("recurrenceCountEditor")).toBe("2"); expect(POM.getInputValue("recurrencePeriodEditor")).toBe("Day(s)"); expect(POM.getInputValue("recurrenceEndCountEditor")).toBe("10 occurrence(s)") }); it("should have correct input values for appointment with week frequency", async () => { const { POM: POM } = await createAppointmentPopup({ appointmentData: Object.assign({}, baseAppointment, { recurrenceRule: "FREQ=WEEKLY;INTERVAL=2;BYDAY=MO,WE,FR;COUNT=10" }) }); expect(POM.getInputValue("repeatEditor")).toBe("Weekly"); POM.recurrenceSettingsButton.click(); expect(POM.getInputValue("recurrenceStartDateEditor")).toBe("5/1/2017"); expect(POM.getInputValue("recurrenceCountEditor")).toBe("2"); expect(POM.getInputValue("recurrencePeriodEditor")).toBe("Week(s)"); expect(POM.getWeekDaysSelection()).toEqual([false, true, false, true, false, true, false]); expect(POM.getInputValue("recurrenceEndCountEditor")).toBe("10 occurrence(s)") }); it("should have correct input values for appointment with monthly frequency", async () => { const { POM: POM } = await createAppointmentPopup({ appointmentData: Object.assign({}, baseAppointment, { recurrenceRule: "FREQ=MONTHLY;INTERVAL=2;BYMONTHDAY=1;COUNT=10" }) }); expect(POM.getInputValue("repeatEditor")).toBe("Monthly"); POM.recurrenceSettingsButton.click(); expect(POM.getInputValue("recurrenceStartDateEditor")).toBe("5/1/2017"); expect(POM.getInputValue("recurrenceCountEditor")).toBe("2"); expect(POM.getInputValue("recurrencePeriodEditor")).toBe("Month(s)"); expect(POM.getInputValue("recurrenceDayOfMonthEditor")).toBe("1"); expect(POM.getInputValue("recurrenceEndCountEditor")).toBe("10 occurrence(s)") }); it("should have correct input values for appointment with yearly frequency", async () => { const { POM: POM } = await createAppointmentPopup({ appointmentData: Object.assign({}, baseAppointment, { recurrenceRule: "FREQ=YEARLY;INTERVAL=2;BYMONTHDAY=1;BYMONTH=5;COUNT=10" }) }); expect(POM.getInputValue("repeatEditor")).toBe("Yearly"); POM.recurrenceSettingsButton.click(); expect(POM.getInputValue("recurrenceStartDateEditor")).toBe("5/1/2017"); expect(POM.getInputValue("recurrenceCountEditor")).toBe("2"); expect(POM.getInputValue("recurrencePeriodEditor")).toBe("Year(s)"); expect(POM.getInputValue("recurrenceDayOfYearDayEditor")).toBe("1"); expect(POM.getInputValue("recurrenceDayOfYearMonthEditor")).toBe("May"); expect(POM.getInputValue("recurrenceEndCountEditor")).toBe("10 occurrence(s)") }); it("T1325870: should use current locale for recurrence editors after locale change", async () => { const currentLocale = locale(); loadMessages({ de: { "dxScheduler-recurrenceYearly": "custom yearly", "dxScheduler-recurrenceRepeatYearly": "custom repeat yearly" } }); locale("de"); try { const { POM: POM } = await createAppointmentPopup({ appointmentData: Object.assign({}, baseAppointment, { recurrenceRule: "FREQ=YEARLY;INTERVAL=2;BYMONTHDAY=1;BYMONTH=5;COUNT=10" }) }); expect(POM.getInputValue("repeatEditor")).toBe("custom yearly"); POM.recurrenceSettingsButton.click(); expect(POM.getInputValue("recurrencePeriodEditor")).toBe("Custom repeat yearly"); expect(POM.getInputValue("recurrenceDayOfYearMonthEditor")).toBe("Mai") } finally { locale(currentLocale) } }); it("should have correct input values for appointment with no end", async () => { const { POM: POM } = await createAppointmentPopup({ appointmentData: Object.assign({}, baseAppointment, { recurrenceRule: "FREQ=DAILY;INTERVAL=2" }) }); POM.recurrenceSettingsButton.click(); expect(POM.getInputValue("recurrenceRepeatEndEditor")).toBe("never") }); it("should have correct input values for appointment with end by date", async () => { const { POM: POM } = await createAppointmentPopup({ appointmentData: Object.assign({}, baseAppointment, { recurrenceRule: "FREQ=DAILY;INTERVAL=2;UNTIL=20170601T000000Z" }) }); POM.recurrenceSettingsButton.click(); expect(POM.getInputValue("recurrenceRepeatEndEditor")).toBe("until"); expect(POM.getInputValue("recurrenceEndUntilEditor")).toBe("6/1/2017") }); it("should have correct input values for appointment with end by count", async () => { const { POM: POM } = await createAppointmentPopup({ appointmentData: Object.assign({}, baseAppointment, { recurrenceRule: "FREQ=DAILY;INTERVAL=2;COUNT=10" }) }); POM.recurrenceSettingsButton.click(); expect(POM.getInputValue("recurrenceRepeatEndEditor")).toBe("count"); expect(POM.getInputValue("recurrenceEndCountEditor")).toBe("10 occurrence(s)") }) }); describe("Repeat End Values Preservation", () => { it("should preserve count value when switching between recurrence types", async () => { const { POM: POM } = await createAppointmentPopup({ appointmentData: Object.assign({}, baseAppointment) }); POM.selectRepeatValue("daily"); POM.setInputValue("recurrenceRepeatEndEditor", "count"); POM.setInputValue("recurrenceEndCountEditor", 15); POM.backButton.click(); POM.selectRepeatValue("weekly"); POM.recurrenceSettingsButton.click(); expect(POM.getInputValue("recurrenceEndCountEditor")).toBe("15 occurrence(s)") }); it("should preserve until value when switching between recurrence types", async () => { const testUntilDate = new Date(2017, 5, 16); const { POM: POM } = await createAppointmentPopup({ appointmentData: Object.assign({}, baseAppointment) }); POM.selectRepeatValue("daily"); POM.setInputValue("recurrenceRepeatEndEditor", "until"); POM.setInputValue("recurrenceEndUntilEditor", testUntilDate); POM.backButton.click(); POM.selectRepeatValue("weekly"); POM.recurrenceSettingsButton.click(); expect(POM.getInputValue("recurrenceEndUntilEditor")).toBe("6/16/2017") }) }); describe("Repeat End Editors Disabled State", () => { it.each([ ["never", "FREQ=DAILY"], ["until", "FREQ=DAILY;UNTIL=20170615T000000Z"], ["count", "FREQ=DAILY;COUNT=10"] ])("should set correct disabled state when repeatEnd is %s", async (repeatEndValue, recurrenceRule) => { const { POM: POM } = await createAppointmentPopup({ appointmentData: Object.assign({}, baseAppointment, { recurrenceRule: recurrenceRule }) }); POM.recurrenceSettingsButton.click(); const untilEditor = POM.dxForm.getEditor("recurrenceEndUntilEditor"); const countEditor = POM.dxForm.getEditor("recurrenceEndCountEditor"); expect(null === untilEditor || void 0 === untilEditor ? void 0 : untilEditor.option("disabled")).toBe("until" !== repeatEndValue); expect(null === countEditor || void 0 === countEditor ? void 0 : countEditor.option("disabled")).toBe("count" !== repeatEndValue) }) }); describe("FrequencyEditor focus", () => { afterEach(() => { jest.useRealTimers() }); it("should not be focused when value is changed via API", async () => { const { POM: POM } = await createAppointmentPopup({ appointmentData: Object.assign({}, recurringAppointment) }); POM.recurrenceSettingsButton.click(); const frequencyEditor = POM.dxForm.getEditor("recurrencePeriodEditor"); const frequencyEditorInputElement = POM.getInput("recurrencePeriodEditor"); null === frequencyEditor || void 0 === frequencyEditor || frequencyEditor.option("value", "yearly"); expect(document.activeElement).not.toBe(frequencyEditorInputElement) }); it("should be focused when value is changed via keyboard", async () => { const { POM: POM } = await createAppointmentPopup({ appointmentData: Object.assign({}, recurringAppointment) }); POM.recurrenceSettingsButton.click(); const frequencyEditorInputElement = POM.getInput("recurrencePeriodEditor"); frequencyEditorInputElement.click(); jest.useFakeTimers(); fireEvent.keyDown(frequencyEditorInputElement, { key: "ArrowDown" }); jest.runAllTimers(); expect(document.activeElement).toBe(frequencyEditorInputElement) }) }); it("should set animation offset CSS variable when switching to recurrence form", async () => { const originalGetComputedStyle = window.getComputedStyle; const originalGetBoundingClientRect = Element.prototype.getBoundingClientRect; const originalGetClientRects = Element.prototype.getClientRects; const originalIsVisible = DOMComponent.prototype._isVisible; try { setupSchedulerTestEnvironment({ height: 600, classRects: { "dx-form": { top: 10 }, "dx-scheduler-form-main-group": { top: 60 } } }); const { POM: POM } = await createAppointmentPopup(); POM.selectRepeatValue("weekly"); const animationTop = POM.dxForm.$element()[0].style.getPropertyValue("--dx-scheduler-animation-top"); expect(animationTop).toBe("50px") } finally { window.getComputedStyle = originalGetComputedStyle; Element.prototype.getBoundingClientRect = originalGetBoundingClientRect; Element.prototype.getClientRects = originalGetClientRects; DOMComponent.prototype._isVisible = originalIsVisible } }); it("T1318550: editors with hidden outer label must have labelMode: hidden", async () => { const { POM: POM } = await createAppointmentPopup({ appointmentData: Object.assign({}, baseAppointment, { recurrenceRule: "FREQ=YEARLY;BYMONTHDAY=1;BYMONTH=5" }) }); POM.recurrenceSettingsButton.click(); ["recurrencePeriodEditor", "recurrenceRepeatEndEditor", "recurrenceEndUntilEditor", "recurrenceEndCountEditor", "recurrenceDayOfYearDayEditor"].forEach(name => { var _POM$dxForm$getEditor4; expect(null === (_POM$dxForm$getEditor4 = POM.dxForm.getEditor(name)) || void 0 === _POM$dxForm$getEditor4 ? void 0 : _POM$dxForm$getEditor4.option("labelMode")).toBe("hidden") }) }) }); describe("Customize form items", () => { const appointment = { text: "Meeting", startDate: new Date(2017, 4, 9, 9, 30), endDate: new Date(2017, 4, 9, 11) }; it("should use default form items when editing.form.items is not configured", async () => { const { POM: POM } = await createAppointmentPopup({ appointmentData: Object.assign({}, appointment) }); const formItems = POM.dxForm.option("items") ?? []; expect(formItems.length).toBeGreaterThan(0) }); it("should produce empty form when editing.form.items is empty array", async () => { const { POM: POM } = await createAppointmentPopup({ appointmentData: Object.assign({}, appointment), editing: { form: { items: [] } } }); const formItems = POM.dxForm.option("items") ?? []; expect(formItems.length).toBe(0) }); it("should resolve named group when specified as string in items array", async () => { var _formItems$; const { POM: POM } = await createAppointmentPopup({ appointmentData: Object.assign({}, appointment), editing: { form: { items: ["mainGroup"] } } }); const formItems = POM.dxForm.option("items") ?? []; expect(formItems.length).toBe(1); expect(null === (_formItems$ = formItems[0]) || void 0 === _formItems$ ? void 0 : _formItems$.name).toBe("mainGroup") }); it.each([true, false])("should set group visibility to %s when specified in object config", async visible => { var _formItems$2; const { POM: POM } = await createAppointmentPopup({ appointmentData: Object.assign({}, appointment), editing: { form: { items: [{ name: "mainGroup", visible: visible }] } } }); const formItems = POM.dxForm.option("items") ?? []; expect(null === (_formItems$2 = formItems[0]) || void 0 === _formItems$2 ? void 0 : _formItems$2.visible).toBe(visible) }); it("should filter group children to specified named items", async () => { var _mainGroup$items, _mainGroup$items2, _mainGroup$items3; const { POM: POM } = await createAppointmentPopup({ appointmentData: Object.assign({}, appointment), editing: { form: { items: [{ name: "mainGroup", items: ["subjectGroup", "dateGroup"] }] } } }); const mainGroup = (POM.dxForm.option("items") ?? [])[0]; expect(null === mainGroup || void 0 === mainGroup || null === (_mainGroup$items = mainGroup.items) || void 0 === _mainGroup$items ? void 0 : _mainGroup$items.length).toBe(2); expect(null === mainGroup || void 0 === mainGroup || null === (_mainGroup$items2 = mainGroup.items) || void 0 === _mainGroup$items2 || null === (_mainGroup$items2 = _mainGroup$items2[0]) || void 0 === _mainGroup$items2 ? void 0 : _mainGroup$items2.name).toBe("subjectGroup"); expect(null === mainGroup || void 0 === mainGroup || null === (_mainGroup$items3 = mainGroup.items) || void 0 === _mainGroup$items3 || null === (_mainGroup$items3 = _mainGroup$items3[1]) || void 0 === _mainGroup$items3 ? void 0 : _mainGroup$items3.name).toBe("dateGroup") }); it("should produce empty children when items array in group config is empty", async () => { var _mainGroup$items4; const { POM: POM } = await createAppointmentPopup({ appointmentData: Object.assign({}, appointment), editing: { form: { items: [{ name: "mainGroup", items: [] }] } } }); const mainGroup = (POM.dxForm.option("items") ?? [])[0]; expect(null === mainGroup || void 0 === mainGroup || null === (_mainGroup$items4 = mainGroup.items) || void 0 === _mainGroup$items4 ? void 0 : _mainGroup$items4.length).toBe(0) }); it("should create placeholder item for non-existent group name", async () => { const { POM: POM } = await createAppointmentPopup({ appointmentData: Object.assign({}, appointment), editing: { form: { items: ["nonExistentGroup"] } } }); const formItems = POM.dxForm.option("items") ?? []; expect(formItems.length).toBe(1) }); it("should handle mixed string and object items", async () => { var _formItems$3, _formItems$4, _formItems$5; const { POM: POM } = await createAppointmentPopup({ appointmentData: Object.assign({}, appointment), editing: { form: { items: ["mainGroup", { name: "mainGroup", visible: false }] } } }); const formItems = POM.dxForm.option("items") ?? []; expect(formItems.length).toBe(2); expect(null === (_formItems$3 = formItems[0]) || void 0 === _formItems$3 ? void 0 : _formItems$3.name).toBe("mainGroup"); expect(null === (_formItems$4 = formItems[1]) || void 0 === _formItems$4 ? void 0 : _formItems$4.name).toBe("mainGroup"); expect(null === (_formItems$5 = formItems[1]) || void 0 === _formItems$5 ? void 0 : _formItems$5.visible).toBe(false) }); it("should call custom onContentReady and onInitialized form callbacks", async () => { const onContentReady = jest.fn(); const onInitialized = jest.fn(); const { POM: POM } = await createAppointmentPopup({ editing: { form: { onContentReady: onContentReady, onInitialized: onInitialized } } }); expect(onContentReady).toHaveBeenCalled(); expect(onInitialized).toHaveBeenCalled(); POM.selectRepeatValue("weekly"); expect(POM.isMainGroupVisible()).toBe(false); expect(POM.isRecurrenceGroupVisible()).toBe(true) }) }) });