devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
1,041 lines (1,040 loc) • 149 kB
JavaScript
/**
* DevExtreme (esm/__internal/scheduler/appointment_popup/appointment_popup.test.js)
* Version: 25.2.3
* Build date: Fri Dec 12 2025
*
* Copyright (c) 2012 - 2025 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 {
CustomStore
} from "../../../common/data/custom_store";
import $ from "../../../core/renderer";
import {
toMilliseconds
} from "../../utils/toMilliseconds";
import fx from "../../../common/core/animation/fx";
import {
createScheduler
} from "../__tests__/__mock__/create_scheduler";
import {
setupSchedulerTestEnvironment
} from "../__tests__/__mock__/m_mock_scheduler";
import {
DEFAULT_SCHEDULER_OPTIONS
} from "../utils/options/constants";
const CLASSES = {
icon: "dx-scheduler-form-icon",
hidden: "dx-hidden",
scheduler: "dx-scheduler",
mainGroupHidden: "dx-scheduler-form-main-group-hidden",
recurrenceGroupHidden: "dx-scheduler-form-recurrence-group-hidden"
};
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 commonAppointment = {
text: "common-app",
startDate: new Date(2017, 4, 9, 9, 30),
endDate: new Date(2017, 4, 9, 11)
};
const disabledAppointment = {
text: "disabled-app",
startDate: new Date(2017, 4, 22, 9, 30),
endDate: new Date(2017, 4, 22, 11, 30),
disabled: true
};
const allDayAppointment = {
text: "all-day-app",
startDate: new Date(2017, 4, 1),
endDate: new Date(2017, 4, 1),
allDay: true
};
const getDefaultConfig = () => ({
dataSource: [],
views: ["month"],
currentView: "month",
currentDate: new Date(2017, 4, 25),
firstDayOfWeek: 1,
startDayHour: 9,
height: 600,
width: 600
});
describe("Appointment Form", (() => {
beforeEach((() => {
fx.off = true;
setupSchedulerTestEnvironment({
height: 600
})
}));
afterEach((() => {
const $scheduler = $(document.querySelector(`.${CLASSES.scheduler}`));
$scheduler.dxScheduler("dispose");
document.body.innerHTML = "";
fx.off = false;
jest.useRealTimers()
}));
describe("Changes saving/canceling", (() => {
it("should update appointment on save button click", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(Object.assign({}, getDefaultConfig(), {
dataSource: [Object.assign({}, commonAppointment)]
}));
const dataSource = scheduler.getDataSource();
const item = dataSource.items()[0];
scheduler.showAppointmentPopup(item);
POM.popup.setInputValue("subjectEditor", "New Subject");
POM.popup.getSaveButton().click();
expect(dataSource.items()[0]).toMatchObject(Object.assign({}, commonAppointment, {
text: "New Subject"
}))
}));
it("should not update appointment on cancel button click", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(Object.assign({}, getDefaultConfig(), {
dataSource: [Object.assign({}, commonAppointment)]
}));
const dataSource = scheduler.getDataSource();
const item = dataSource.items()[0];
scheduler.showAppointmentPopup(item);
POM.popup.setInputValue("subjectEditor", "New Subject");
POM.popup.getCancelButton().click();
expect(dataSource.items()[0]).toMatchObject(commonAppointment)
}));
it("should update recurring appointment on save button click in recurrence form", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(Object.assign({}, getDefaultConfig(), {
dataSource: [Object.assign({}, recurringAppointment)]
}));
const dataSource = scheduler.getDataSource();
const item = dataSource.items()[0];
scheduler.showAppointmentPopup(item);
POM.popup.getEditSeriesButton().click();
POM.popup.setInputValue("subjectEditor", "New Subject");
POM.popup.openRecurrenceSettings();
POM.popup.getSaveButton().click();
expect(dataSource.items()[0]).toMatchObject(Object.assign({}, recurringAppointment, {
text: "New Subject"
}))
}));
it("should not update recurring appointment on cancel button click in recurrence form", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(Object.assign({}, getDefaultConfig(), {
dataSource: [Object.assign({}, recurringAppointment)]
}));
const dataSource = scheduler.getDataSource();
const item = dataSource.items()[0];
scheduler.showAppointmentPopup(item);
POM.popup.getEditSeriesButton().click();
POM.popup.setInputValue("subjectEditor", "New Subject");
POM.popup.openRecurrenceSettings();
POM.popup.getCancelButton().click();
expect(dataSource.items()[0]).toMatchObject(recurringAppointment)
}));
it("should update appointment recurrence rule changes on save button click", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(Object.assign({}, getDefaultConfig(), {
dataSource: [Object.assign({}, commonAppointment)]
}));
const dataSource = scheduler.getDataSource();
const item = dataSource.items()[0];
scheduler.showAppointmentPopup(item);
POM.popup.selectRepeatValue("daily");
POM.popup.getSaveButton().click();
expect(dataSource.items()[0]).toMatchObject(Object.assign({}, commonAppointment, {
recurrenceRule: "FREQ=DAILY"
}))
}));
it("should not update appointment recurrence rule changes on cancel button click", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(Object.assign({}, getDefaultConfig(), {
dataSource: [Object.assign({}, commonAppointment)]
}));
const dataSource = scheduler.getDataSource();
const item = dataSource.items()[0];
scheduler.showAppointmentPopup(item);
POM.popup.selectRepeatValue("daily");
POM.popup.getCancelButton().click();
expect(dataSource.items()[0]).toMatchObject(commonAppointment)
}));
it("should not update recurrence rule on save button click if recurrence rule was not changed", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(Object.assign({}, getDefaultConfig(), {
dataSource: [Object.assign({}, recurringAppointment)]
}));
const dataSource = scheduler.getDataSource();
const item = dataSource.items()[0];
scheduler.showAppointmentPopup(item);
POM.popup.getEditSeriesButton().click();
POM.popup.getSaveButton().click();
expect(dataSource.items()[0]).toMatchObject(recurringAppointment)
}));
it("should update recurrence rule on save button click if repeat editor value was set to never", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(Object.assign({}, getDefaultConfig(), {
dataSource: [Object.assign({}, recurringAppointment)]
}));
const dataSource = scheduler.getDataSource();
const item = dataSource.items()[0];
scheduler.showAppointmentPopup(item);
POM.popup.getEditSeriesButton().click();
POM.popup.selectRepeatValue("never");
POM.popup.getSaveButton().click();
expect(dataSource.items()[0]).toMatchObject(Object.assign({}, recurringAppointment, {
recurrenceRule: ""
}))
}));
it("should update appointment when data source is a custom store", (async () => {
const appointment = Object.assign({}, commonAppointment, {
id: 0
});
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(Object.assign({}, getDefaultConfig(), {
dataSource: {
store: {
type: "array",
key: "id",
data: [appointment]
}
}
}));
scheduler.showAppointmentPopup(appointment);
POM.popup.setInputValue("subjectEditor", "Updated subject");
scheduler.hideAppointmentPopup(true);
const items = scheduler.getDataSource().items();
expect(items).toHaveLength(1);
expect(items[0]).toMatchObject(Object.assign({}, appointment, {
text: "Updated subject"
}))
}));
it("should create appointment when data source is a custom store", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(Object.assign({}, getDefaultConfig(), {
dataSource: {
store: {
type: "array",
key: "id",
data: []
}
}
}));
scheduler.showAppointmentPopup();
POM.popup.setInputValue("subjectEditor", "New subject");
POM.popup.setInputValue("startDateEditor", new Date(2017, 4, 25, 9, 0));
POM.popup.setInputValue("startTimeEditor", new Date(2017, 4, 25, 9, 0));
POM.popup.setInputValue("endDateEditor", new Date(2017, 4, 25, 10, 0));
POM.popup.setInputValue("endTimeEditor", new Date(2017, 4, 25, 10, 0));
POM.popup.setInputValue("descriptionEditor", "New appointment description");
scheduler.hideAppointmentPopup(true);
const items = scheduler.getDataSource().items();
expect(items).toHaveLength(1);
expect(items[0]).toMatchObject({
text: "New subject",
startDate: new Date(2017, 4, 25, 9, 0),
endDate: new Date(2017, 4, 25, 10, 0),
description: "New appointment description"
})
}));
it("should update resource value on save button click", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(Object.assign({}, getDefaultConfig(), {
dataSource: [{
text: "Resource test app",
startDate: new Date(2017, 4, 9, 9, 30),
endDate: new Date(2017, 4, 9, 11),
roomId: 1
}],
resources: [{
fieldExpr: "roomId",
dataSource: [{
text: "Room 1",
id: 1,
color: "#00af2c"
}, {
text: "Room 2",
id: 2,
color: "#56ca85"
}, {
text: "Room 3",
id: 3,
color: "#8ecd3c"
}]
}]
}));
const dataSource = scheduler.getDataSource();
const item = dataSource.items()[0];
scheduler.showAppointmentPopup(item);
POM.popup.setInputValue("roomId", 2);
POM.popup.getSaveButton().click();
expect(dataSource.items()[0].roomId).toBe(2)
}));
it("should create separate appointment when saving single appointment from series", (async () => {
const appointment = {
text: "recurring-app",
startDate: "2017-05-01T09:30:00.000Z",
endDate: "2017-05-01T11:00:00.000Z",
recurrenceRule: "FREQ=DAILY;COUNT=5"
};
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(Object.assign({}, getDefaultConfig(), {
dataSource: [Object.assign({}, appointment)]
}));
const dataSource = scheduler.getDataSource();
POM.openPopupByDblClick("recurring-app");
POM.popup.getEditAppointmentButton().click();
POM.popup.setInputValue("subjectEditor", "single appointment");
scheduler.hideAppointmentPopup(true);
expect(dataSource.items()).toHaveLength(2);
expect(dataSource.items()[0]).toEqual(Object.assign({}, appointment, {
recurrenceException: "20170501T093000Z"
}));
expect(dataSource.items()[1]).toEqual(Object.assign({}, appointment, {
text: "single appointment",
recurrenceRule: "",
allDay: false
}))
}))
}));
describe("Validation", (() => {
it.each(["startDateEditor", "startTimeEditor", "endDateEditor", "endTimeEditor"])("should not close popup on save button click when %s is empty", (async editorName => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(getDefaultConfig());
scheduler.showAppointmentPopup(Object.assign({}, commonAppointment));
POM.popup.setInputValue(editorName, null);
POM.popup.getSaveButton().click();
expect(POM.isPopupVisible()).toBe(true)
}));
it.each(["startTimeEditor", "endDateEditor", "endTimeEditor"])("should not close popup on save button click in recurrence form when %s editor is empty", (async editorName => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(getDefaultConfig());
scheduler.showAppointmentPopup(Object.assign({}, commonAppointment));
POM.popup.setInputValue(editorName, null);
POM.popup.selectRepeatValue("daily");
POM.popup.getSaveButton().click();
expect(POM.isPopupVisible()).toBe(true)
}));
it("should close popup on save button click in recurrence form when startEditor editor is empty", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(getDefaultConfig());
scheduler.showAppointmentPopup(Object.assign({}, commonAppointment));
POM.popup.setInputValue("startDateEditor", null);
POM.popup.selectRepeatValue("daily");
expect(POM.popup.getInputValue("recurrenceStartDateEditor")).toBe("5/9/2017");
POM.popup.getSaveButton().click();
expect(POM.isPopupVisible()).toBe(false)
}))
}));
describe("State", (() => {
it("should have empty description, subject and timezone inputs when opening second common appointment", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(Object.assign({}, getDefaultConfig(), {
editing: {
allowUpdating: true,
allowTimeZoneEditing: true
}
}));
scheduler.showAppointmentPopup(Object.assign({}, commonAppointment));
POM.popup.setInputValue("descriptionEditor", "temp");
POM.popup.setInputValue("startDateTimeZoneEditor", "America/Los_Angeles");
POM.popup.setInputValue("endDateTimeZoneEditor", "America/Anchorage");
POM.popup.getSaveButton().click();
scheduler.showAppointmentPopup();
expect(POM.popup.getInputValue("subjectEditor")).toBe("");
expect(POM.popup.getInputValue("descriptionEditor")).toBe("");
expect(POM.popup.getInputValue("startDateTimeZoneEditor")).toBe("");
expect(POM.popup.getInputValue("endDateTimeZoneEditor")).toBe("")
}));
it("should have correct form data when opening second appointment", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(getDefaultConfig());
scheduler.showAppointmentPopup(commonAppointment);
expect(POM.popup.form.option("formData")).toMatchObject(Object.assign({}, commonAppointment));
POM.popup.getCancelButton().click();
scheduler.showAppointmentPopup(allDayAppointment);
expect(POM.popup.form.option("formData")).toMatchObject(Object.assign({}, allDayAppointment))
}));
it("should have empty resource editor value when opening second appointment", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(Object.assign({}, getDefaultConfig(), {
resources: [{
fieldExpr: "roomId",
dataSource: [{
text: "Room 1",
id: 1,
color: "#00af2c"
}, {
text: "Room 2",
id: 2,
color: "#56ca85"
}, {
text: "Room 3",
id: 3,
color: "#8ecd3c"
}]
}]
}));
scheduler.showAppointmentPopup({
text: "Resource test app",
startDate: new Date(2017, 4, 9, 9, 30),
endDate: new Date(2017, 4, 9, 11),
roomId: 1
});
POM.popup.setInputValue("roomId", 2);
scheduler.hideAppointmentPopup(true);
scheduler.showAppointmentPopup();
expect(POM.popup.getInputValue("roomId")).toBe("")
}));
it("should have correct repeat editor value when opening recurring appointment after common appointment", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(getDefaultConfig());
scheduler.showAppointmentPopup(Object.assign({}, commonAppointment));
POM.popup.getSaveButton().click();
scheduler.showAppointmentPopup(Object.assign({}, recurringAppointment));
POM.popup.getEditSeriesButton().click();
expect(POM.popup.getInputValue("repeatEditor")).toBe("Daily")
}));
it("should have correct editor values when opening for empty date cell - 1", (async () => {
const {
POM: POM
} = await createScheduler(Object.assign({}, getDefaultConfig(), {
currentView: "week"
}));
POM.dblClickDateTableCell(0, 0);
expect(POM.popup.getInputValue("subjectEditor")).toBe("");
expect(POM.popup.getInputValue("startDateEditor")).toBe("5/22/2017");
expect(POM.popup.getInputValue("startTimeEditor")).toBe("9:00 AM");
expect(POM.popup.getInputValue("endDateEditor")).toBe("5/22/2017");
expect(POM.popup.getInputValue("endTimeEditor")).toBe("9:30 AM");
expect(POM.popup.getInputValue("allDayEditor")).toBe("false");
expect(POM.popup.getInputValue("descriptionEditor")).toBe("")
}));
it("should have correct editor values when opening for empty date cell - 2", (async () => {
const {
POM: POM
} = await createScheduler(Object.assign({}, getDefaultConfig(), {
currentView: "week"
}));
POM.dblClickDateTableCell(1, 1);
expect(POM.popup.getInputValue("subjectEditor")).toBe("");
expect(POM.popup.getInputValue("startDateEditor")).toBe("5/23/2017");
expect(POM.popup.getInputValue("startTimeEditor")).toBe("9:30 AM");
expect(POM.popup.getInputValue("endDateEditor")).toBe("5/23/2017");
expect(POM.popup.getInputValue("endTimeEditor")).toBe("10:00 AM");
expect(POM.popup.getInputValue("allDayEditor")).toBe("false");
expect(POM.popup.getInputValue("descriptionEditor")).toBe("")
}));
it("should have correct editor values when opening for empty all day cell", (async () => {
const {
POM: POM
} = await createScheduler(Object.assign({}, getDefaultConfig(), {
currentView: "week"
}));
POM.dblClickAllDayTableCell(1);
expect(POM.popup.getInputValue("subjectEditor")).toBe("");
expect(POM.popup.getInputValue("startDateEditor")).toBe("5/23/2017");
expect(POM.popup.isInputVisible("startTimeEditor")).toBe(false);
expect(POM.popup.getInputValue("endDateEditor")).toBe("5/23/2017");
expect(POM.popup.isInputVisible("endTimeEditor")).toBe(false);
expect(POM.popup.getInputValue("allDayEditor")).toBe("true");
expect(POM.popup.getInputValue("descriptionEditor")).toBe("")
}))
}));
describe("Readonly state", (() => {
it("form should be readonly when editing.allowUpdating is false", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(Object.assign({}, getDefaultConfig(), {
editing: {
allowUpdating: false
}
}));
scheduler.showAppointmentPopup(Object.assign({}, commonAppointment));
expect(POM.popup.form.option("readOnly")).toBe(true)
}));
it("form should not be readonly when editing.allowUpdating is false and adding a new appointment", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(Object.assign({}, getDefaultConfig(), {
editing: {
allowUpdating: false,
allowAdding: true
}
}));
scheduler.showAppointmentPopup(Object.assign({}, commonAppointment), true);
expect(POM.popup.form.option("readOnly")).toBe(false)
}));
it("form should be readonly after adding new appointment if editing.allowUpdating is false", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(Object.assign({}, getDefaultConfig(), {
editing: {
allowUpdating: false,
allowAdding: true
}
}));
const dataSource = scheduler.getDataSource();
scheduler.showAppointmentPopup(Object.assign({}, commonAppointment), true);
scheduler.hideAppointmentPopup(true);
const item = dataSource.items()[0];
scheduler.showAppointmentPopup(item);
expect(POM.popup.form.option("readOnly")).toBe(true)
}));
it("form should be readonly when appointment is disabled", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(Object.assign({}, getDefaultConfig(), {
dataSource: [Object.assign({}, disabledAppointment)]
}));
const dataSource = scheduler.getDataSource();
const item = dataSource.items()[0];
scheduler.showAppointmentPopup(item);
expect(POM.popup.form.option("readOnly")).toBe(true)
}))
}));
describe("startDate/endDate editors behavior", (() => {
it.each([
["startDateEditor", "startTimeEditor"],
["endDateEditor", "endTimeEditor"],
["startTimeEditor", "startDateEditor"],
["endTimeEditor", "endDateEditor"]
])("when %s value is set to null, %s value should not be null", (async (dateEditorName, timeEditorName) => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(getDefaultConfig());
scheduler.showAppointmentPopup(Object.assign({}, commonAppointment));
POM.popup.setInputValue(dateEditorName, null);
expect(POM.popup.getInputValue(timeEditorName)).not.toBeNull()
}));
it("should update endDate when startDate is changed to a value greater than endDate", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(getDefaultConfig());
scheduler.showAppointmentPopup({
text: "test app",
startDate: new Date(2017, 4, 9, 9, 30),
endDate: new Date(2017, 4, 9, 11)
});
POM.popup.setInputValue("startDateEditor", new Date(2017, 4, 10));
expect(POM.popup.getInputValue("startTimeEditor")).toEqual("9:30 AM");
expect(POM.popup.getInputValue("endDateEditor")).toEqual("5/10/2017");
expect(POM.popup.getInputValue("endTimeEditor")).toEqual("11:00 AM")
}));
it("should update endDate when startTime is changed to a value greater than endDate time", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(getDefaultConfig());
scheduler.showAppointmentPopup({
text: "test app",
startDate: new Date(2017, 4, 9, 9, 30),
endDate: new Date(2017, 4, 9, 11)
});
POM.popup.setInputValue("startTimeEditor", new Date(2017, 4, 9, 12));
expect(POM.popup.getInputValue("startDateEditor")).toEqual("5/9/2017");
expect(POM.popup.getInputValue("endDateEditor")).toEqual("5/9/2017");
expect(POM.popup.getInputValue("endTimeEditor")).toEqual("1:30 PM")
}));
it("should update startDate when endDate is changed to a value less than startDate", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(getDefaultConfig());
scheduler.showAppointmentPopup({
text: "test app",
startDate: new Date(2017, 4, 9, 9, 30),
endDate: new Date(2017, 4, 9, 11)
});
POM.popup.setInputValue("endDateEditor", new Date(2017, 4, 8));
expect(POM.popup.getInputValue("startDateEditor")).toEqual("5/8/2017");
expect(POM.popup.getInputValue("startTimeEditor")).toEqual("9:30 AM");
expect(POM.popup.getInputValue("endTimeEditor")).toEqual("11:00 AM")
}));
it("should update startDate when endTime is changed to a value less than startDate time", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(getDefaultConfig());
scheduler.showAppointmentPopup({
text: "test app",
startDate: new Date(2017, 4, 9, 9, 30),
endDate: new Date(2017, 4, 9, 11)
});
POM.popup.setInputValue("endTimeEditor", new Date(2017, 4, 9, 9, 0));
expect(POM.popup.getInputValue("startDateEditor")).toEqual("5/9/2017");
expect(POM.popup.getInputValue("startTimeEditor")).toEqual("7:30 AM");
expect(POM.popup.getInputValue("endDateEditor")).toEqual("5/9/2017")
}));
it("should not update endDate when startDate is changed to a value less than endDate", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(getDefaultConfig());
scheduler.showAppointmentPopup({
text: "test app",
startDate: new Date(2017, 4, 9, 9, 30),
endDate: new Date(2017, 4, 9, 11)
});
POM.popup.setInputValue("startDateEditor", new Date(2017, 4, 8));
expect(POM.popup.getInputValue("startTimeEditor")).toEqual("9:30 AM");
expect(POM.popup.getInputValue("endDateEditor")).toEqual("5/9/2017");
expect(POM.popup.getInputValue("endTimeEditor")).toEqual("11:00 AM")
}));
it("should not update endDate when startTime is changed to a value less than endDate time", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(getDefaultConfig());
scheduler.showAppointmentPopup({
text: "test app",
startDate: new Date(2017, 4, 9, 9, 30),
endDate: new Date(2017, 4, 9, 11)
});
POM.popup.setInputValue("startTimeEditor", new Date(2017, 4, 9, 10, 0));
expect(POM.popup.getInputValue("startDateEditor")).toEqual("5/9/2017");
expect(POM.popup.getInputValue("endDateEditor")).toEqual("5/9/2017");
expect(POM.popup.getInputValue("endTimeEditor")).toEqual("11:00 AM")
}));
it("should not update startDate when endDate is changed to a value greater than startDate", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(getDefaultConfig());
scheduler.showAppointmentPopup({
text: "test app",
startDate: new Date(2017, 4, 9, 9, 30),
endDate: new Date(2017, 4, 9, 11)
});
POM.popup.setInputValue("endDateEditor", new Date(2017, 4, 10));
expect(POM.popup.getInputValue("startDateEditor")).toEqual("5/9/2017");
expect(POM.popup.getInputValue("startTimeEditor")).toEqual("9:30 AM");
expect(POM.popup.getInputValue("endTimeEditor")).toEqual("11:00 AM")
}));
it("should not update startDate when endTime is changed to a value greater than startDate time", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(getDefaultConfig());
scheduler.showAppointmentPopup({
text: "test app",
startDate: new Date(2017, 4, 9, 9, 30),
endDate: new Date(2017, 4, 9, 11)
});
POM.popup.setInputValue("endTimeEditor", new Date(2017, 4, 9, 12));
expect(POM.popup.getInputValue("startDateEditor")).toEqual("5/9/2017");
expect(POM.popup.getInputValue("startTimeEditor")).toEqual("9:30 AM");
expect(POM.popup.getInputValue("endDateEditor")).toEqual("5/9/2017")
}))
}));
describe.each([
["Field expressions", "customField"],
["Nested field expressions", "nested.customField"]
])("%s", (exprValue => {
it.each([
["textExpr", "subjectEditor", "qwerty"],
["allDayExpr", "allDayEditor", true],
["startDateTimeZoneExpr", "startDateTimeZoneEditor", "Pacific/Midway"],
["endDateTimeZoneExpr", "endDateTimeZoneEditor", "Pacific/Midway"],
["descriptionExpr", "descriptionEditor", "qwerty"]
])("should update correct field if %s is defined", (async (fieldExpr, editorName, value) => {
const defaultField = DEFAULT_SCHEDULER_OPTIONS[fieldExpr];
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(Object.assign({}, getDefaultConfig(), {
editing: {
allowUpdating: true,
allowTimeZoneEditing: true
},
[fieldExpr]: exprValue
}));
scheduler.showAppointmentPopup();
POM.popup.setInputValue(editorName, value);
scheduler.hideAppointmentPopup(true);
const customFieldValue = scheduler.option(`dataSource[0].${exprValue}`);
const defaultFieldValue = scheduler.option(`dataSource[0].${defaultField}`);
expect(customFieldValue).toBe(value);
expect(defaultFieldValue).toBeUndefined()
}));
it.each([
["startDateExpr", "startDateEditor", "startTimeEditor"],
["endDateExpr", "endDateEditor", "endTimeEditor"]
])("should update correct field if %s is defined", (async (fieldExpr, dateEditorName, timeEditorName) => {
const value = new Date(2017, 4, 9, 9, 30);
const defaultField = DEFAULT_SCHEDULER_OPTIONS[fieldExpr];
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(Object.assign({}, getDefaultConfig(), {
editing: {
allowUpdating: true,
allowTimeZoneEditing: true
},
[fieldExpr]: exprValue
}));
scheduler.showAppointmentPopup();
POM.popup.setInputValue(dateEditorName, value);
POM.popup.setInputValue(timeEditorName, value);
scheduler.hideAppointmentPopup(true);
const customFieldValue = scheduler.option(`dataSource[0].${exprValue}`);
const defaultFieldValue = scheduler.option(`dataSource[0].${defaultField}`);
expect(customFieldValue).toEqual(new Date(value));
expect(defaultFieldValue).toBeUndefined()
}));
it("should update correct field if recurrenceRuleExpr is defined", (async () => {
const fieldExpr = "recurrenceRuleExpr";
const defaultField = DEFAULT_SCHEDULER_OPTIONS.recurrenceRuleExpr;
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(Object.assign({}, getDefaultConfig(), {
editing: {
allowUpdating: true,
allowTimeZoneEditing: true
},
[fieldExpr]: exprValue
}));
scheduler.showAppointmentPopup();
POM.popup.selectRepeatValue("daily");
scheduler.hideAppointmentPopup(true);
const customFieldValue = scheduler.option(`dataSource[0].${exprValue}`);
const defaultFieldValue = scheduler.option(`dataSource[0].${defaultField}`);
expect(customFieldValue).toBe("FREQ=DAILY");
expect(defaultFieldValue).toBeUndefined()
}));
it("should update correct resource field if fieldExpr for resource is defined", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(Object.assign({}, getDefaultConfig(), {
editing: {
allowUpdating: true,
allowTimeZoneEditing: true
},
resources: [{
fieldExpr: exprValue,
allowMultiple: false,
dataSource: [{
text: "Room 1",
id: 1,
color: "#00af2c"
}, {
text: "Room 2",
id: 2,
color: "#56ca85"
}, {
text: "Room 3",
id: 3,
color: "#8ecd3c"
}]
}]
}));
scheduler.showAppointmentPopup();
POM.popup.setInputValue(exprValue, 2);
scheduler.hideAppointmentPopup(true);
const customFieldValue = scheduler.option(`dataSource[0].${exprValue}`);
const defaultFieldValue = scheduler.option("dataSource[0].roomId");
expect(customFieldValue).toBe(2);
expect(defaultFieldValue).toBeUndefined()
}))
}));
describe("allDay switch", (() => {
it("should be turned on when opening allDay appointment", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(getDefaultConfig());
scheduler.showAppointmentPopup(allDayAppointment);
expect(POM.popup.getInputValue("allDayEditor")).toBe("true")
}));
it("should be turned off when opening non-allDay appointment", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(getDefaultConfig());
scheduler.showAppointmentPopup(commonAppointment);
expect(POM.popup.getInputValue("allDayEditor")).toBe("false")
}));
it("should hide time editors when switched on", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(getDefaultConfig());
scheduler.showAppointmentPopup(commonAppointment);
expect(POM.popup.startDate).toBeDefined();
expect(POM.popup.startTime).toBeDefined();
expect(POM.popup.endDate).toBeDefined();
expect(POM.popup.endTime).toBeDefined();
POM.popup.getSwitchByName("allDay").click();
expect(POM.popup.startDate).toBeDefined();
expect(POM.popup.startTime).toBeNull();
expect(POM.popup.endDate).toBeDefined();
expect(POM.popup.endTime).toBeNull()
}));
it("should show time editors when switched off", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(getDefaultConfig());
scheduler.showAppointmentPopup(allDayAppointment);
expect(POM.popup.startDate).toBeDefined();
expect(POM.popup.startTime).toBeNull();
expect(POM.popup.endDate).toBeDefined();
expect(POM.popup.endTime).toBeNull();
POM.popup.getSwitchByName("allDay").click();
expect(POM.popup.startDate).toBeDefined();
expect(POM.popup.startTime).toBeDefined();
expect(POM.popup.endDate).toBeDefined();
expect(POM.popup.endTime).toBeDefined()
}));
it("should set correct dates when switching on then off in day view", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(Object.assign({}, getDefaultConfig(), {
currentView: "day"
}));
scheduler.showAppointmentPopup(commonAppointment);
POM.popup.getSwitchByName("allDay").click();
POM.popup.getSwitchByName("allDay").click();
expect(POM.popup.getInputValue("startDateEditor")).toBe("5/9/2017");
expect(POM.popup.getInputValue("startTimeEditor")).toBe("9:00 AM");
expect(POM.popup.getInputValue("endDateEditor")).toBe("5/9/2017");
expect(POM.popup.getInputValue("endTimeEditor")).toBe("9:30 AM")
}));
it("should set correct dates when switching off then on in day view", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(Object.assign({}, getDefaultConfig(), {
currentView: "day"
}));
scheduler.showAppointmentPopup(allDayAppointment);
POM.popup.getSwitchByName("allDay").click();
POM.popup.getSwitchByName("allDay").click();
expect(POM.popup.getInputValue("startDateEditor")).toBe("5/1/2017");
expect(POM.popup.isInputVisible("startTimeEditor")).toBeFalsy();
expect(POM.popup.getInputValue("endDateEditor")).toBe("5/1/2017");
expect(POM.popup.isInputVisible("endTimeEditor")).toBeFalsy()
}));
it("should set correct dates when switching on then off in month view", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(Object.assign({}, getDefaultConfig(), {
currentView: "month"
}));
scheduler.showAppointmentPopup(commonAppointment);
POM.popup.getSwitchByName("allDay").click();
POM.popup.getSwitchByName("allDay").click();
expect(POM.popup.getInputValue("startDateEditor")).toBe("5/9/2017");
expect(POM.popup.getInputValue("startTimeEditor")).toBe("9:00 AM");
expect(POM.popup.getInputValue("endDateEditor")).toBe("5/10/2017");
expect(POM.popup.getInputValue("endTimeEditor")).toBe("12:00 AM")
}));
it("should set correct dates when switching off then on in month view", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(Object.assign({}, getDefaultConfig(), {
currentView: "month"
}));
scheduler.showAppointmentPopup(allDayAppointment);
POM.popup.getSwitchByName("allDay").click();
POM.popup.getSwitchByName("allDay").click();
expect(POM.popup.getInputValue("startDateEditor")).toBe("5/1/2017");
expect(POM.popup.isInputVisible("startTimeEditor")).toBeFalsy();
expect(POM.popup.getInputValue("endDateEditor")).toBe("5/1/2017");
expect(POM.popup.isInputVisible("endTimeEditor")).toBeFalsy()
}));
it("should show correct dates after switching off allDay and canceling changes (T832711)", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(void 0);
scheduler.showAppointmentPopup(allDayAppointment);
POM.popup.getSwitchByName("allDay").click();
POM.popup.getCancelButton().click();
scheduler.showAppointmentPopup(allDayAppointment);
expect(POM.popup.getInputValue("startDateEditor")).toBe("5/1/2017");
expect(POM.popup.isInputVisible("startTimeEditor")).toBeFalsy();
expect(POM.popup.getInputValue("endDateEditor")).toBe("5/1/2017");
expect(POM.popup.isInputVisible("endTimeEditor")).toBeFalsy()
}));
it("should show correct dates after switching on allDay and canceling changes (T832711)", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(getDefaultConfig());
scheduler.showAppointmentPopup(commonAppointment);
POM.popup.getSwitchByName("allDay").click();
POM.popup.getCancelButton().click();
scheduler.showAppointmentPopup(commonAppointment);
expect(POM.popup.getInputValue("startDateEditor")).toBe("5/9/2017");
expect(POM.popup.getInputValue("startTimeEditor")).toBe("9:30 AM");
expect(POM.popup.getInputValue("endDateEditor")).toBe("5/9/2017");
expect(POM.popup.getInputValue("endTimeEditor")).toBe("11:00 AM")
}))
}));
describe("Timezone Editors", (() => {
it("should have correct timezone editors values", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(Object.assign({}, getDefaultConfig(), {
editing: {
allowUpdating: true,
allowTimeZoneEditing: true
}
}));
scheduler.showAppointmentPopup({
text: "Watercolor Landscape",
startDate: new Date("2020-06-01T17:30:00.000Z"),
endDate: new Date("2020-06-01T19:00:00.000Z"),
startDateTimeZone: "Etc/GMT+10",
endDateTimeZone: "US/Alaska"
});
expect(POM.popup.getInputValue("startDateTimeZoneEditor")).toBe("Etc/GMT+10");
expect(POM.popup.getInputValue("endDateTimeZoneEditor")).toBe("US/Alaska")
}));
it("should be shown when editing.allowTimeZoneEditing is true", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(Object.assign({}, getDefaultConfig(), {
editing: {
allowTimeZoneEditing: true
}
}));
scheduler.showAppointmentPopup(commonAppointment);
expect(POM.popup.startTimeZone).toBeDefined();
expect(POM.popup.endTimeZone).toBeDefined()
}));
it("should be hidden when editing.allowTimeZoneEditing is false", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(Object.assign({}, getDefaultConfig(), {
editing: {
allowTimeZoneEditing: false
}
}));
scheduler.showAppointmentPopup(commonAppointment);
expect(POM.popup.startTimeZone).toBeNull();
expect(POM.popup.endTimeZone).toBeNull()
}));
it("change of startTimeZone value should trigger endTimeZone value change", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(Object.assign({}, getDefaultConfig(), {
editing: {
allowTimeZoneEditing: true
}
}));
scheduler.showAppointmentPopup(commonAppointment);
const startTimeZoneSelectBox = $(POM.popup.startTimeZone).dxSelectBox("instance");
const endTimeZoneSelectBox = $(POM.popup.endTimeZone).dxSelectBox("instance");
startTimeZoneSelectBox.option("value", "America/Los_Angeles");
expect(startTimeZoneSelectBox.option("value")).toBe("America/Los_Angeles");
expect(endTimeZoneSelectBox.option("value")).toBe("America/Los_Angeles")
}));
it("change of endTimeZone value should not trigger startTimeZone value change", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(Object.assign({}, getDefaultConfig(), {
editing: {
allowTimeZoneEditing: true
}
}));
scheduler.showAppointmentPopup(commonAppointment);
const startTimeZoneSelectBox = $(POM.popup.startTimeZone).dxSelectBox("instance");
const endTimeZoneSelectBox = $(POM.popup.endTimeZone).dxSelectBox("instance");
startTimeZoneSelectBox.option("value", "America/Los_Angeles");
endTimeZoneSelectBox.option("value", "America/New_York");
expect(startTimeZoneSelectBox.option("value")).toBe("America/Los_Angeles");
expect(endTimeZoneSelectBox.option("value")).toBe("America/New_York")
}))
}));
describe("Resources", (() => {
it("should have correct resource editor value", (async () => {
const {
scheduler: scheduler,
POM: POM
} = await createScheduler(Object.assign({}, getDefaultConfig(), {
dataSource: [{
text: "Resource test app",
startDate: new Date(2017, 4, 9, 9, 30),
endDate: new Date(2017, 4, 9, 11),
roomId: 2
}],
resources: [{
fieldExpr: "roomId",
dataSource: [{
text: "Room 1",
id: 1,
color: "#00af2c"
}, {
text: "Room 2",
id: 2,
color: "#56ca85"
}, {
text: "Room 3",
id: 3,
color: "#8ecd3c"
}]