diff --git a/e2e/testcafe-devextreme/tests/accessibility/scheduler/legacyPopup.ts b/e2e/testcafe-devextreme/tests/accessibility/scheduler/legacyPopup.ts deleted file mode 100644 index eab6c756557a..000000000000 --- a/e2e/testcafe-devextreme/tests/accessibility/scheduler/legacyPopup.ts +++ /dev/null @@ -1,88 +0,0 @@ -import Scheduler from 'devextreme-testcafe-models/scheduler'; -import { createWidget } from '../../../helpers/createWidget'; -import url from '../../../helpers/getPageUrl'; -import { a11yCheck } from '../../../helpers/accessibility/utils'; - -fixture.disablePageReloads`Scheduler - Popup` - .page(url(__dirname, '../../container.html')); - -const a11yCheckConfig = {}; - -test('Scheduler edit appointment is accessible', async (t) => { - const scheduler = new Scheduler('#container'); - - await t.doubleClick(scheduler.getAppointmentByIndex(0).element()); - await t.expect(scheduler.legacyAppointmentPopup.isVisible()).ok(); - - await a11yCheck(t, a11yCheckConfig, '#container'); -}).before(async () => { - await createWidget('dxScheduler', { - timeZone: 'America/Los_Angeles', - dataSource: [{ - text: 'Install New Router in Dev Room', - startDate: new Date('2021-03-29T21:30:00.000Z'), - endDate: new Date('2021-03-29T22:30:00.000Z'), - recurrenceRule: 'FREQ=DAILY', - }], - editing: { legacyForm: true }, - recurrenceEditMode: 'series', - currentView: 'week', - currentDate: new Date(2021, 2, 28), - }); -}); - -test('Scheduler recurrence editor repeat end accessible', async (t) => { - const scheduler = new Scheduler('#container'); - const getItem = (index: number) => scheduler - .legacyAppointmentPopup - .getEndRepeatRadioButton(index); - const getAriaLabel = (index: number) => getItem(index) - .getAttribute('aria-label'); - - await t.doubleClick(scheduler.getAppointmentByIndex(0).element()); - await t.expect(scheduler.legacyAppointmentPopup.isVisible()).ok(); - - await t - .expect(getAriaLabel(1)) - .eql('On 22 May 2025') - .expect(getAriaLabel(2)) - .eql('After') - .typeText(scheduler.legacyAppointmentPopup.repeatUntilElement, '2026') - .click(getItem(1)) // unfocus input - .expect(getAriaLabel(1)) - .eql('On 22 May 2026') - .expect(getAriaLabel(2)) - .eql('After'); - await t - .click(getItem(0)) - .expect(getAriaLabel(1)) - .eql('On') - .expect(getAriaLabel(2)) - .eql('After'); - await t - .click(getItem(2)) - .expect(getAriaLabel(1)) - .eql('On') - .expect(getAriaLabel(2)) - .eql('After 1 occurrence(s)') - .typeText(scheduler.legacyAppointmentPopup.repeatCountElement, '3') - .click(getItem(2)) // unfocus input - .expect(getAriaLabel(1)) - .eql('On') - .expect(getAriaLabel(2)) - .eql('After 13 occurrence(s)'); -}).before(async () => { - await createWidget('dxScheduler', { - timeZone: 'America/Los_Angeles', - editing: { legacyForm: true }, - dataSource: [{ - text: 'Install New Router in Dev Room', - startDate: new Date('2021-03-29T21:30:00.000Z'), - endDate: new Date('2021-03-29T22:30:00.000Z'), - recurrenceRule: 'FREQ=DAILY;UNTIL=20250522T215959Z', - }], - recurrenceEditMode: 'series', - currentView: 'week', - currentDate: new Date('2021-03-29T21:30:00.000Z'), - }); -}); diff --git a/e2e/testcafe-devextreme/tests/scheduler/common/appointments/legacyEditing.ts b/e2e/testcafe-devextreme/tests/scheduler/common/appointments/legacyEditing.ts deleted file mode 100644 index 2a52261f5118..000000000000 --- a/e2e/testcafe-devextreme/tests/scheduler/common/appointments/legacyEditing.ts +++ /dev/null @@ -1,123 +0,0 @@ -import { ClientFunction } from 'testcafe'; -import { createScreenshotsComparer } from 'devextreme-screenshot-comparer'; -import Scheduler from 'devextreme-testcafe-models/scheduler'; -import { createWidget } from '../../../../helpers/createWidget'; -import url from '../../../../helpers/getPageUrl'; -import { testScreenshot } from '../../../../helpers/themeUtils'; - -const CLICK_OPTIONS = { speed: 0.5 }; -const SCHEDULER_SELECTOR = '#container'; -const INITIAL_APPOINTMENT_TITLE = 'appointment'; -const ADDITIONAL_TITLE_TEXT = '-updated'; -const UPDATED_APPOINTMENT_TITLE = `${INITIAL_APPOINTMENT_TITLE}${ADDITIONAL_TITLE_TEXT}`; - -fixture.disablePageReloads`Appointment Editing` - .page(url(__dirname, '../../../container.html')); - -test('Should correctly update appointment if dataSource is a simple array', async (t) => { - const scheduler = new Scheduler(SCHEDULER_SELECTOR); - const appointment = scheduler.getAppointment(INITIAL_APPOINTMENT_TITLE); - const updatedAppointment = scheduler.getAppointment(UPDATED_APPOINTMENT_TITLE); - const { legacyAppointmentPopup: appointmentPopup } = scheduler; - - await t - .doubleClick(appointment.element, CLICK_OPTIONS) - .click(appointmentPopup.subjectElement) - .typeText(appointmentPopup.subjectElement, ADDITIONAL_TITLE_TEXT) - .expect(appointmentPopup.subjectElement.value) - .eql(UPDATED_APPOINTMENT_TITLE) - .click(appointmentPopup.doneButton) - .expect(updatedAppointment.element.exists) - .ok(); -}).before(async () => createWidget('dxScheduler', { - dataSource: [{ - id: 1, - text: INITIAL_APPOINTMENT_TITLE, - startDate: new Date(2021, 2, 29, 9, 30), - endDate: new Date(2021, 2, 29, 11, 30), - }], - views: ['day'], - currentView: 'day', - currentDate: new Date(2021, 2, 29), - startDayHour: 9, - endDayHour: 14, - height: 600, - editing: { legacyForm: true }, -})); - -test('Should correctly update appointment if dataSource is a Store with key array', async (t) => { - const scheduler = new Scheduler(SCHEDULER_SELECTOR); - const appointment = scheduler.getAppointment(INITIAL_APPOINTMENT_TITLE); - const updatedAppointment = scheduler.getAppointment(UPDATED_APPOINTMENT_TITLE); - const { legacyAppointmentPopup: appointmentPopup } = scheduler; - - await t - .doubleClick(appointment.element, CLICK_OPTIONS) - .click(appointmentPopup.subjectElement) - .typeText(appointmentPopup.subjectElement, ADDITIONAL_TITLE_TEXT) - .expect(appointmentPopup.subjectElement.value) - .eql(UPDATED_APPOINTMENT_TITLE) - .click(appointmentPopup.doneButton) - .expect(updatedAppointment.element.exists) - .ok(); -}).before(async () => { - const initScheduler = ClientFunction(() => { - const $scheduler = $(SCHEDULER_SELECTOR) as any; - const devExpress = (window as any).DevExpress; - - $scheduler.dxScheduler({ - dataSource: new devExpress.data.DataSource({ - store: { - type: 'array', - key: 'id', - data: [{ - id: 1, - text: INITIAL_APPOINTMENT_TITLE, - startDate: new Date(2021, 2, 29, 9, 30), - endDate: new Date(2021, 2, 29, 11, 30), - }], - }, - }), - views: ['day'], - currentView: 'day', - currentDate: new Date(2021, 2, 29), - startDayHour: 9, - endDayHour: 14, - height: 600, - editing: { legacyForm: true }, - }).dxScheduler('instance'); - devExpress.fx.off = true; - }, { dependencies: { SCHEDULER_SELECTOR, INITIAL_APPOINTMENT_TITLE } }); - - await initScheduler(); -}); - -test('Appointment EditForm screenshot', async (t) => { - const { takeScreenshot, compareResults } = createScreenshotsComparer(t); - const scheduler = new Scheduler(SCHEDULER_SELECTOR); - const appointment = scheduler.getAppointment(INITIAL_APPOINTMENT_TITLE); - - await t.doubleClick(appointment.element); - - await testScreenshot(t, takeScreenshot, 'appointment-popup-screenshot.png', { element: appointment.element }); - - await t - .expect(scheduler.legacyAppointmentPopup.element.exists) - .ok() - .expect(compareResults.isValid()) - .ok(compareResults.errorMessages()); -}).before(async () => createWidget('dxScheduler', { - dataSource: [{ - id: 1, - text: INITIAL_APPOINTMENT_TITLE, - startDate: new Date(2021, 2, 29, 9, 30), - endDate: new Date(2021, 2, 29, 11, 30), - }], - editing: { legacyForm: true }, - views: ['day'], - currentView: 'day', - currentDate: new Date(2021, 2, 29), - startDayHour: 9, - endDayHour: 14, - height: 600, -})); diff --git a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/allDay.ts b/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/allDay.ts deleted file mode 100644 index 9971d28230f5..000000000000 --- a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/allDay.ts +++ /dev/null @@ -1,130 +0,0 @@ -import { createScreenshotsComparer } from 'devextreme-screenshot-comparer'; -import Scheduler from 'devextreme-testcafe-models/scheduler'; -import { createWidget } from '../../../../../helpers/createWidget'; -import url from '../../../../../helpers/getPageUrl'; -import { testScreenshot } from '../../../../../helpers/themeUtils'; - -fixture.disablePageReloads`Layout:AppointmentForm:AllDay` - .page(url(__dirname, '../../../../container.html')); - -test('Start and end dates should be reflect the current day(appointment is already available case)', async (t) => { - const scheduler = new Scheduler('#container'); - const { takeScreenshot, compareResults } = createScreenshotsComparer(t); - const { legacyAppointmentPopup: appointmentPopup } = scheduler; - - await t - .click(scheduler.getAppointment('Text').element) - .click(scheduler.appointmentTooltip.getListItem('Text').element); - - await testScreenshot(t, takeScreenshot, 'appointment-form-before-click-all-day.png'); - - await t.click(appointmentPopup.allDayElement); - - await testScreenshot(t, takeScreenshot, 'appointment-form-after-click-all-day.png'); - - await t.click(appointmentPopup.doneButton); - - await testScreenshot(t, takeScreenshot, 'all-day-appointment-on-tables.png'); - - await t - .click(scheduler.getAppointment('Text').element) - .click(scheduler.appointmentTooltip.getListItem('Text').element); - - await testScreenshot(t, takeScreenshot, 'appointment-form-after-render-on-table.png'); - - await t.click(appointmentPopup.allDayElement); - - await testScreenshot(t, takeScreenshot, 'appointment-form-after-switch-off-all-day.png'); - - await t.expect(compareResults.isValid()) - .ok(compareResults.errorMessages()); -}).before(async () => { - await createWidget('dxScheduler', { - dataSource: [{ - text: 'Text', - startDate: new Date(2021, 3, 28, 10), - endDate: new Date(2021, 3, 28, 12), - }], - editing: { legacyForm: true }, - views: ['week'], - currentView: 'week', - currentDate: new Date(2021, 3, 29), - startDayHour: 9, - height: 600, - }); -}); - -test('Start and end dates should be reflect the current day(create new appointment case)', async (t) => { - const scheduler = new Scheduler('#container'); - const { takeScreenshot, compareResults } = createScreenshotsComparer(t); - const { legacyAppointmentPopup: appointmentPopup } = scheduler; - - await t.doubleClick(scheduler.getDateTableCell(2, 3)); - - await testScreenshot(t, takeScreenshot, 'new-appointment-form-before-click-all-day.png'); - - await t.click(appointmentPopup.allDayElement); - - await testScreenshot(t, takeScreenshot, 'new-appointment-form-after-click-all-day.png'); - - await t.click(appointmentPopup.doneButton); - - await testScreenshot(t, takeScreenshot, 'new-all-day-appointment-on-tables.png'); - - await t - .click(scheduler.getAppointment('').element) - .click(scheduler.appointmentTooltip.getListItem('').element); - - await testScreenshot(t, takeScreenshot, 'new-appointment-form-after-render-on-table.png'); - - await t.click(appointmentPopup.allDayElement); - - await testScreenshot(t, takeScreenshot, 'new-appointment-form-after-switch-off-all-day.png'); - - await t.expect(compareResults.isValid()) - .ok(compareResults.errorMessages()); -}).before(async () => { - await createWidget('dxScheduler', { - dataSource: [], - views: ['week'], - editing: { legacyForm: true }, - currentView: 'week', - currentDate: new Date(2021, 3, 29), - startDayHour: 9, - height: 600, - }); -}); - -test('StartDate and endDate should have correct type after "allDay" and "repeat" option are changed (T1002864)', async (t) => { - const scheduler = new Scheduler('#container'); - const { legacyAppointmentPopup: appointmentPopup } = scheduler; - - const { takeScreenshot, compareResults } = createScreenshotsComparer(t); - - await t.doubleClick(scheduler.getDateTableCell(0, 0)); - - await testScreenshot( - t, - takeScreenshot, - 'form-before-change-allday-and-reccurence-options.png', - { element: appointmentPopup.content }, - ); - - await t - .click(appointmentPopup.allDayElement) - .click(appointmentPopup.recurrenceElement); - - await testScreenshot( - t, - takeScreenshot, - 'form-after-change-allday-and-reccurence-options.png', - { element: appointmentPopup.content }, - ); - - await t - .expect(compareResults.isValid()) - .ok(compareResults.errorMessages()); -}).before(async () => createWidget('dxScheduler', { - currentDate: new Date(2021, 1, 1), - editing: { legacyForm: true }, -})); diff --git a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/common.ts b/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/common.ts deleted file mode 100644 index 516ad47cc483..000000000000 --- a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/common.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { createScreenshotsComparer } from 'devextreme-screenshot-comparer'; -import Scheduler from 'devextreme-testcafe-models/scheduler'; -import { createWidget } from '../../../../../helpers/createWidget'; -import url from '../../../../../helpers/getPageUrl'; -import { testScreenshot } from '../../../../../helpers/themeUtils'; - -fixture.disablePageReloads`AppointmentForm screenshot tests` - .page(url(__dirname, '../../../../container.html')); - -// visual: generic.light -// visual: fluent.blue.light -// visual: material.blue.light -test('Appointemt form tests', async (t) => { - const scheduler = new Scheduler('#container'); - const { legacyAppointmentPopup: appointmentPopup } = scheduler; - - const { takeScreenshot, compareResults } = createScreenshotsComparer(t); - - await t.doubleClick(scheduler.getDateTableCell(0, 0)); - - await testScreenshot(t, takeScreenshot, 'initial-form.png', { - element: appointmentPopup.content, - }); - - await t - .click(appointmentPopup.allDayElement) - .click(appointmentPopup.recurrenceElement); - - await testScreenshot(t, takeScreenshot, 'allday-and-reccurence-form.png', { - element: appointmentPopup.content, - }); - - await t - .expect(compareResults.isValid()) - .ok(compareResults.errorMessages()); -}).before(async () => { - await createWidget('dxScheduler', { - currentDate: new Date(2021, 1, 1), - editing: { legacyForm: true }, - }); -}); diff --git a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/all-day-appointment-on-tables (fluent.blue.light).png b/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/all-day-appointment-on-tables (fluent.blue.light).png deleted file mode 100644 index f245956cb5da..000000000000 Binary files a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/all-day-appointment-on-tables (fluent.blue.light).png and /dev/null differ diff --git a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/allday-and-reccurence-form (fluent.blue.light).png b/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/allday-and-reccurence-form (fluent.blue.light).png deleted file mode 100644 index 8e52179e474e..000000000000 Binary files a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/allday-and-reccurence-form (fluent.blue.light).png and /dev/null differ diff --git a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/appointment-form-after-click-all-day (fluent.blue.light).png b/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/appointment-form-after-click-all-day (fluent.blue.light).png deleted file mode 100644 index bdaaacd50970..000000000000 Binary files a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/appointment-form-after-click-all-day (fluent.blue.light).png and /dev/null differ diff --git a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/appointment-form-after-render-on-table (fluent.blue.light).png b/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/appointment-form-after-render-on-table (fluent.blue.light).png deleted file mode 100644 index b25074e05f42..000000000000 Binary files a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/appointment-form-after-render-on-table (fluent.blue.light).png and /dev/null differ diff --git a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/appointment-form-after-switch-off-all-day (fluent.blue.light).png b/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/appointment-form-after-switch-off-all-day (fluent.blue.light).png deleted file mode 100644 index 07a8e42ff121..000000000000 Binary files a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/appointment-form-after-switch-off-all-day (fluent.blue.light).png and /dev/null differ diff --git a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/appointment-form-before-click-all-day (fluent.blue.light).png b/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/appointment-form-before-click-all-day (fluent.blue.light).png deleted file mode 100644 index 51204c22885b..000000000000 Binary files a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/appointment-form-before-click-all-day (fluent.blue.light).png and /dev/null differ diff --git a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/appointment-form-in-mobile-environment (fluent.blue.light).png b/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/appointment-form-in-mobile-environment (fluent.blue.light).png deleted file mode 100644 index 43a6283c1cc7..000000000000 Binary files a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/appointment-form-in-mobile-environment (fluent.blue.light).png and /dev/null differ diff --git a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/dx-number-boxes-not-integer-chars (fluent.blue.light).png b/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/dx-number-boxes-not-integer-chars (fluent.blue.light).png deleted file mode 100644 index 067d221014f4..000000000000 Binary files a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/dx-number-boxes-not-integer-chars (fluent.blue.light).png and /dev/null differ diff --git a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/form-after-change-allday-and-reccurence-options (fluent.blue.light).png b/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/form-after-change-allday-and-reccurence-options (fluent.blue.light).png deleted file mode 100644 index 8e52179e474e..000000000000 Binary files a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/form-after-change-allday-and-reccurence-options (fluent.blue.light).png and /dev/null differ diff --git a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/form-before-change-allday-and-reccurence-options (fluent.blue.light).png b/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/form-before-change-allday-and-reccurence-options (fluent.blue.light).png deleted file mode 100644 index 18b8b77d0835..000000000000 Binary files a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/form-before-change-allday-and-reccurence-options (fluent.blue.light).png and /dev/null differ diff --git a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/initial-form (fluent.blue.light).png b/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/initial-form (fluent.blue.light).png deleted file mode 100644 index 18b8b77d0835..000000000000 Binary files a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/initial-form (fluent.blue.light).png and /dev/null differ diff --git a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/new-all-day-appointment-on-tables (fluent.blue.light).png b/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/new-all-day-appointment-on-tables (fluent.blue.light).png deleted file mode 100644 index 0d188c1b8274..000000000000 Binary files a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/new-all-day-appointment-on-tables (fluent.blue.light).png and /dev/null differ diff --git a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/new-appointment-form-after-click-all-day (fluent.blue.light).png b/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/new-appointment-form-after-click-all-day (fluent.blue.light).png deleted file mode 100644 index 1dade82263d2..000000000000 Binary files a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/new-appointment-form-after-click-all-day (fluent.blue.light).png and /dev/null differ diff --git a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/new-appointment-form-after-render-on-table (fluent.blue.light).png b/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/new-appointment-form-after-render-on-table (fluent.blue.light).png deleted file mode 100644 index db0c01a962ba..000000000000 Binary files a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/new-appointment-form-after-render-on-table (fluent.blue.light).png and /dev/null differ diff --git a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/new-appointment-form-after-switch-off-all-day (fluent.blue.light).png b/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/new-appointment-form-after-switch-off-all-day (fluent.blue.light).png deleted file mode 100644 index 5e0a411490f4..000000000000 Binary files a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/new-appointment-form-after-switch-off-all-day (fluent.blue.light).png and /dev/null differ diff --git a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/new-appointment-form-before-click-all-day (fluent.blue.light).png b/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/new-appointment-form-before-click-all-day (fluent.blue.light).png deleted file mode 100644 index aba169a67754..000000000000 Binary files a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/etalons/new-appointment-form-before-click-all-day (fluent.blue.light).png and /dev/null differ diff --git a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/integerFormatNumberBox.ts b/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/integerFormatNumberBox.ts deleted file mode 100644 index 7633f22fd20d..000000000000 --- a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/integerFormatNumberBox.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { createScreenshotsComparer } from 'devextreme-screenshot-comparer'; -import Scheduler from 'devextreme-testcafe-models/scheduler'; -import { createWidget } from '../../../../../helpers/createWidget'; -import url from '../../../../../helpers/getPageUrl'; -import { testScreenshot } from '../../../../../helpers/themeUtils'; - -fixture.disablePageReloads`Layout:AppointmentForm:IntegerFormatNumberBox` - .page(url(__dirname, '../../../../container.html')); - -test('dxNumberBox should not allow to enter not integer chars(T1002864)', async (t) => { - const scheduler = new Scheduler('#container'); - const { legacyAppointmentPopup: appointmentPopup } = scheduler; - - const { takeScreenshot, compareResults } = createScreenshotsComparer(t); - - await t - .doubleClick(scheduler.getAppointment('Website Re-Design Plan').element); - - await t - .typeText(appointmentPopup.repeatEveryElement, '.,2', { speed: 0.5 }); - - await testScreenshot(t, takeScreenshot, 'dx-number-boxes-not-integer-chars.png', { - element: appointmentPopup.content, - }); - - await t - .expect(compareResults.isValid()) - .ok(compareResults.errorMessages()); -}).before(async () => createWidget('dxScheduler', { - dataSource: [{ - text: 'Website Re-Design Plan', - startDate: new Date(2021, 3, 26, 10), - endDate: new Date(2021, 3, 26, 11), - recurrenceRule: 'FREQ=WEEKLY;BYDAY=MO,TH;UNTIL=20220114T205959Z', - }], - editing: { legacyForm: true }, - views: ['day', 'week', 'workWeek', 'month'], - currentView: 'week', - currentDate: new Date(2021, 3, 29), - startDayHour: 9, - height: 600, - recurrenceEditMode: 'series', -})); diff --git a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/mobileEnvironment.ts b/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/mobileEnvironment.ts deleted file mode 100644 index 80a938bffb87..000000000000 --- a/e2e/testcafe-devextreme/tests/scheduler/common/layout/legacyAppointmentForm/mobileEnvironment.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { createScreenshotsComparer } from 'devextreme-screenshot-comparer'; -import Scheduler from 'devextreme-testcafe-models/scheduler'; -import { createWidget } from '../../../../../helpers/createWidget'; -import url from '../../../../../helpers/getPageUrl'; -import { testScreenshot } from '../../../../../helpers/themeUtils'; - -fixture.disablePageReloads`Layout:AppointmentForm:MobileEnvironment` - .page(url(__dirname, '../../../../container.html')); - -test.meta({ browserSize: [350, 600] })('Appointment form should be display valid layout', async (t) => { - const scheduler = new Scheduler('#container'); - const { takeScreenshot, compareResults } = createScreenshotsComparer(t); - - await t.doubleClick(scheduler.getAppointment('Text').element); - - await testScreenshot(t, takeScreenshot, 'appointment-form-in-mobile-environment.png'); - - await t.expect(compareResults.isValid()) - .ok(compareResults.errorMessages()); -}).before(async () => { - await createWidget('dxScheduler', { - dataSource: [{ - text: 'Text', - startDate: new Date(2021, 3, 28, 10), - endDate: new Date(2021, 3, 28, 12), - }], - views: ['week'], - currentView: 'week', - currentDate: new Date(2021, 3, 29), - startDayHour: 9, - height: 600, - editing: { legacyForm: true }, - }); -}); diff --git a/e2e/testcafe-devextreme/tests/scheduler/common/legacyAppointmentForm.ts b/e2e/testcafe-devextreme/tests/scheduler/common/legacyAppointmentForm.ts deleted file mode 100644 index c171a7769c3b..000000000000 --- a/e2e/testcafe-devextreme/tests/scheduler/common/legacyAppointmentForm.ts +++ /dev/null @@ -1,204 +0,0 @@ -import { Selector } from 'testcafe'; -import Scheduler from 'devextreme-testcafe-models/scheduler'; -import { createWidget } from '../../../helpers/createWidget'; -import url from '../../../helpers/getPageUrl'; -import { Themes } from '../../../helpers/themes'; - -fixture.disablePageReloads`Legacy appointment popup form` - .page(url(__dirname, '../../container.html')); - -test('Subject and description fields should be empty after showing popup on empty cell', async (t) => { - const APPOINTMENT_TEXT = 'Website Re-Design Plan'; - - const scheduler = new Scheduler('#container'); - const { legacyAppointmentPopup: appointmentPopup } = scheduler; - - await t.doubleClick(scheduler.getAppointment(APPOINTMENT_TEXT).element) - .expect(appointmentPopup.subjectElement.value) - .eql(APPOINTMENT_TEXT) - - .typeText(appointmentPopup.descriptionElement, 'temp') - - .click(appointmentPopup.doneButton) - .doubleClick(scheduler.getDateTableCell(0, 5)) - - .expect(appointmentPopup.subjectElement.value) - .eql('') - - .expect(appointmentPopup.descriptionElement.value) - .eql(''); -}).before(async () => createWidget('dxScheduler', { - views: ['month'], - currentView: 'month', - currentDate: new Date(2017, 4, 22), - height: 600, - width: 600, - editing: { legacyForm: true }, - dataSource: [ - { - text: 'Website Re-Design Plan', - startDate: new Date(2017, 4, 22, 9, 30), - endDate: new Date(2017, 4, 22, 11, 30), - }, - ], -})); - -test('Custom form shouldn\'t throw exception, after second show appointment form(T812654)', async (t) => { - const APPOINTMENT_TEXT = 'Website Re-Design Plan'; - const TEXT_EDITOR_CLASS = '.dx-texteditor-input'; - const CHECKBOX_CLASS = '.dx-checkbox.dx-widget'; - - const scheduler = new Scheduler('#container'); - - await t - .doubleClick(scheduler.getAppointment(APPOINTMENT_TEXT).element, { - speed: 0.5, - }) - .click(CHECKBOX_CLASS) - - .expect(Selector(TEXT_EDITOR_CLASS).value) - .eql(APPOINTMENT_TEXT) - - .click(scheduler.legacyAppointmentPopup.cancelButton) - - .click(scheduler.getAppointment(APPOINTMENT_TEXT).element) - .click(scheduler.appointmentTooltip.getListItem(APPOINTMENT_TEXT).element) - - .expect(Selector(TEXT_EDITOR_CLASS).exists) - .eql(false); -}).before(async () => createWidget('dxScheduler', { - views: ['month'], - currentView: 'month', - currentDate: new Date(2017, 4, 22), - height: 600, - width: 600, - editing: { legacyForm: true }, - onAppointmentFormOpening: (e) => { - const items = [{ - name: 'show1', - dataField: 'show1', - editorType: 'dxCheckBox', - editorOptions: { - type: 'boolean', - onValueChanged: (args): boolean => e.form.itemOption('text1', 'visible', args.value), - }, - }, { - name: 'text1', - dataField: 'text', - editorType: 'dxTextArea', - colSpan: 6, - visible: false, - }]; - e.form.option('items', items); - }, - dataSource: [ - { - show1: false, - text: 'Website Re-Design Plan', - startDate: new Date(2017, 4, 22, 9, 30), - endDate: new Date(2017, 4, 22, 11, 30), - }, - ], -})); - -test.meta({ runInTheme: Themes.genericLight })('Appointment should have correct form data on consecutive shows (T832711)', async (t) => { - const APPOINTMENT_TEXT = 'Google AdWords Strategy'; - - const scheduler = new Scheduler('#container'); - const { legacyAppointmentPopup: appointmentPopup } = scheduler; - - await t - .doubleClick(scheduler.getAppointment(APPOINTMENT_TEXT).element) - .expect(appointmentPopup.element.exists) - .ok() - .expect(appointmentPopup.isVisible()) - .ok() - .expect(appointmentPopup.subjectElement.value) - .eql(APPOINTMENT_TEXT) - - .click(appointmentPopup.allDayElement) - .click(appointmentPopup.cancelButton) - .expect(appointmentPopup.isVisible()) - .notOk(); - - await t - .doubleClick(scheduler.getAppointment(APPOINTMENT_TEXT).element) - .expect(appointmentPopup.isVisible()) - .ok() - - .expect(appointmentPopup.endDateElement.value) - .eql('5/5/2017'); -}).before(async () => createWidget('dxScheduler', { - views: ['month'], - currentView: 'month', - currentDate: new Date(2017, 4, 25), - endDayHour: 20, - editing: { legacyForm: true }, - dataSource: [{ - text: 'Google AdWords Strategy', - startDate: new Date(2017, 4, 1), - endDate: new Date(2017, 4, 5), - allDay: true, - }], - height: 580, -})); - -test('From elements for disabled appointments should be read only (T835731)', async (t) => { - const APPOINTMENT_TEXT = 'Install New Router in Dev Room'; - const scheduler = new Scheduler('#container'); - const { legacyAppointmentPopup: appointmentPopup } = scheduler; - - await t.doubleClick(scheduler.getAppointment(APPOINTMENT_TEXT).element) - .expect(appointmentPopup.freqElement.hasClass('dx-state-readonly')).ok() - - .expect(appointmentPopup.subjectElement.value) - .eql(APPOINTMENT_TEXT) - - .typeText(appointmentPopup.subjectElement, 'New Title') - .expect(appointmentPopup.subjectElement.value) - .eql(APPOINTMENT_TEXT) - - .typeText(appointmentPopup.descriptionElement, 'description') - .expect(appointmentPopup.descriptionElement.value) - .eql('') - - .click(appointmentPopup.allDayElement) - .expect(appointmentPopup.startDateElement.value) - .eql('5/22/2017, 2:30 PM'); -}).before(async () => createWidget('dxScheduler', { - dataSource: [{ - text: 'Install New Router in Dev Room', - startDate: new Date(2017, 4, 22, 14, 30), - endDate: new Date(2017, 4, 25, 15, 30), - disabled: true, - recurrenceRule: 'FREQ=DAILY', - }], - editing: { legacyForm: true }, - currentView: 'week', - recurrenceEditMode: 'series', - currentDate: new Date(2017, 4, 25), - startDayHour: 9, - height: 600, -})); - -test('AppointmentForm should display correct dates in work-week when firstDayOfWeek is used', async (t) => { - const scheduler = new Scheduler('#container'); - const { legacyAppointmentPopup: appointmentPopup } = scheduler; - - await t - .doubleClick(scheduler.getDateTableCell(2, 4)) - - .expect(appointmentPopup.startDateElement.value) - .eql('6/28/2021, 6:00 AM') - - .expect(appointmentPopup.endDateElement.value) - .eql('6/28/2021, 6:30 AM'); -}).before(async () => createWidget('dxScheduler', { - views: ['workWeek'], - currentView: 'workWeek', - editing: { legacyForm: true }, - currentDate: new Date(2021, 5, 28), - startDayHour: 5, - height: 600, - firstDayOfWeek: 2, -})); diff --git a/e2e/testcafe-devextreme/tests/scheduler/common/legacyAppointmentForm/appointmentPopupErrors.ts b/e2e/testcafe-devextreme/tests/scheduler/common/legacyAppointmentForm/appointmentPopupErrors.ts deleted file mode 100644 index 4096577f7ce2..000000000000 --- a/e2e/testcafe-devextreme/tests/scheduler/common/legacyAppointmentForm/appointmentPopupErrors.ts +++ /dev/null @@ -1,35 +0,0 @@ -import Scheduler from 'devextreme-testcafe-models/scheduler'; -import { createWidget } from '../../../../helpers/createWidget'; -import url from '../../../../helpers/getPageUrl'; - -fixture`Appointment Popup errors check` - .page(url(__dirname, '../../../container.html')); - -// NOTE: This test case requires page reloading, -// without page reloads the getBrowserConsoleMessages will return undefined. -test('Appointment popup shouldn\'t raise error if appointment is recursive', async (t) => { - const scheduler = new Scheduler('#container'); - await t.doubleClick(scheduler.getAppointment('Meeting of Instructors').element); - await t.click(Scheduler.getEditRecurrenceDialog().series); - - const consoleMessages = await t.getBrowserConsoleMessages(); - await t.expect(consoleMessages.error.length).eql(0); -}).before(async () => { - const data = [{ - text: 'Meeting of Instructors', - startDate: new Date('2020-11-01T17:00:00.000Z'), - endDate: new Date('2020-11-01T17:15:00.000Z'), - recurrenceRule: 'FREQ=DAILY;BYDAY=TU;UNTIL=20201203', - }]; - - return createWidget('dxScheduler', { - timeZone: 'America/Los_Angeles', - dataSource: data, - currentView: 'month', - currentDate: new Date(2020, 10, 25), - height: 600, - editing: { - legacyForm: true, - }, - }); -}); diff --git a/e2e/testcafe-devextreme/tests/scheduler/common/legacyAppointmentForm/dataEditors.ts b/e2e/testcafe-devextreme/tests/scheduler/common/legacyAppointmentForm/dataEditors.ts deleted file mode 100644 index 56eb1ac4553d..000000000000 --- a/e2e/testcafe-devextreme/tests/scheduler/common/legacyAppointmentForm/dataEditors.ts +++ /dev/null @@ -1,171 +0,0 @@ -import Scheduler from 'devextreme-testcafe-models/scheduler'; -import { createWidget } from '../../../../helpers/createWidget'; -import url from '../../../../helpers/getPageUrl'; - -fixture.disablePageReloads`Appointment popup form:date editors` - .page(url(__dirname, '../../../container.html')); - -test('Form date editors should be pass numeric chars according by date mask', async (t) => { - const scheduler = new Scheduler('#container'); - const { legacyAppointmentPopup: appointmentPopup } = scheduler; - - await t - .doubleClick(scheduler.getAppointment('Website Re-Design Plan').element); - - await t - .click(appointmentPopup.subjectElement); - - await t - .pressKey('tab') - .typeText(appointmentPopup.startDateElement, '111111111111') - .expect(appointmentPopup.startDateElement.value) - .eql('11/11/1111, 11:11 AM'); - - await t - .pressKey('tab') - .typeText(appointmentPopup.endDateElement, '111111111111') - .expect(appointmentPopup.endDateElement.value) - .eql('11/11/1111, 11:11 PM'); - - await t - .pressKey('tab') - .pressKey('tab') - .pressKey('tab') - .pressKey('tab') - .pressKey('tab') - .pressKey('tab') - .pressKey('tab') - .typeText(appointmentPopup.endRepeatDateElement, '11111111') - .expect(appointmentPopup.endRepeatDateElement.value) - .eql('11/11/1111'); -}).before(async () => createWidget('dxScheduler', { - dataSource: [{ - text: 'Website Re-Design Plan', - startDate: new Date(2021, 2, 30, 11), - endDate: new Date(2021, 2, 30, 12), - recurrenceRule: 'FREQ=DAILY;UNTIL=20211029T205959Z', - }], - recurrenceEditMode: 'series', - views: ['week'], - currentView: 'week', - currentDate: new Date(2021, 2, 28), - startDayHour: 9, - height: 600, - editing: { - legacyForm: true, - }, -})); - -test('Form date editors should not be pass chars according by date mask', async (t) => { - const scheduler = new Scheduler('#container'); - const { legacyAppointmentPopup: appointmentPopup } = scheduler; - - await t - .doubleClick(scheduler.getAppointment('Website Re-Design Plan').element); - - await t - .click(appointmentPopup.subjectElement); - - await t - .pressKey('tab') - .typeText(appointmentPopup.startDateElement, 'TEXT') - .expect(appointmentPopup.startDateElement.value) - .eql('3/30/2021, 11:00 AM'); - - await t - .pressKey('tab') - .typeText(appointmentPopup.endDateElement, 'TEXT') - .expect(appointmentPopup.endDateElement.value) - .eql('3/30/2021, 12:00 PM'); - - await t - .pressKey('tab') - .pressKey('tab') - .pressKey('tab') - .pressKey('tab') - .pressKey('tab') - .pressKey('tab') - .pressKey('tab') - .typeText(appointmentPopup.endRepeatDateElement, 'TEXT') - .expect(appointmentPopup.endRepeatDateElement.value) - .eql('10/29/2021'); -}).before(async () => createWidget('dxScheduler', { - dataSource: [{ - text: 'Website Re-Design Plan', - startDate: new Date(2021, 2, 30, 11), - endDate: new Date(2021, 2, 30, 12), - recurrenceRule: 'FREQ=DAILY;UNTIL=20211029T205959Z', - }], - recurrenceEditMode: 'series', - views: ['week'], - currentView: 'week', - currentDate: new Date(2021, 2, 28), - startDayHour: 9, - height: 600, - editing: { - legacyForm: true, - }, -})); - -test('Form date editors should not be pass chars after remove all characters according by date mask', async (t) => { - const scheduler = new Scheduler('#container'); - const { legacyAppointmentPopup: appointmentPopup } = scheduler; - - await t - .doubleClick(scheduler.getAppointment('Website Re-Design Plan').element); - - await t - .click(appointmentPopup.startDateElement) - .selectText(appointmentPopup.startDateElement) - .pressKey('backspace') - - .typeText(appointmentPopup.startDateElement, 'TEXT') - .expect(appointmentPopup.startDateElement.value) - .eql('') - - .typeText(appointmentPopup.startDateElement, '1') - .expect(appointmentPopup.startDateElement.value) - .eql('1/30/2021, 11:00 AM'); - - await t - .click(appointmentPopup.endDateElement) - .selectText(appointmentPopup.endDateElement) - .pressKey('backspace') - - .typeText(appointmentPopup.endDateElement, 'TEXT') - .expect(appointmentPopup.endDateElement.value) - .eql('') - - .typeText(appointmentPopup.endDateElement, '1') - .expect(appointmentPopup.endDateElement.value) - .eql('1/30/2021, 12:00 PM'); - - await t - .click(appointmentPopup.endRepeatDateElement) - .selectText(appointmentPopup.endRepeatDateElement) - .pressKey('backspace') - - .typeText(appointmentPopup.endRepeatDateElement, 'TEXT') - .expect(appointmentPopup.endRepeatDateElement.value) - .eql('') - - .typeText(appointmentPopup.endRepeatDateElement, '1') - .expect(appointmentPopup.endRepeatDateElement.value) - .eql('1/29/2021'); -}).before(async () => createWidget('dxScheduler', { - dataSource: [{ - text: 'Website Re-Design Plan', - startDate: new Date(2021, 2, 30, 11), - endDate: new Date(2021, 2, 30, 12), - recurrenceRule: 'FREQ=DAILY;UNTIL=20211029T205959Z', - }], - recurrenceEditMode: 'series', - views: ['week'], - currentView: 'week', - currentDate: new Date(2021, 2, 28), - startDayHour: 9, - height: 600, - editing: { - legacyForm: true, - }, -})); diff --git a/e2e/testcafe-devextreme/tests/scheduler/common/legacyAppointmentForm/etalons/form_recurrence-editor-first-opening_nested-expr (fluent.blue.light).png b/e2e/testcafe-devextreme/tests/scheduler/common/legacyAppointmentForm/etalons/form_recurrence-editor-first-opening_nested-expr (fluent.blue.light).png deleted file mode 100644 index 35e6dcc14ceb..000000000000 Binary files a/e2e/testcafe-devextreme/tests/scheduler/common/legacyAppointmentForm/etalons/form_recurrence-editor-first-opening_nested-expr (fluent.blue.light).png and /dev/null differ diff --git a/e2e/testcafe-devextreme/tests/scheduler/common/legacyAppointmentForm/etalons/recurrence-editor_after-hide (fluent.blue.light).png b/e2e/testcafe-devextreme/tests/scheduler/common/legacyAppointmentForm/etalons/recurrence-editor_after-hide (fluent.blue.light).png deleted file mode 100644 index ca0758f048a3..000000000000 Binary files a/e2e/testcafe-devextreme/tests/scheduler/common/legacyAppointmentForm/etalons/recurrence-editor_after-hide (fluent.blue.light).png and /dev/null differ diff --git a/e2e/testcafe-devextreme/tests/scheduler/common/legacyAppointmentForm/etalons/recurrence-editor_after-popup-reopen (fluent.blue.light).png b/e2e/testcafe-devextreme/tests/scheduler/common/legacyAppointmentForm/etalons/recurrence-editor_after-popup-reopen (fluent.blue.light).png deleted file mode 100644 index aa8440f986ed..000000000000 Binary files a/e2e/testcafe-devextreme/tests/scheduler/common/legacyAppointmentForm/etalons/recurrence-editor_after-popup-reopen (fluent.blue.light).png and /dev/null differ diff --git a/e2e/testcafe-devextreme/tests/scheduler/common/legacyAppointmentForm/expressions.ts b/e2e/testcafe-devextreme/tests/scheduler/common/legacyAppointmentForm/expressions.ts deleted file mode 100644 index 89d2492160f6..000000000000 --- a/e2e/testcafe-devextreme/tests/scheduler/common/legacyAppointmentForm/expressions.ts +++ /dev/null @@ -1,612 +0,0 @@ -import { ClientFunction } from 'testcafe'; -import { createScreenshotsComparer } from 'devextreme-screenshot-comparer'; -import Scheduler from 'devextreme-testcafe-models/scheduler'; -import { createWidget } from '../../../../helpers/createWidget'; -import url from '../../../../helpers/getPageUrl'; -import { testScreenshot } from '../../../../helpers/themeUtils'; - -fixture.disablePageReloads`Appointment form: expressions` - .page(url(__dirname, '../../../container.html')); - -const SCHEDULER_SELECTOR = '#container'; -const TEST_TITLE = 'Test'; -const TEST_DESCRIPTION = 'Test description...'; - -const getDataSourceValues = ClientFunction(() => ($(SCHEDULER_SELECTOR) as any) - .dxScheduler('instance') - .option('dataSource'), { dependencies: { SCHEDULER_SELECTOR } }); - -// tests config -// common -const TEXT_TEST_CASES = { - editor: 'text', - errorMessage: 'appointment\'s text incorrect', - getValue: async (scheduler: Scheduler) => scheduler.legacyAppointmentPopup.subjectElement().value, - setValue: async (t: TestController, scheduler: Scheduler, value: string) => t - .typeText(scheduler.legacyAppointmentPopup.subjectElement, value, { replace: true }), - setTestValue: '???', - expectedValue: TEST_TITLE, - cases: [ - { - name: 'expression should work', - options: { - dataSource: [{ - textCustom: TEST_TITLE, - startDate: '2023-12-10T10:00:00', - endDate: '2023-12-10T14:00:00', - }], - textExpr: 'textCustom', - }, - }, - { - name: 'nested expression should work', - options: { - dataSource: [{ - nested: { - textCustom: TEST_TITLE, - }, - startDate: '2023-12-10T10:00:00', - endDate: '2023-12-10T14:00:00', - }], - textExpr: 'nested.textCustom', - }, - }, - { - name: 'deep nested expression should work', - options: { - dataSource: [{ - nestedA: { - nestedB: { - nestedC: { - textCustom: TEST_TITLE, - }, - }, - }, - startDate: '2023-12-10T10:00:00', - endDate: '2023-12-10T14:00:00', - }], - textExpr: 'nestedA.nestedB.nestedC.textCustom', - }, - }, - ], -}; -const DESCRIPTION_TEST_CASES = { - editor: 'description', - errorMessage: 'appointment\'s description incorrect', - getValue: async (scheduler: Scheduler) => scheduler - .legacyAppointmentPopup.descriptionElement().value, - setValue: async (t: TestController, scheduler: Scheduler, value: string) => t - .typeText(scheduler.legacyAppointmentPopup.descriptionElement, value, { replace: true }), - setTestValue: '???', - expectedValue: TEST_DESCRIPTION, - cases: [ - { - name: 'expression should work', - options: { - dataSource: [{ - text: TEST_TITLE, - startDate: '2023-12-10T10:00:00', - endDate: '2023-12-10T14:00:00', - descriptionCustom: TEST_DESCRIPTION, - }], - descriptionExpr: 'descriptionCustom', - }, - }, - { - name: 'nested expression should work', - options: { - dataSource: [{ - text: TEST_TITLE, - startDate: '2023-12-10T10:00:00', - endDate: '2023-12-10T14:00:00', - nested: { - descriptionCustom: TEST_DESCRIPTION, - }, - }], - descriptionExpr: 'nested.descriptionCustom', - }, - }, - { - name: 'deep nested expression should work', - options: { - dataSource: [{ - text: TEST_TITLE, - startDate: '2023-12-10T10:00:00', - endDate: '2023-12-10T14:00:00', - nestedA: { - nestedB: { - nestedC: { - descriptionCustom: TEST_DESCRIPTION, - }, - }, - }, - }], - descriptionExpr: 'nestedA.nestedB.nestedC.descriptionCustom', - }, - }, - ], -}; -const START_DATE_TEST_CASES = { - editor: 'startDate', - errorMessage: 'appointment\'s startDate incorrect', - getValue: async (scheduler: Scheduler) => scheduler - .legacyAppointmentPopup.startDateElement().value, - setValue: async (t: TestController, scheduler: Scheduler, value: string) => t - .typeText(scheduler.legacyAppointmentPopup.startDateElement, value, { replace: true }), - setTestValue: '10/10/2020, 01:00 AM', - expectedValue: '12/10/2023, 10:00 AM', - cases: [ - { - name: 'expression should work', - options: { - dataSource: [{ - text: TEST_TITLE, - startDateCustom: '2023-12-10T10:00:00', - endDate: '2023-12-10T14:00:00', - }], - startDateExpr: 'startDateCustom', - }, - }, - { - name: 'nested expression should work', - options: { - dataSource: [{ - text: TEST_TITLE, - endDate: '2023-12-10T14:00:00', - nested: { - startDateCustom: '2023-12-10T10:00:00', - }, - }], - startDateExpr: 'nested.startDateCustom', - }, - }, - { - name: 'deep nested expression should work', - options: { - dataSource: [{ - text: TEST_TITLE, - endDate: '2023-12-10T14:00:00', - nestedA: { - nestedB: { - nestedC: { - startDateCustom: '2023-12-10T10:00:00', - }, - }, - }, - }], - startDateExpr: 'nestedA.nestedB.nestedC.startDateCustom', - }, - }, - ], -}; -const END_DATE_TEST_CASES = { - editor: 'endDate', - errorMessage: 'appointment\'s endDate incorrect', - getValue: async (scheduler: Scheduler) => scheduler.legacyAppointmentPopup.endDateElement().value, - setValue: async (t: TestController, scheduler: Scheduler, value: string) => t - .typeText(scheduler.legacyAppointmentPopup.endDateElement, value, { replace: true }), - setTestValue: '10/10/2020, 01:00 AM', - expectedValue: '12/10/2023, 2:00 PM', - cases: [ - { - name: 'expression should work', - options: { - dataSource: [{ - text: TEST_TITLE, - startDate: '2023-12-10T10:00:00', - endDateCustom: '2023-12-10T14:00:00', - }], - endDateExpr: 'endDateCustom', - }, - }, - { - name: 'nested expression should work', - options: { - dataSource: [{ - text: TEST_TITLE, - startDate: '2023-12-10T10:00:00', - nested: { - endDateCustom: '2023-12-10T14:00:00', - }, - }], - endDateExpr: 'nested.endDateCustom', - }, - }, - { - name: 'deep nested expression should work', - options: { - dataSource: [{ - text: TEST_TITLE, - startDate: '2023-12-10T10:00:00', - nestedA: { - nestedB: { - nestedC: { - endDateCustom: '2023-12-10T14:00:00', - }, - }, - }, - }], - endDateExpr: 'nestedA.nestedB.nestedC.endDateCustom', - }, - }, - ], -}; -const ALL_DAY_TEST_CASES = { - editor: 'allDay', - errorMessage: 'appointment\'s allDay incorrect', - getValue: async (scheduler: Scheduler) => scheduler - .legacyAppointmentPopup.getAllDaySwitchValue(), - setValue: async (t: TestController, scheduler: Scheduler, value: string) => { - const currentValue = await scheduler.legacyAppointmentPopup.getAllDaySwitchValue(); - - if (currentValue !== value) { - await t.click(scheduler.legacyAppointmentPopup.allDayElement); - } - }, - setTestValue: 'false', - expectedValue: 'true', - cases: [ - { - name: 'expression should work', - options: { - dataSource: [{ - text: TEST_TITLE, - startDate: '2023-12-10T10:00:00', - endDate: '2023-12-10T14:00:00', - allDayCustom: true, - }], - allDayExpr: 'allDayCustom', - }, - }, - { - name: 'nested expression should work', - options: { - dataSource: [{ - text: TEST_TITLE, - startDate: '2023-12-10T10:00:00', - endDate: '2023-12-10T14:00:00', - nested: { - allDayCustom: true, - }, - }], - allDayExpr: 'nested.allDayCustom', - }, - }, - { - name: 'deep nested expression should work', - options: { - dataSource: [{ - text: TEST_TITLE, - startDate: '2023-12-10T10:00:00', - endDate: '2023-12-10T14:00:00', - nestedA: { - nestedB: { - nestedC: { - allDayCustom: true, - }, - }, - }, - }], - allDayExpr: 'nestedA.nestedB.nestedC.allDayCustom', - }, - }, - ], -}; - -// additional -const START_DATE_TIME_ZONE_TEST_CASES = { - editor: 'startDateTimeZone', - errorMessage: 'appointment\'s startDateTimeZone incorrect', - // eslint-disable-next-line @stylistic/max-len - getValue: async (scheduler: Scheduler) => scheduler.legacyAppointmentPopup.startDateTimeZoneElement().value, - expectedValue: '(GMT -01:00) Etc - GMT+1', - cases: [ - { - name: 'expression should work', - options: { - dataSource: [{ - text: TEST_TITLE, - startDate: '2023-12-10T10:00:00', - endDate: '2023-12-10T14:00:00', - startDateTimeZoneCustom: 'Etc/GMT+1', - }], - editing: { - allowTimeZoneEditing: true, - }, - startDateTimeZoneExpr: 'startDateTimeZoneCustom', - }, - }, - { - name: 'nested expression should work', - options: { - dataSource: [{ - text: TEST_TITLE, - startDate: '2023-12-10T10:00:00', - endDate: '2023-12-10T14:00:00', - nested: { - startDateTimeZoneCustom: 'Etc/GMT+1', - }, - }], - editing: { - allowTimeZoneEditing: true, - }, - startDateTimeZoneExpr: 'nested.startDateTimeZoneCustom', - }, - }, - { - name: 'deep nested expression should work', - options: { - dataSource: [{ - text: TEST_TITLE, - startDate: '2023-12-10T10:00:00', - endDate: '2023-12-10T14:00:00', - nestedA: { - nestedB: { - nestedC: { - startDateTimeZoneCustom: 'Etc/GMT+1', - }, - }, - }, - }], - editing: { - allowTimeZoneEditing: true, - }, - startDateTimeZoneExpr: 'nestedA.nestedB.nestedC.startDateTimeZoneCustom', - }, - }, - ], -}; -const END_DATE_TIME_ZONE_TEST_CASES = { - editor: 'endDateTimeZone', - errorMessage: 'appointment\'s endDateTimeZone incorrect', - getValue: async (scheduler: Scheduler) => scheduler - .legacyAppointmentPopup.endDateTimeZoneElement().value, - expectedValue: '(GMT -02:00) Etc - GMT+2', - cases: [ - { - name: 'expression should work', - options: { - dataSource: [{ - text: TEST_TITLE, - startDate: '2023-12-10T10:00:00', - endDate: '2023-12-10T14:00:00', - endDateTimeZoneCustom: 'Etc/GMT+2', - }], - editing: { - allowTimeZoneEditing: true, - }, - endDateTimeZoneExpr: 'endDateTimeZoneCustom', - }, - }, - { - name: 'nested expression should work', - options: { - dataSource: [{ - text: TEST_TITLE, - startDate: '2023-12-10T10:00:00', - endDate: '2023-12-10T14:00:00', - nested: { - endDateTimeZoneCustom: 'Etc/GMT+2', - }, - }], - editing: { - allowTimeZoneEditing: true, - }, - endDateTimeZoneExpr: 'nested.endDateTimeZoneCustom', - }, - }, - { - name: 'deep nested expression should work', - options: { - dataSource: [{ - text: TEST_TITLE, - startDate: '2023-12-10T10:00:00', - endDate: '2023-12-10T14:00:00', - nestedA: { - nestedB: { - nestedC: { - endDateTimeZoneCustom: 'Etc/GMT+2', - }, - }, - }, - }], - editing: { - allowTimeZoneEditing: true, - }, - endDateTimeZoneExpr: 'nestedA.nestedB.nestedC.endDateTimeZoneCustom', - }, - }, - ], -}; -const RECURRENCE_RULE_TEST_CASES = { - editor: 'recurrenceRule', - errorMessage: 'appointment\'s recurrenceRule incorrect', - getValue: async (scheduler: Scheduler) => scheduler - .legacyAppointmentPopup.getRecurrenceRuleSwitchValue(), - expectedValue: 'true', - cases: [ - { - name: 'expression should work', - options: { - dataSource: [{ - text: TEST_TITLE, - startDate: '2023-12-10T10:00:00', - endDate: '2023-12-10T14:00:00', - recurrenceRuleCustom: 'FREQ=DAILY', - }], - recurrenceEditMode: 'series', - recurrenceRuleExpr: 'recurrenceRuleCustom', - }, - }, - { - name: 'nested expression should work', - options: { - dataSource: [{ - text: TEST_TITLE, - startDate: '2023-12-10T10:00:00', - endDate: '2023-12-10T14:00:00', - nested: { - recurrenceRuleCustom: 'FREQ=DAILY', - }, - }], - recurrenceEditMode: 'series', - recurrenceRuleExpr: 'nested.recurrenceRuleCustom', - }, - }, - { - name: 'deep nested expression should work', - options: { - dataSource: [{ - text: TEST_TITLE, - startDate: '2023-12-10T10:00:00', - endDate: '2023-12-10T14:00:00', - nestedA: { - nestedB: { - nestedC: { - recurrenceRuleCustom: 'FREQ=DAILY', - }, - }, - }, - }], - recurrenceEditMode: 'series', - recurrenceRuleExpr: 'nestedA.nestedB.nestedC.recurrenceRuleCustom', - }, - }, - ], -}; - -[ - TEXT_TEST_CASES, - DESCRIPTION_TEST_CASES, - START_DATE_TEST_CASES, - END_DATE_TEST_CASES, - ALL_DAY_TEST_CASES, - START_DATE_TIME_ZONE_TEST_CASES, - END_DATE_TIME_ZONE_TEST_CASES, - RECURRENCE_RULE_TEST_CASES, -].forEach(({ - editor, - errorMessage, - getValue, - expectedValue, - cases, -}) => { - cases.forEach(({ - name, - options, - }) => { - test(`${editor}: ${name}`, async (t) => { - const scheduler = new Scheduler(SCHEDULER_SELECTOR); - const appointment = scheduler.getAppointment(TEST_TITLE); - - await t.expect(appointment).ok(`appointment with title: ${TEST_TITLE} not found.`); - - await t.doubleClick(appointment.element); - - const value = await getValue(scheduler); - - await t.expect(value).eql(expectedValue, errorMessage); - }).before(async () => { - await createWidget('dxScheduler', { - currentDate: '2023-12-10', - cellDuration: 240, - ...options, - editing: { - legacyForm: true, - ...options.editing, - }, - }); - }); - }); -}); - -// test cases -[ - TEXT_TEST_CASES, - DESCRIPTION_TEST_CASES, - START_DATE_TEST_CASES, - END_DATE_TEST_CASES, - ALL_DAY_TEST_CASES, -].forEach(({ - editor, - setValue, - setTestValue, - cases, -}) => { - cases.forEach(({ - name, - options, - }) => { - test(`${editor}: ${name} should not mutate DataSource data directly`, async (t) => { - const scheduler = new Scheduler(SCHEDULER_SELECTOR); - const appointment = scheduler.getAppointment(TEST_TITLE); - const expectedDataSource = options.dataSource; - - await t.expect(appointment).ok(`appointment with title: ${TEST_TITLE} not found.`); - - await t.doubleClick(appointment.element); - await setValue(t, scheduler, setTestValue); - await t.click(scheduler.legacyAppointmentPopup.cancelButton); - - const dataSource = await getDataSourceValues(); - - await t.expect(dataSource).eql(expectedDataSource); - }).before(async () => { - await createWidget('dxScheduler', { - currentDate: '2023-12-10', - cellDuration: 240, - ...options, - editing: { - legacyForm: true, - ...options.editing, - }, - }); - }); - }); -}); - -test( - 'Appointment popup should has correct width when the nested "recurrenceRuleExpr" option is set', - async (t) => { - const { takeScreenshot, compareResults } = createScreenshotsComparer(t); - const scheduler = new Scheduler(SCHEDULER_SELECTOR); - const appointment = scheduler.getAppointment(TEST_TITLE); - - await t.doubleClick(appointment.element); - await t.expect(scheduler.legacyAppointmentPopup.form.exists).ok(); - - await testScreenshot( - t, - takeScreenshot, - 'form_recurrence-editor-first-opening_nested-expr.png', - { element: scheduler.legacyAppointmentPopup.content }, - ); - - await t.expect(compareResults.isValid()) - .ok(compareResults.errorMessages()); - }, -).before(async () => { - await createWidget('dxScheduler', { - dataSource: [ - { - startDate: '2023-12-10T10:00:00', - endDate: '2023-12-10T14:00:00', - text: TEST_TITLE, - nestedA: { - nestedB: { - nestedC: { - recurrenceRuleCustom: 'FREQ=DAILY', - }, - }, - }, - }, - ], - currentDate: '2023-12-10', - cellDuration: 240, - recurrenceEditMode: 'series', - recurrenceRuleExpr: 'nestedA.nestedB.nestedC.recurrenceRuleCustom', - editing: { - legacyForm: true, - }, - }); -}); diff --git a/e2e/testcafe-devextreme/tests/scheduler/common/legacyAppointmentForm/recurrenceEditor.ts b/e2e/testcafe-devextreme/tests/scheduler/common/legacyAppointmentForm/recurrenceEditor.ts deleted file mode 100644 index d3c0accf5b7a..000000000000 --- a/e2e/testcafe-devextreme/tests/scheduler/common/legacyAppointmentForm/recurrenceEditor.ts +++ /dev/null @@ -1,148 +0,0 @@ -import Scheduler from 'devextreme-testcafe-models/scheduler'; -import { createScreenshotsComparer } from 'devextreme-screenshot-comparer'; -import LegacyAppointmentPopup from 'devextreme-testcafe-models/scheduler/appointment/legacyPopup'; -import { createWidget } from '../../../../helpers/createWidget'; -import url from '../../../../helpers/getPageUrl'; -import { testScreenshot } from '../../../../helpers/themeUtils'; - -fixture.disablePageReloads`Appointment Form: recurrence editor` - .page(url(__dirname, '../../../container.html')); - -const SCHEDULER_SELECTOR = '#container'; - -const fillRecurrenceForm = async ( - t: TestController, - popup: LegacyAppointmentPopup, -): Promise => { - await t.click(popup.recurrenceTypeElement); - await t.click(popup.getRecurrenceTypeSelectItem(2)); - await t.typeText(popup.repeatEveryElement, '10', { replace: true }); - await t.click(popup.getEndRepeatRadioButton(1)); - await t.typeText(popup.endRepeatDateElement, '01/01/2024', { replace: true }); -}; - -test('Should not reset the recurrence editor value after the repeat toggling', async (t) => { - const { takeScreenshot, compareResults } = createScreenshotsComparer(t); - const scheduler = new Scheduler(SCHEDULER_SELECTOR); - const popup = scheduler.legacyAppointmentPopup; - const cell = scheduler.getDateTableCell(0, 0); - - await t.doubleClick(cell); - await t.click(popup.recurrenceElement); - await fillRecurrenceForm(t, popup); - await t.click(popup.recurrenceElement); - await t.click(popup.recurrenceElement); - - await testScreenshot(t, takeScreenshot, 'recurrence-editor_after-hide.png', { element: popup.content }); - - await t.expect(compareResults.isValid()) - .ok(compareResults.errorMessages()); -}).before(async () => { - await createWidget('dxScheduler', { - dataSource: [], - views: ['week'], - currentView: 'week', - currentDate: '2024-01-01T10:00:00', - editing: { - legacyForm: true, - }, - }); -}); - -test('Should reset the recurrence editor value after the popup reopening', async (t) => { - const { takeScreenshot, compareResults } = createScreenshotsComparer(t); - const scheduler = new Scheduler(SCHEDULER_SELECTOR); - const popup = scheduler.legacyAppointmentPopup; - const cell = scheduler.getDateTableCell(0, 0); - - await t.doubleClick(cell); - await t.click(popup.recurrenceElement); - await fillRecurrenceForm(t, popup); - await t.click(popup.cancelButton); - await t.doubleClick(cell); - await t.click(popup.recurrenceElement); - - await testScreenshot(t, takeScreenshot, 'recurrence-editor_after-popup-reopen.png', { element: popup.content }); - - await t.expect(compareResults.isValid()) - .ok(compareResults.errorMessages()); -}).before(async () => { - await createWidget('dxScheduler', { - dataSource: [], - views: ['week'], - currentView: 'week', - currentDate: '2024-01-01T10:00:00', - editing: { - legacyForm: true, - }, - }); -}); - -test('Should correctly create usual appointment after repeat toggling', async (t) => { - const scheduler = new Scheduler(SCHEDULER_SELECTOR); - const popup = scheduler.legacyAppointmentPopup; - const cell = scheduler.getDateTableCell(0, 0); - - await t.doubleClick(cell); - await t.click(popup.recurrenceElement); - await t.click(popup.recurrenceElement); - await t.click(popup.doneButton); - - await t.expect(scheduler.getAppointmentCount()).eql(1); -}).before(async () => { - await createWidget('dxScheduler', { - dataSource: [], - views: ['week'], - currentView: 'week', - currentDate: '2024-01-01T10:00:00', - editing: { - legacyForm: true, - }, - }); -}); - -test('Should correctly create recurrent appointment', async (t) => { - const scheduler = new Scheduler(SCHEDULER_SELECTOR); - const popup = scheduler.legacyAppointmentPopup; - const cell = scheduler.getDateTableCell(0, 0); - - await t.doubleClick(cell); - await t.click(popup.recurrenceElement); - await t.click(popup.doneButton); - - await t.expect(scheduler.getAppointmentCount()).eql(7); -}).before(async () => { - await createWidget('dxScheduler', { - dataSource: [], - views: ['week'], - currentView: 'week', - currentDate: '2024-01-01T10:00:00', - editing: { - legacyForm: true, - }, - }); -}); - -test('Should correctly create recurrent appointment after repeat toggle', async (t) => { - const scheduler = new Scheduler(SCHEDULER_SELECTOR); - const popup = scheduler.legacyAppointmentPopup; - const cell = scheduler.getDateTableCell(0, 0); - - await t.doubleClick(cell); - await t.click(popup.recurrenceElement); - await t.click(popup.recurrenceElement); - await t.click(popup.recurrenceElement); - await t.click(popup.doneButton); - - await t.expect(scheduler.getAppointmentCount()).eql(7); -}).before(async () => { - await createWidget('dxScheduler', { - dataSource: [], - views: ['week'], - currentView: 'week', - currentDate: '2024-01-01T10:00:00', - editing: { - legacyForm: true, - }, - }); -}); diff --git a/e2e/testcafe-devextreme/tests/scheduler/common/legacyAppointmentForm/showAppointmentPopup.ts b/e2e/testcafe-devextreme/tests/scheduler/common/legacyAppointmentForm/showAppointmentPopup.ts deleted file mode 100644 index 68fb3c8cd2b5..000000000000 --- a/e2e/testcafe-devextreme/tests/scheduler/common/legacyAppointmentForm/showAppointmentPopup.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { ClientFunction } from 'testcafe'; -import Scheduler from 'devextreme-testcafe-models/scheduler'; -import { createWidget } from '../../../../helpers/createWidget'; -import url from '../../../../helpers/getPageUrl'; - -fixture.disablePageReloads`Appointment Form` - .page(url(__dirname, '../../../container.html')); - -const showAppointmentPopup = ClientFunction(() => { - const instance = ($('#container') as any).dxScheduler('instance'); - instance.showAppointmentPopup(); -}); - -test('Invoke showAppointmentPopup method shouldn\'t raise error if value of currentDate property as a string', async (t) => { - const scheduler = new Scheduler('#container'); - - await showAppointmentPopup(); - - await t.expect(scheduler.legacyAppointmentPopup.startDateElement.value) - .eql('3/25/2021, 12:00 AM'); - - await t.expect(scheduler.legacyAppointmentPopup.endDateElement.value) - .eql('3/25/2021, 12:30 AM'); -}).before(async () => createWidget('dxScheduler', { - dataSource: [], - views: ['week'], - currentView: 'week', - currentDate: new Date(2021, 2, 25).toISOString(), - height: 600, - editing: { - legacyForm: true, - }, -})); - -test('Show appointment popup if deffereRendering is false (T1069753)', async (t) => { - const scheduler = new Scheduler('#container'); - const appointment = scheduler.getAppointmentByIndex(0); - - await t - .doubleClick(appointment.element) - .expect(scheduler.legacyAppointmentPopup.isVisible) - .ok(); -}).before(async () => { - await ClientFunction(() => { - (window as any).DevExpress.ui.dxPopup.defaultOptions({ - options: { - deferRendering: false, - }, - }); - })(); - - await createWidget('dxScheduler', { - dataSource: [{ - text: 'Test', - startDate: new Date(2021, 2, 29, 10), - endDate: new Date(2021, 2, 29, 11), - }], - views: ['day'], - currentView: 'day', - currentDate: new Date(2021, 2, 29), - startDayHour: 9, - endDayHour: 12, - width: 400, - editing: { - legacyForm: true, - }, - }); -}); diff --git a/e2e/testcafe-devextreme/tests/scheduler/common/legacyAppointmentForm/timezoneEditors.ts b/e2e/testcafe-devextreme/tests/scheduler/common/legacyAppointmentForm/timezoneEditors.ts deleted file mode 100644 index e7c1b719b870..000000000000 --- a/e2e/testcafe-devextreme/tests/scheduler/common/legacyAppointmentForm/timezoneEditors.ts +++ /dev/null @@ -1,79 +0,0 @@ -import Scheduler from 'devextreme-testcafe-models/scheduler'; -import { createWidget } from '../../../../helpers/createWidget'; -import url from '../../../../helpers/getPageUrl'; - -fixture.disablePageReloads`Layout:AppointmentForm:TimezoneEditors(T1080932)` - .page(url(__dirname, '../../../container.html')); - -const dataSource = [{ - text: 'Watercolor Landscape', - startDate: new Date('2020-06-01T17:30:00.000Z'), - endDate: new Date('2020-06-01T19:00:00.000Z'), - recurrenceRule: 'FREQ=WEEKLY', - startDateTimeZone: 'Etc/GMT+10', - endDateTimeZone: 'US/Alaska', -}]; - -const inputClassName = '.dx-texteditor-input'; -const startDateTimeZoneValue = '(GMT -10:00) Etc - GMT+10'; -const endDateTimeZoneValue = '(GMT -08:00) US - Alaska'; - -test.skip('TimeZone editors should be have data after hide forms data(T1080932)', async (t) => { - const scheduler = new Scheduler('#container'); - const { legacyAppointmentPopup: appointmentPopup } = scheduler; - - await t.doubleClick(scheduler.getAppointmentByIndex(0).element); - - const startDateTimeZone = appointmentPopup.wrapper.find(inputClassName).nth(1); - await t.expect(startDateTimeZone.value).eql(startDateTimeZoneValue); - - const endDateTimeZone = appointmentPopup.wrapper.find(inputClassName).nth(3); - await t.expect(endDateTimeZone.value).eql(endDateTimeZoneValue); -}).before(async () => { - await createWidget('dxScheduler', { - dataSource, - onAppointmentFormOpening: (e) => { - e.form.itemOption('mainGroup.text', 'visible', false); - }, - editing: { - allowTimeZoneEditing: true, - legacyForm: true, - }, - recurrenceEditMode: 'series', - views: ['month'], - currentView: 'month', - currentDate: new Date(2020, 6, 25), - startDayHour: 9, - height: 600, - }); -}); - -test.skip('TimeZone editors should be have data in default case(T1080932)', async (t) => { - const scheduler = new Scheduler('#container'); - - await t.doubleClick(scheduler.getAppointmentByIndex(0).element); - - const { legacyAppointmentPopup: appointmentPopup } = scheduler; - - await t.doubleClick(scheduler.getAppointmentByIndex(0).element); - - const startDateTimeZone = appointmentPopup.wrapper.find(inputClassName).nth(2); - await t.expect(startDateTimeZone.value).eql(startDateTimeZoneValue); - - const endDateTimeZone = appointmentPopup.wrapper.find(inputClassName).nth(4); - await t.expect(endDateTimeZone.value).eql(endDateTimeZoneValue); -}).before(async () => { - await createWidget('dxScheduler', { - dataSource, - editing: { - allowTimeZoneEditing: true, - legacyForm: true, - }, - recurrenceEditMode: 'series', - views: ['month'], - currentView: 'month', - currentDate: new Date(2020, 6, 25), - startDayHour: 9, - height: 600, - }); -}); diff --git a/packages/devextreme-scss/scss/widgets/base/scheduler/_common.scss b/packages/devextreme-scss/scss/widgets/base/scheduler/_common.scss index 0a0f2411c040..d331e306e8e3 100644 --- a/packages/devextreme-scss/scss/widgets/base/scheduler/_common.scss +++ b/packages/devextreme-scss/scss/widgets/base/scheduler/_common.scss @@ -5,24 +5,6 @@ $scheduler-appointment-collector-margin: 3px; $scheduler-appointment-collector-height: 22px; -$scheduler-popup-scrollable-content-padding: 20px; - -.dx-scheduler-legacy-appointment-popup { - .dx-popup-content { - padding-top: 0; - padding-bottom: 0; - } - - .dx-scrollable-content { - padding-top: $scheduler-popup-scrollable-content-padding; - } - - .dx-form.dx-recurrence-editor-container { - .dx-scrollable-content { - padding-top: 0; - } - } -} .dx-scheduler { .dx-empty-message { diff --git a/packages/devextreme-scss/scss/widgets/base/scheduler/_index.scss b/packages/devextreme-scss/scss/widgets/base/scheduler/_index.scss index 05b0808f5944..9a868e452bed 100644 --- a/packages/devextreme-scss/scss/widgets/base/scheduler/_index.scss +++ b/packages/devextreme-scss/scss/widgets/base/scheduler/_index.scss @@ -99,8 +99,6 @@ $scheduler-time-indicator-shadow-color: rgba(255, 255, 255, 0.1); $scheduler-time-indicator-shadow: 0 1px 0 0 $scheduler-time-indicator-shadow-color; $scheduler-time-indicator-text-shadow: $scheduler-time-indicator-shadow-color 1px 0 0; -$scheduler-appointment-form-label-padding: 20px; - @use "./appointment" with ( $scheduler-transparent-top-border: $scheduler-transparent-top-border, $scheduler-appointment-base-color: $scheduler-appointment-base-color, @@ -604,45 +602,6 @@ $scheduler-appointment-form-label-padding: 20px; } } - .dx-scheduler-legacy-appointment-popup { - .dx-form .dx-field-item.dx-appointment-form-switch > div { - flex-grow: 0; - width: auto; - } - - .dx-layout-manager .dx-label-h-align .dx-field-item-content { - .dx-switch, - .dx-checkbox { - margin: 0; - } - } - - .dx-field-item-label-location-left { - padding-right: $scheduler-appointment-form-label-padding; - } - - .dx-field { - min-height: 0; - } - - .dx-field-label { - width: auto; - } - - .dx-field-value { - padding-left: 0; - padding-right: 0; - - &:not(.dx-widget) > .dx-checkbox { - float: left; - - &.dx-rtl { - float: right; - } - } - } - } - .dx-scheduler-appointment-collector { &.dx-button.dx-state-hover { &::before { diff --git a/packages/devextreme-scss/scss/widgets/fluent/scheduler/_colors.scss b/packages/devextreme-scss/scss/widgets/fluent/scheduler/_colors.scss index 96b0642dcdb4..965f42ee75bf 100644 --- a/packages/devextreme-scss/scss/widgets/fluent/scheduler/_colors.scss +++ b/packages/devextreme-scss/scss/widgets/fluent/scheduler/_colors.scss @@ -65,7 +65,6 @@ $scheduler-current-time-cell-color: $base-accent !default; $scheduler-time-indicator-color: #eb5757 !default; $scheduler-dd-appointment-hover-text-color: $base-inverted-text-color !default; $scheduler-form-icon-color: $base-icon-color !default; -$scheduler-popup-title-bg: $scheduler-workspace-background-color !default; $scheduler-workspace-month-text-color: $base-text-color !default; $scheduler-workspace-other-month-text-color: $base-label-color !default; $scheduler-dropdown-appointment-date-color: color.change($base-text-color, $alpha: 0.54) !default; diff --git a/packages/devextreme-scss/scss/widgets/fluent/scheduler/_index.scss b/packages/devextreme-scss/scss/widgets/fluent/scheduler/_index.scss index 081ca90b0bea..a40c6ea98837 100644 --- a/packages/devextreme-scss/scss/widgets/fluent/scheduler/_index.scss +++ b/packages/devextreme-scss/scss/widgets/fluent/scheduler/_index.scss @@ -760,35 +760,6 @@ $fluent-scheduler-agenda-time-panel-cell-padding: 8px; } } -.dx-scheduler-legacy-appointment-popup { - .dx-form { - padding: 0 10px 0 10px; - } - - .dx-popup-title { - background-color: $scheduler-popup-title-bg; - border-bottom: none; - - .dx-closebutton, - .dx-closebutton.dx-rtl { - margin: 0; - } - } - - .dx-toolbar-after { - margin-right: 4px; - - .dx-rtl & { - margin-left: 4px; - margin-right: 0; - } - } -} - -.dx-scheduler-legacy-appointment-popup .dx-form-validation-summary { - padding: 10px 20px; -} - .dx-scheduler-header-panel, .dx-scheduler-time-panel { font-size: $fluent-scheduler-workspace-info-text-size; diff --git a/packages/devextreme-scss/scss/widgets/generic/scheduler/_colors.scss b/packages/devextreme-scss/scss/widgets/generic/scheduler/_colors.scss index 9a50494cc11c..a218d48aded9 100644 --- a/packages/devextreme-scss/scss/widgets/generic/scheduler/_colors.scss +++ b/packages/devextreme-scss/scss/widgets/generic/scheduler/_colors.scss @@ -68,7 +68,6 @@ $scheduler-current-time-cell-color: $base-accent !default; $scheduler-time-indicator-color: null !default; $scheduler-dd-appointment-hover-text-color: null !default; $scheduler-form-icon-color: $base-icon-color !default; -$scheduler-popup-title-bg: $scheduler-workspace-background-color !default; $scheduler-workspace-month-text-color: null !default; $scheduler-dropdown-appointment-date-color: null !default; $scheduler-workspace-active-cell-color: null !default; @@ -76,7 +75,6 @@ $scheduler-workspace-hovered-cell-color: null !default; $scheduler-group-header-color: null !default; $scheduler-header-bg: null !default; $scheduler-alldaypanel-bg: null !default; -$scheduler-appointment-form-separator-color: $base-border-color !default; $scheduler-tab-selected-bg: null !default; $scheduler-tab-selected-before-bg: null !default; $scheduler-tab-focused-border-color: null !default; diff --git a/packages/devextreme-scss/scss/widgets/generic/scheduler/_index.scss b/packages/devextreme-scss/scss/widgets/generic/scheduler/_index.scss index fc82711b346a..2abce2057d9c 100644 --- a/packages/devextreme-scss/scss/widgets/generic/scheduler/_index.scss +++ b/packages/devextreme-scss/scss/widgets/generic/scheduler/_index.scss @@ -231,31 +231,6 @@ $generic-scheduler-agenda-group-header-padding: $generic-scheduler-agenda-time-c } } -.dx-scheduler-legacy-appointment-popup { - .dx-popup-title { - background-color: $scheduler-popup-title-bg; - - .dx-closebutton, - .dx-closebutton.dx-rtl { - margin: 0; - } - } - - .dx-popup-bottom { - border-top: 1px solid; - border-top-color: $scheduler-appointment-form-separator-color; - } - - .dx-toolbar-after { - margin-right: 4px; - - .dx-rtl & { - margin-left: 4px; - margin-right: 0; - } - } -} - .dx-scheduler-appointment-popup { > .dx-overlay-content > .dx-toolbar.dx-widget { > .dx-toolbar-items-container { @@ -334,10 +309,6 @@ $generic-scheduler-agenda-group-header-padding: $generic-scheduler-agenda-time-c } } -.dx-scheduler-legacy-appointment-popup .dx-form-validation-summary { - padding: 10px 20px; -} - .dx-scheduler-work-space-month .dx-scheduler-date-table-cell { font-size: $generic-scheduler-month-date-text-size; } diff --git a/packages/devextreme-scss/scss/widgets/material/scheduler/_colors.scss b/packages/devextreme-scss/scss/widgets/material/scheduler/_colors.scss index 404f8b130a75..36419aac68b0 100644 --- a/packages/devextreme-scss/scss/widgets/material/scheduler/_colors.scss +++ b/packages/devextreme-scss/scss/widgets/material/scheduler/_colors.scss @@ -64,7 +64,6 @@ $scheduler-current-time-cell-color: $base-accent !default; $scheduler-time-indicator-color: #eb5757 !default; $scheduler-dd-appointment-hover-text-color: $base-inverted-text-color !default; $scheduler-form-icon-color: $base-icon-color !default; -$scheduler-popup-title-bg: $scheduler-workspace-background-color !default; $scheduler-workspace-month-text-color: $base-text-color !default; $scheduler-workspace-other-month-text-color: color.change($base-text-color, $alpha: 0.6) !default; $scheduler-dropdown-appointment-date-color: $base-text-color !default; diff --git a/packages/devextreme-scss/scss/widgets/material/scheduler/_index.scss b/packages/devextreme-scss/scss/widgets/material/scheduler/_index.scss index 8a65dd85500b..8f45e24750f9 100644 --- a/packages/devextreme-scss/scss/widgets/material/scheduler/_index.scss +++ b/packages/devextreme-scss/scss/widgets/material/scheduler/_index.scss @@ -733,35 +733,6 @@ $material-scheduler-agenda-time-panel-cell-padding: 8px; } } -.dx-scheduler-legacy-appointment-popup { - .dx-form { - padding: 0 10px 0 10px; - } - - .dx-popup-title { - background-color: $scheduler-popup-title-bg; - border-bottom: none; - - .dx-closebutton, - .dx-closebutton.dx-rtl { - margin: 0; - } - } - - .dx-toolbar-after { - margin-right: 4px; - - .dx-rtl & { - margin-left: 4px; - margin-right: 0; - } - } -} - -.dx-scheduler-legacy-appointment-popup .dx-form-validation-summary { - padding: 10px 20px; -} - .dx-scheduler-header-panel, .dx-scheduler-time-panel { font-size: $material-scheduler-workspace-info-text-size; diff --git a/packages/devextreme/js/__internal/scheduler/__tests__/__mock__/create_appointment_popup.ts b/packages/devextreme/js/__internal/scheduler/__tests__/__mock__/create_appointment_popup.ts index 0ca0948beaee..983cf4ee4762 100644 --- a/packages/devextreme/js/__internal/scheduler/__tests__/__mock__/create_appointment_popup.ts +++ b/packages/devextreme/js/__internal/scheduler/__tests__/__mock__/create_appointment_popup.ts @@ -39,7 +39,6 @@ const DEFAULT_EDITING = { allowDeleting: true, allowResizing: true, allowDragging: true, - legacyForm: false, }; const DEFAULT_APPOINTMENT = { diff --git a/packages/devextreme/js/__internal/scheduler/__tests__/legacy_form.test.ts b/packages/devextreme/js/__internal/scheduler/__tests__/legacy_form.test.ts deleted file mode 100644 index 571226bd7a50..000000000000 --- a/packages/devextreme/js/__internal/scheduler/__tests__/legacy_form.test.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { - beforeEach, describe, expect, it, -} from '@jest/globals'; - -import { createScheduler } from './__mock__/create_scheduler'; -import { setupSchedulerTestEnvironment } from './__mock__/m_mock_scheduler'; - -describe('LegacyForm', () => { - beforeEach(() => { - setupSchedulerTestEnvironment(); - }); - - it('should be false by default', async () => { - const { scheduler } = await createScheduler({ }); - - // @ts-expect-error private option - expect(scheduler.option('editing').legacyForm).toBe(false); - }); - - it('should be true when explicitly set', async () => { - const { scheduler } = await createScheduler({ editing: { legacyForm: true } }); - - // @ts-expect-error private option - expect(scheduler.option('editing').legacyForm).toBe(true); - }); - - it('should be changed by option()', async () => { - const { scheduler } = await createScheduler({}); - - scheduler.option('editing', { legacyForm: true }); - - // @ts-expect-error private option - expect(scheduler.option('editing').legacyForm).toBe(true); - }); -}); diff --git a/packages/devextreme/js/__internal/scheduler/appointment_popup/m_form.ts b/packages/devextreme/js/__internal/scheduler/appointment_popup/m_form.ts index 3b182d90714a..f5820a5f440e 100644 --- a/packages/devextreme/js/__internal/scheduler/appointment_popup/m_form.ts +++ b/packages/devextreme/js/__internal/scheduler/appointment_popup/m_form.ts @@ -1,3 +1,8 @@ +import '@js/ui/text_area'; +import '@js/ui/tag_box'; +import '@js/ui/switch'; +import '@js/ui/select_box'; + import type { TextEditorButton } from '@js/common'; import messageLocalization from '@js/common/core/localization/message'; import { DataSource } from '@js/common/data'; diff --git a/packages/devextreme/js/__internal/scheduler/appointment_popup/m_legacy_form.ts b/packages/devextreme/js/__internal/scheduler/appointment_popup/m_legacy_form.ts deleted file mode 100644 index ab4d026edc26..000000000000 --- a/packages/devextreme/js/__internal/scheduler/appointment_popup/m_legacy_form.ts +++ /dev/null @@ -1,477 +0,0 @@ -import '../m_recurrence_editor'; -import '@js/ui/text_area'; -import '@js/ui/tag_box'; -import '@js/ui/switch'; -import '@js/ui/select_box'; - -import messageLocalization from '@js/common/core/localization/message'; -import DataSource from '@js/common/data/data_source'; -import devices from '@js/core/devices'; -import $ from '@js/core/renderer'; -import dateUtils from '@js/core/utils/date'; -import dateSerialization from '@js/core/utils/date_serialization'; -import { extend } from '@js/core/utils/extend'; -import Form from '@js/ui/form'; -import { current, isFluent } from '@js/ui/themes'; - -import timeZoneUtils from '../m_utils_time_zone'; - -const SCREEN_SIZE_OF_SINGLE_COLUMN = 600; - -export const APPOINTMENT_FORM_GROUP_NAMES = { - Main: 'mainGroup', - Recurrence: 'recurrenceGroup', -}; - -// TODO: Remove duplication in the scheduler's popup testing model. -// NOTE: These CSS classes allow access the editors -// from e2e testcafe tests. -const E2E_TEST_CLASSES = { - form: 'e2e-dx-scheduler-form', - textEditor: 'e2e-dx-scheduler-form-text', - descriptionEditor: 'e2e-dx-scheduler-form-description', - startDateEditor: 'e2e-dx-scheduler-form-start-date', - endDateEditor: 'e2e-dx-scheduler-form-end-date', - startDateTimeZoneEditor: 'e2e-dx-scheduler-form-start-date-timezone', - endDateTimeZoneEditor: 'e2e-dx-scheduler-form-end-date-timezone', - allDaySwitch: 'e2e-dx-scheduler-form-all-day-switch', - recurrenceSwitch: 'e2e-dx-scheduler-form-recurrence-switch', -}; - -const createTimeZoneDataSource = () => new DataSource({ - store: timeZoneUtils.getTimeZonesCache(), - paginate: true, - pageSize: 10, -}); - -const getStylingModeFunc = (): string | undefined => (isFluent(current()) ? 'filled' : undefined); - -const getStartDateWithStartHour = (startDate, startDayHour) => new Date(new Date(startDate).setHours(startDayHour)); - -const validateAppointmentFormDate = (editor, value, previousValue) => { - const isCurrentDateCorrect = value === null || Boolean(value); - const isPreviousDateCorrect = previousValue === null || Boolean(previousValue); - if (!isCurrentDateCorrect && isPreviousDateCorrect) { - editor.option('value', previousValue); - } -}; - -const updateRecurrenceItemVisibility = (recurrenceRuleExpr, value, form) => { - form.itemOption(APPOINTMENT_FORM_GROUP_NAMES.Recurrence, 'visible', value); - form.getEditor(recurrenceRuleExpr)?.changeValueByVisibility(value); -}; - -export class AppointmentForm { - scheduler: any; - - form: any; - - // NOTE: flag to prevent double value set during form updating - private isFormUpdating = false; - - constructor(scheduler) { - this.scheduler = scheduler; - this.form = null; - } - - get dxForm() { - return this.form; - } - - set readOnly(value) { - this.form.option('readOnly', value); - const { recurrenceRuleExpr } = this.scheduler.getDataAccessors().expr; - - const recurrenceEditor = this.form.getEditor(recurrenceRuleExpr); - recurrenceEditor?.option('readOnly', value); - } - - get formData() { - return this.form.option('formData'); - } - - set formData(value) { - this.form.option('formData', value); - } - - create(triggerResize, changeSize, formData) { - const { allowTimeZoneEditing } = this.scheduler.getEditingConfig(); - const dataAccessors = this.scheduler.getDataAccessors(); - const { expr } = dataAccessors; - - const isRecurrence = Boolean(dataAccessors.get('recurrenceRule', formData)); - const colSpan = isRecurrence ? 1 : 2; - - const mainItems = [ - ...this.createMainItems(expr, triggerResize, changeSize, allowTimeZoneEditing), - ...this.scheduler.createResourceEditorModel(), - ]; - - changeSize(isRecurrence); - - const items = [ - { - itemType: 'group', - name: APPOINTMENT_FORM_GROUP_NAMES.Main, - colCountByScreen: { - lg: 2, - xs: 1, - }, - colSpan, - items: mainItems, - }, { - itemType: 'group', - name: APPOINTMENT_FORM_GROUP_NAMES.Recurrence, - visible: isRecurrence, - colSpan, - items: this.createRecurrenceEditor(expr), - }, - ]; - - const element = $('
'); - - this.scheduler.createComponent(element, Form, { - items, - showValidationSummary: true, - scrollingEnabled: true, - colCount: 'auto', - colCountByScreen: { - lg: 2, - xs: 1, - }, - formData, - showColonAfterLabel: false, - labelLocation: 'top', - onInitialized: (e) => { - this.form = e.component; - }, - screenByWidth: (width) => (width < SCREEN_SIZE_OF_SINGLE_COLUMN || devices.current().deviceType !== 'desktop' ? 'xs' : 'lg'), - elementAttr: { - class: E2E_TEST_CLASSES.form, - }, - }); - } - - private dateBoxValueChanged(args, dateExpr, isNeedCorrect) { - validateAppointmentFormDate(args.component, args.value, args.previousValue); - - const value = dateSerialization.deserializeDate(args.value); - const previousValue = dateSerialization.deserializeDate(args.previousValue); - const dateEditor = this.form.getEditor(dateExpr); - const dateValue = dateSerialization.deserializeDate(dateEditor.option('value')); - - if (!this.isFormUpdating && dateValue && value && isNeedCorrect(dateValue, value)) { - const duration = previousValue ? dateValue.getTime() - previousValue.getTime() : 0; - dateEditor.option('value', new Date(value.getTime() + duration)); - } - } - - private createTimezoneEditor(timeZoneExpr, secondTimeZoneExpr, visibleIndex, colSpan, isMainTimeZone, cssClass, visible = false) { - const noTzTitle = messageLocalization.format('dxScheduler-noTimezoneTitle'); - - return { - name: this.normalizeEditorName(timeZoneExpr), - dataField: timeZoneExpr, - editorType: 'dxSelectBox', - visibleIndex, - colSpan, - cssClass, - label: { - text: ' ', - }, - editorOptions: { - displayExpr: 'title', - valueExpr: 'id', - placeholder: noTzTitle, - searchEnabled: true, - dataSource: createTimeZoneDataSource(), - onValueChanged: (args) => { - const { form } = this; - const secondTimezoneEditor = form.getEditor(secondTimeZoneExpr); - if (isMainTimeZone) { - secondTimezoneEditor.option('value', args.value); - } - }, - }, - visible, - }; - } - - private createDateBoxItems(dataExprs, allowTimeZoneEditing) { - const colSpan = allowTimeZoneEditing ? 2 : 1; - const firstDayOfWeek = this.scheduler.getFirstDayOfWeek(); - - return [ - this.createDateBoxEditor( - dataExprs.startDateExpr, - colSpan, - firstDayOfWeek, - 'dxScheduler-editorLabelStartDate', - E2E_TEST_CLASSES.startDateEditor, - (args) => { - this.dateBoxValueChanged(args, dataExprs.endDateExpr, (endValue, startValue) => endValue < startValue); - }, - ), - - this.createTimezoneEditor( - dataExprs.startDateTimeZoneExpr, - dataExprs.endDateTimeZoneExpr, - 1, - colSpan, - true, - E2E_TEST_CLASSES.startDateTimeZoneEditor, - allowTimeZoneEditing, - ), - - this.createDateBoxEditor( - dataExprs.endDateExpr, - colSpan, - firstDayOfWeek, - 'dxScheduler-editorLabelEndDate', - E2E_TEST_CLASSES.endDateEditor, - (args) => { - this.dateBoxValueChanged(args, dataExprs.startDateExpr, (startValue, endValue) => endValue < startValue); - }, - ), - - this.createTimezoneEditor( - dataExprs.endDateTimeZoneExpr, - dataExprs.startDateTimeZoneExpr, - 3, - colSpan, - false, - E2E_TEST_CLASSES.endDateTimeZoneEditor, - allowTimeZoneEditing, - ), - ]; - } - - private changeFormItemDateType(name: string, groupName: string, isAllDay: boolean): void { - const editorPath = this.getEditorPath(name, groupName); - const itemEditorOptions = this.form.itemOption(editorPath).editorOptions; - - const type = isAllDay ? 'date' : 'datetime'; - - const newEditorOption = { ...itemEditorOptions, type }; - - this.form.itemOption(editorPath, 'editorOptions', newEditorOption); - } - - private createMainItems(dataExprs, triggerResize, changeSize, allowTimeZoneEditing) { - return [ - { - name: this.normalizeEditorName(dataExprs.textExpr), - dataField: dataExprs.textExpr, - cssClass: E2E_TEST_CLASSES.textEditor, - editorType: 'dxTextBox', - colSpan: 2, - label: { - text: messageLocalization.format('dxScheduler-editorLabelTitle'), - }, - editorOptions: { - stylingMode: getStylingModeFunc(), - }, - }, - { - itemType: 'group', - colSpan: 2, - colCountByScreen: { - lg: 2, - xs: 1, - }, - items: this.createDateBoxItems(dataExprs, allowTimeZoneEditing), - }, - { - itemType: 'group', - colSpan: 2, - colCountByScreen: { - lg: 2, - xs: 2, - }, - items: [{ - name: this.normalizeEditorName(dataExprs.allDayExpr), - dataField: dataExprs.allDayExpr, - cssClass: `dx-appointment-form-switch ${E2E_TEST_CLASSES.allDaySwitch}`, - editorType: 'dxSwitch', - label: { - text: messageLocalization.format('dxScheduler-allDay'), - location: 'right', - }, - editorOptions: { - onValueChanged: (args) => { - const { value } = args; - const startDateEditor = this.form.getEditor(dataExprs.startDateExpr); - const endDateEditor = this.form.getEditor(dataExprs.endDateExpr); - const startDate = dateSerialization.deserializeDate(startDateEditor.option('value')); - - if (!this.isFormUpdating && startDate) { - if (value) { - const allDayStartDate = dateUtils.trimTime(startDate); - startDateEditor.option('value', new Date(allDayStartDate)); - endDateEditor.option('value', new Date(allDayStartDate)); - } else { - const startDateWithStartHour = getStartDateWithStartHour(startDate, this.scheduler.getStartDayHour()); - const endDate = this.scheduler.getCalculatedEndDate(startDateWithStartHour); - startDateEditor.option('value', startDateWithStartHour); - endDateEditor.option('value', endDate); - } - } - - this.changeFormItemDateType(dataExprs.startDateExpr, 'Main', value); - this.changeFormItemDateType(dataExprs.endDateExpr, 'Main', value); - }, - }, - }, { - editorType: 'dxSwitch', - dataField: 'repeat', - cssClass: `dx-appointment-form-switch ${E2E_TEST_CLASSES.recurrenceSwitch}`, - name: 'visibilityChanged', - label: { - text: messageLocalization.format('dxScheduler-editorLabelRecurrence'), - location: 'right', - }, - editorOptions: { - onValueChanged: (args) => { - const { form } = this; - const colSpan = args.value ? 1 : 2; - - form.itemOption(APPOINTMENT_FORM_GROUP_NAMES.Main, 'colSpan', colSpan); - form.itemOption(APPOINTMENT_FORM_GROUP_NAMES.Recurrence, 'colSpan', colSpan); - - updateRecurrenceItemVisibility(dataExprs.recurrenceRuleExpr, args.value, form); - - changeSize(args.value); - triggerResize(); - }, - }, - }], - }, - { - itemType: 'empty', - colSpan: 2, - }, - { - name: this.normalizeEditorName(dataExprs.descriptionExpr), - dataField: dataExprs.descriptionExpr, - cssClass: E2E_TEST_CLASSES.descriptionEditor, - editorType: 'dxTextArea', - colSpan: 2, - label: { - text: messageLocalization.format('dxScheduler-editorLabelDescription'), - }, - editorOptions: { - stylingMode: getStylingModeFunc(), - }, - }, - { - itemType: 'empty', - colSpan: 2, - }, - ]; - } - - private createRecurrenceEditor(dataExprs) { - return [{ - name: this.normalizeEditorName(dataExprs.recurrenceRuleExpr), - dataField: dataExprs.recurrenceRuleExpr, - editorType: 'dxRecurrenceEditor', - editorOptions: { - firstDayOfWeek: this.scheduler.getFirstDayOfWeek(), - timeZoneCalculator: this.scheduler.getTimeZoneCalculator(), - getStartDateTimeZone: () => this.scheduler.getDataAccessors().get('startDateTimeZone', this.formData), - }, - label: { - text: ' ', - visible: false, - }, - }]; - } - - private setEditorsType(allDay) { - const { startDateExpr, endDateExpr } = this.scheduler.getDataAccessors().expr; - - const startDateItemPath = this.getEditorPath(startDateExpr, 'Main'); - const endDateItemPath = this.getEditorPath(endDateExpr, 'Main'); - - const startDateFormItem = this.form.itemOption(startDateItemPath); - const endDateFormItem = this.form.itemOption(endDateItemPath); - - if (startDateFormItem && endDateFormItem) { - const startDateEditorOptions = startDateFormItem.editorOptions; - const endDateEditorOptions = endDateFormItem.editorOptions; - - startDateEditorOptions.type = endDateEditorOptions.type = allDay ? 'date' : 'datetime'; - - this.form.itemOption(startDateItemPath, 'editorOptions', startDateEditorOptions); - this.form.itemOption(endDateItemPath, 'editorOptions', endDateEditorOptions); - } - } - - private updateRecurrenceEditorStartDate(date, expression) { - const options = { startDate: date }; - - this.setEditorOptions(expression, 'Recurrence', options); - } - - private setEditorOptions(name, groupName: 'Main' | 'Recurrence', options) { - const editorPath = this.getEditorPath(name, groupName); - const editor = this.form.itemOption(editorPath); - - editor && this.form.itemOption(editorPath, 'editorOptions', extend({}, editor.editorOptions, options)); - } - - updateFormData(formData: Record): void { - this.isFormUpdating = true; - this.form.option('formData', formData); - - const dataAccessors = this.scheduler.getDataAccessors(); - const { expr } = dataAccessors; - - const rawStartDate = dataAccessors.get('startDate', formData); - - const allDay = dataAccessors.get('allDay', formData); - const startDate = new Date(rawStartDate); - - this.updateRecurrenceEditorStartDate(startDate, expr.recurrenceRuleExpr); - - this.setEditorsType(allDay); - this.isFormUpdating = false; - } - - private createDateBoxEditor(dataField, colSpan, firstDayOfWeek, label, cssClass, onValueChanged) { - return { - editorType: 'dxDateBox', - name: this.normalizeEditorName(dataField), - dataField, - colSpan, - cssClass, - label: { - text: messageLocalization.format(label), - }, - validationRules: [{ - type: 'required', - }], - editorOptions: { - stylingMode: getStylingModeFunc(), - width: '100%', - calendarOptions: { - firstDayOfWeek, - }, - onValueChanged, - useMaskBehavior: true, - }, - }; - } - - private getEditorPath(name: string, groupName: string): string { - const normalizedName = this.normalizeEditorName(name); - return `${APPOINTMENT_FORM_GROUP_NAMES[groupName]}.${normalizedName}`; - } - - private normalizeEditorName(name: string): string { - // NOTE: This ternary operator covers the "recurrenceRuleExpr: null/''" scenarios. - return name - ? name.replace(/\./g, '_') - : name; - } -} diff --git a/packages/devextreme/js/__internal/scheduler/appointment_popup/m_legacy_popup.ts b/packages/devextreme/js/__internal/scheduler/appointment_popup/m_legacy_popup.ts deleted file mode 100644 index b9864131c2c7..000000000000 --- a/packages/devextreme/js/__internal/scheduler/appointment_popup/m_legacy_popup.ts +++ /dev/null @@ -1,379 +0,0 @@ -import { triggerResizeEvent } from '@js/common/core/events/visibility_change'; -import messageLocalization from '@js/common/core/localization/message'; -import devices from '@js/core/devices'; -import $ from '@js/core/renderer'; -import dateUtils from '@js/core/utils/date'; -import { Deferred, when } from '@js/core/utils/deferred'; -import Popup from '@js/ui/popup/ui.popup'; -import { - getMaxWidth, - getPopupToolbarItems, - isPopupFullScreenNeeded, -} from '@ts/scheduler/r1/appointment_popup/index'; - -import { hide as hideLoading, show as showLoading } from '../m_loading'; -import { AppointmentAdapter } from '../utils/appointment_adapter/appointment_adapter'; -import { getAppointmentGroupValues, getRawAppointmentGroupValues } from '../utils/resource_manager/appointment_groups_utils'; - -const toMs = dateUtils.dateToMilliseconds; - -export const APPOINTMENT_POPUP_CLASS = 'dx-scheduler-legacy-appointment-popup'; - -const DAY_IN_MS = toMs('day'); - -const POPUP_CONFIG = { - height: 'auto', - maxHeight: '100%', - showCloseButton: false, - showTitle: false, - preventScrollEvents: false, - enableBodyScroll: false, - defaultOptionsRules: [ - { - device: () => devices.current().android, - options: { - showTitle: false, - }, - }, - ], - _ignorePreventScrollEventsDeprecation: true, -}; - -export const ACTION_TO_APPOINTMENT = { - CREATE: 0, - UPDATE: 1, - EXCLUDE_FROM_SERIES: 2, -}; - -export class AppointmentPopup { - scheduler: any; - - form: any; - - popup: any; - - state: any; - - constructor(scheduler, form) { - this.scheduler = scheduler; - this.form = form; - this.popup = null; - - this.state = { - action: null, - lastEditData: null, - saveChangesLocker: false, - appointment: { - data: null, - }, - }; - } - - get visible() { - return this.popup ? this.popup.option('visible') : false; - } - - show(appointment, config) { - this.state.appointment.data = appointment; - this.state.action = config.action; - this.state.excludeInfo = config.excludeInfo; - - if (!this.popup) { - const popupConfig = this.createPopupConfig(); - this.popup = this.createPopup(popupConfig); - } - - this.popup.option( - 'toolbarItems', - getPopupToolbarItems( - config.isToolbarVisible, - (e) => this.doneButtonClickHandler(e), - ), - ); - - this.popup.show(); - } - - hide() { - this.popup.hide(); - } - - dispose() { - this.popup?.$element().remove(); - } - - private createPopup(options) { - const popupElement = $('
') - .addClass(APPOINTMENT_POPUP_CLASS) - .appendTo(this.scheduler.getElement()); - - return this.scheduler.createComponent(popupElement, Popup, options); - } - - private createPopupConfig() { - return { - ...POPUP_CONFIG, - onHiding: () => this.scheduler.focus(), - contentTemplate: () => this.createPopupContent(), - onShowing: (e) => this.onShowing(e), - wrapperAttr: { class: APPOINTMENT_POPUP_CLASS }, - }; - } - - private onShowing(e) { - this.updateForm(); - - e.component.$overlayContent().attr( - 'aria-label', - messageLocalization.format('dxScheduler-ariaEditForm'), - ); - - const arg = { - form: this.form.dxForm, - popup: this.popup, - appointmentData: this.state.appointment.data, - cancel: false, - }; - - this.scheduler.getAppointmentFormOpening()(arg); - this.scheduler.processActionResult(arg, (canceled) => { - if (canceled) { - e.cancel = true; - } else { - this.updatePopupFullScreenMode(); - } - }); - } - - private createPopupContent() { - this.createForm(); - return this.form.dxForm.$element(); // TODO - } - - private createFormData(rawAppointment) { - const appointment = this.createAppointmentAdapter(rawAppointment); - const resourceManager = this.scheduler.getResourceManager(); - const rawAppointmentGroupValues = getRawAppointmentGroupValues( - rawAppointment, - resourceManager.resources, - ); - - return { - ...rawAppointment, - ...rawAppointmentGroupValues, - repeat: Boolean(appointment.recurrenceRule), - }; - } - - private createForm() { - const rawAppointment = this.state.appointment.data; - const formData = this.createFormData(rawAppointment); - - this.form.create(this.triggerResize.bind(this), this.changeSize.bind(this), formData); // TODO - } - - private isReadOnly(rawAppointment) { - const appointment = this.createAppointmentAdapter(rawAppointment); - - if (rawAppointment && appointment.disabled) { - return true; - } - - if (this.state.action === ACTION_TO_APPOINTMENT.CREATE) { - return false; - } - - return !this.scheduler.getEditingConfig().allowUpdating; - } - - private createAppointmentAdapter(rawAppointment) { - return new AppointmentAdapter( - rawAppointment, - this.scheduler.getDataAccessors(), - ); - } - - private updateForm() { - const { data } = this.state.appointment; - const appointment = this.createFormData(data); - const formData = this.createAppointmentAdapter(appointment) - .clone() - .calculateDates(this.scheduler.getTimeZoneCalculator(), 'toAppointment') - .source; - - this.form.readOnly = this.isReadOnly(formData); - this.form.updateFormData(formData); - } - - triggerResize() { - if (this.popup) { - triggerResizeEvent(this.popup.$element()); - } - } - - changeSize(isRecurrence) { - if (this.popup) { - const isFullScreen = isPopupFullScreenNeeded(); - const maxWidth = isFullScreen - ? '100%' - : getMaxWidth(isRecurrence); - this.popup.option('fullScreen', isFullScreen); - this.popup.option('maxWidth', maxWidth); - } - } - - updatePopupFullScreenMode() { - if (this.form.dxForm && this.visible) { // TODO - const { formData } = this.form; - const dataAccessors = this.scheduler.getDataAccessors(); - const isRecurrence = dataAccessors.get('recurrenceRule', formData); - - this.changeSize(isRecurrence); - } - } - - saveChangesAsync(isShowLoadPanel) { - // @ts-expect-error - const deferred = new Deferred(); - const validation = this.form.dxForm.validate(); - - isShowLoadPanel && this.showLoadPanel(); - - when(validation?.complete || validation).done((validation) => { - if (validation && !validation.isValid) { - hideLoading(); - deferred.resolve(false); - return; - } - - const { repeat } = this.form.formData; - const adapter = this.createAppointmentAdapter(this.form.formData); - const clonedAdapter = adapter - .clone() - .calculateDates(this.scheduler.getTimeZoneCalculator(), 'fromAppointment'); - const shouldClearRecurrenceRule = !repeat && Boolean(clonedAdapter.recurrenceRule); - - this.addMissingDSTTime(adapter, clonedAdapter); - - if (shouldClearRecurrenceRule) { - clonedAdapter.recurrenceRule = ''; - } - - const appointment = clonedAdapter.source; - delete appointment.repeat; // TODO - - switch (this.state.action) { - case ACTION_TO_APPOINTMENT.CREATE: - this.scheduler.addAppointment(appointment).done(deferred.resolve); - break; - case ACTION_TO_APPOINTMENT.UPDATE: - this.scheduler.updateAppointment(this.state.appointment.data, appointment).done(deferred.resolve); - break; - case ACTION_TO_APPOINTMENT.EXCLUDE_FROM_SERIES: - this.scheduler.updateAppointment(this.state.excludeInfo.sourceAppointment, this.state.excludeInfo.updatedAppointment); - this.scheduler.addAppointment(appointment).done(deferred.resolve); - break; - default: - break; - } - - deferred.done(() => { - hideLoading(); - this.state.lastEditData = appointment; - }); - }); - - return deferred.promise(); - } - - private doneButtonClickHandler(e) { - e.cancel = true; - this.saveEditDataAsync(); - } - - saveEditDataAsync() { - // @ts-expect-error - const deferred = new Deferred(); - - if (this.tryLockSaveChanges()) { - when(this.saveChangesAsync(true)).done(() => { - if (this.state.lastEditData) { // TODO - const adapter = this.createAppointmentAdapter(this.state.lastEditData); - - const { startDate, endDate, allDay } = adapter; - - const startTime = startDate.getTime(); - const endTime = endDate.getTime(); - - const inAllDayRow = allDay || (endTime - startTime) >= DAY_IN_MS; - const resourceManager = this.scheduler.getResourceManager(); - const appointmentGroupValues = getAppointmentGroupValues( - this.state.lastEditData, - resourceManager.resources, - ); - - this.scheduler.updateScrollPosition(startDate, appointmentGroupValues, inAllDayRow); - this.state.lastEditData = null; - } - - this.unlockSaveChanges(); - - deferred.resolve(); - }); - } - - return deferred.promise(); - } - - private showLoadPanel() { - const container = this.popup.$overlayContent(); - - showLoading({ - container, - position: { - of: container, - }, - }); - } - - private tryLockSaveChanges() { - if (this.state.saveChangesLocker === false) { - this.state.saveChangesLocker = true; - return true; - } - return false; - } - - private unlockSaveChanges() { - this.state.saveChangesLocker = false; - } - - // NOTE: Fix ticket T1102713 - private addMissingDSTTime(formAppointmentAdapter, clonedAppointmentAdapter) { - const timeZoneCalculator = this.scheduler.getTimeZoneCalculator(); - - clonedAppointmentAdapter.startDate = this.addMissingDSTShiftToDate( - timeZoneCalculator, - formAppointmentAdapter.startDate, - clonedAppointmentAdapter.startDate, - ); - - if (clonedAppointmentAdapter.endDate) { - clonedAppointmentAdapter.endDate = this.addMissingDSTShiftToDate( - timeZoneCalculator, - formAppointmentAdapter.endDate, - clonedAppointmentAdapter.endDate, - ); - } - } - - private addMissingDSTShiftToDate(timeZoneCalculator, originFormDate, clonedDate) { - const originTimezoneShift = timeZoneCalculator.getOffsets(originFormDate)?.common; - const clonedTimezoneShift = timeZoneCalculator.getOffsets(clonedDate)?.common; - const shiftDifference = originTimezoneShift - clonedTimezoneShift; - - return shiftDifference - ? new Date(clonedDate.getTime() + shiftDifference * toMs('hour')) - : clonedDate; - } -} diff --git a/packages/devextreme/js/__internal/scheduler/m_recurrence_editor.ts b/packages/devextreme/js/__internal/scheduler/m_recurrence_editor.ts deleted file mode 100644 index 501339c94bfb..000000000000 --- a/packages/devextreme/js/__internal/scheduler/m_recurrence_editor.ts +++ /dev/null @@ -1,844 +0,0 @@ -/* eslint-disable max-classes-per-file, spellcheck/spell-checker */ -import '@js/ui/radio_group'; - -import dateLocalization from '@js/common/core/localization/date'; -import messageLocalization from '@js/common/core/localization/message'; -import registerComponent from '@js/core/component_registrator'; -import $ from '@js/core/renderer'; -import dateUtils from '@js/core/utils/date'; -import { extend } from '@js/core/utils/extend'; -import { isDefined } from '@js/core/utils/type'; -import ButtonGroup from '@js/ui/button_group'; -import Editor from '@js/ui/editor/editor'; -import Form from '@js/ui/form'; -import { current, isFluent } from '@js/ui/themes'; - -import { getRecurrenceString, parseRecurrenceRule } from './recurrence/base'; -import { daysFromByDayRule } from './recurrence/days_from_by_day_rule'; - -const RECURRENCE_EDITOR = 'dx-recurrence-editor'; -const LABEL_POSTFIX = '-label'; -const WRAPPER_POSTFIX = '-wrapper'; -const RECURRENCE_EDITOR_CONTAINER = 'dx-recurrence-editor-container'; -const REPEAT_END_TYPE_EDITOR = 'dx-recurrence-radiogroup-repeat-type'; -const REPEAT_COUNT_EDITOR = 'dx-recurrence-numberbox-repeat-count'; -const REPEAT_UNTIL_DATE_EDITOR = 'dx-recurrence-datebox-until-date'; -const RECURRENCE_BUTTON_GROUP = 'dx-recurrence-button-group'; -const FREQUENCY_EDITOR = 'dx-recurrence-selectbox-freq'; -const INTERVAL_EDITOR = 'dx-recurrence-numberbox-interval'; -const REPEAT_ON_EDITOR = 'dx-recurrence-repeat-on'; -const DAY_OF_MONTH = 'dx-recurrence-numberbox-day-of-month'; -const MONTH_OF_YEAR = 'dx-recurrence-selectbox-month-of-year'; - -const recurrentEditorNumberBoxWidth = 90; -const repeatInputWidth = '100%'; -const recurrentEditorSelectBoxWidth = 120; -const defaultRecurrenceTypeIndex = 1; // default daily recurrence - -const frequenciesMessages = [ - /* { - // functionality is not removed, but hide the ability to set minute recurrence in the editor. - // in the future, if we publish the dxRecurrenceEditor, then we publish the minute recurrence - recurrence: 'dxScheduler-recurrenceMinutely', - value: 'minutely' - } */ - { - recurrence: 'dxScheduler-recurrenceHourly', - value: 'hourly', - }, { - recurrence: 'dxScheduler-recurrenceDaily', - value: 'daily', - }, { - recurrence: 'dxScheduler-recurrenceWeekly', - value: 'weekly', - }, { - recurrence: 'dxScheduler-recurrenceMonthly', - value: 'monthly', - }, { - recurrence: 'dxScheduler-recurrenceYearly', - value: 'yearly', - }, -]; - -const frequencies = frequenciesMessages.map((item) => ({ text() { return messageLocalization.format(item.recurrence); }, value: item.value })); - -const repeatEndTypes = [ - { type: 'never' }, - { type: 'until' }, - { type: 'count' }, -]; - -const days = ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA']; - -const getStylingModeFunc = (): string | undefined => (isFluent(current()) ? 'filled' : undefined); - -class RecurrenceRule { - private recurrenceRule: any; - - constructor(rule) { - this.recurrenceRule = parseRecurrenceRule(rule); - } - - makeRules(string) { - this.recurrenceRule = parseRecurrenceRule(string); - } - - makeRule(field, value) { - if (!value || (Array.isArray(value) && !value.length)) { - // eslint-disable-next-line @typescript-eslint/no-dynamic-delete - delete this.recurrenceRule[field]; - return; - } - - if (isDefined(field)) { - if (field === 'until') { - delete this.recurrenceRule.count; - } - - if (field === 'count') { - delete this.recurrenceRule.until; - } - - this.recurrenceRule[field] = value; - } - } - - getRepeatEndRule() { - const rules = this.recurrenceRule; - - if ('count' in rules) { - return 'count'; - } - - if ('until' in rules) { - return 'until'; - } - - return 'never'; - } - - getRecurrenceString() { - return getRecurrenceString(this.recurrenceRule); - } - - getRules() { - return this.recurrenceRule; - } - - getDaysFromByDayRule() { - return daysFromByDayRule(this.recurrenceRule); - } -} - -class RecurrenceEditor extends Editor { - private recurrenceRule!: RecurrenceRule; - - private $container: any; - - private weekEditor: any; - - private editors!: any[]; - - private $repeatOnWeek: any; - - private recurrenceForm: any; - - _getDefaultOptions() { - // @ts-expect-error - const defaultOptions = super._getDefaultOptions(); - - return extend(defaultOptions, { - value: null, - - startDate: new Date(), - - firstDayOfWeek: undefined, - }); - } - - private getFirstDayOfWeek() { - const firstDayOfWeek = this.option('firstDayOfWeek'); - return isDefined(firstDayOfWeek) ? firstDayOfWeek : dateLocalization.firstDayOfWeekIndex(); - } - - private createComponent(element, name, config = {}) { - // @ts-expect-error - this._extendConfig(config, { - readOnly: this.option('readOnly'), - }); - - // @ts-expect-error - return super._createComponent(element, name, config); - } - - _init() { - // @ts-expect-error - super._init(); - this.recurrenceRule = new RecurrenceRule(this.option('value')); - } - - _render() { - // @ts-expect-error - super._render(); - - (this.$element() as any).addClass(RECURRENCE_EDITOR); - - this.$container = $('
') - .addClass(RECURRENCE_EDITOR_CONTAINER) - .appendTo(this.$element()); - - this.prepareEditors(); - this.renderEditors(this.$container); - this.updateRepeatInputAriaLabel(); - } - - getEditorByField(fieldName) { - let editor = this.getRecurrenceForm().getEditor(fieldName); - - if (!isDefined(editor)) { - switch (fieldName) { - case 'byday': - editor = this.weekEditor; - break; - default: - break; - } - } - - return editor; - } - - private prepareEditors() { - const freq = (this.recurrenceRule.getRules().freq || frequenciesMessages[defaultRecurrenceTypeIndex].value).toLowerCase(); - - this.editors = [ - this.createFreqEditor(freq), - this.createIntervalEditor(freq), - this.createRepeatOnLabel(freq), - { - itemType: 'group', - cssClass: REPEAT_ON_EDITOR, - colCount: 2, - colCountByScreen: { xs: 2 }, - items: this.createRepeatOnEditor(freq), - }, - { - itemType: 'group', - colCount: 2, - items: this.createRepeatEndEditor(), - }, - ]; - - return this.editors; - } - - private createFreqEditor(freq) { - return { - dataField: 'freq', - name: 'FREQ', - editorType: 'dxSelectBox', - cssClass: FREQUENCY_EDITOR, - editorOptions: { - stylingMode: getStylingModeFunc(), - items: frequencies, - value: freq, - field: 'freq', - valueExpr: 'value', - displayExpr: 'text', - layout: 'horizontal', - elementAttr: { - class: FREQUENCY_EDITOR, - }, - onValueChanged: (args) => this.valueChangedHandler(args), - }, - label: { - text: messageLocalization.format('dxScheduler-editorLabelRecurrence'), - }, - }; - } - - private createIntervalEditor(freq) { - const interval = this.recurrenceRule.getRules().interval || 1; - return { - itemType: 'group', - colCount: 2, - cssClass: `${INTERVAL_EDITOR}${WRAPPER_POSTFIX}`, - colCountByScreen: { xs: 2 }, - items: [ - { - dataField: 'interval', - editorType: 'dxNumberBox', - editorOptions: { - stylingMode: getStylingModeFunc(), - format: '#', - width: recurrentEditorNumberBoxWidth, - min: 1, - field: 'interval', - value: interval, - showSpinButtons: true, - useLargeSpinButtons: false, - elementAttr: { - class: INTERVAL_EDITOR, - }, - onValueChanged: (args) => this.valueChangedHandler(args), - }, - label: { - text: messageLocalization.format('dxScheduler-recurrenceRepeatEvery'), - }, - }, - { - name: 'intervalLabel', - cssClass: `${INTERVAL_EDITOR}${LABEL_POSTFIX}`, - template: () => messageLocalization.format(`dxScheduler-recurrenceRepeat${freq.charAt(0).toUpperCase()}${freq.substr(1).toLowerCase()}`), - }, - ], - }; - } - - private createRepeatOnLabel(freq) { - return { - itemType: 'group', - cssClass: `${REPEAT_ON_EDITOR}${LABEL_POSTFIX}`, - items: [ - { - name: 'repeatOnLabel', - colSpan: 2, - template: () => messageLocalization.format('dxScheduler-recurrenceRepeatOn'), - visible: freq && freq !== 'daily' && freq !== 'hourly', - }, - ], - }; - } - - private createRepeatOnEditor(freq) { - return [ - this.createByDayEditor(freq), - this.createByMonthEditor(freq), - this.createByMonthDayEditor(freq), - ]; - } - - private createByDayEditor(freq) { - return { - dataField: 'byday', - colSpan: 2, - template: (_, itemElement) => { - const firstDayOfWeek = this.getFirstDayOfWeek() as any; - const byDay = this.daysOfWeekByRules(); - - const localDaysNames = dateLocalization.getDayNames('abbreviated'); - const dayNames = days.slice(firstDayOfWeek).concat(days.slice(0, firstDayOfWeek)); - - const itemsButtonGroup = localDaysNames.slice(firstDayOfWeek).concat(localDaysNames.slice(0, firstDayOfWeek)).map((item, index) => ({ text: item, key: dayNames[index] })); - - this.$repeatOnWeek = $('
').addClass(RECURRENCE_BUTTON_GROUP).appendTo(itemElement); - - this.weekEditor = this.createComponent(this.$repeatOnWeek, ButtonGroup, { - items: itemsButtonGroup, - field: 'byday', - selectionMode: 'multiple', - selectedItemKeys: byDay, - keyExpr: 'key', - onSelectionChanged: (e) => { - const selectedItemKeys = e.component.option('selectedItemKeys'); - const selectedKeys = selectedItemKeys?.length - ? selectedItemKeys - : this.getDefaultByDayValue(); - - this.recurrenceRule.makeRule('byday', selectedKeys); - this.changeEditorValue(); - }, - }); - }, - visible: freq === 'weekly', - label: { - visible: false, - }, - }; - } - - private createByMonthEditor(freq) { - const monthsName = (dateLocalization.getMonthNames as any)('wide'); - const months = [...Array(12)].map((_, i) => ({ value: `${i + 1}`, text: monthsName[i] })); - - return { - dataField: 'bymonth', - editorType: 'dxSelectBox', - editorOptions: { - stylingMode: getStylingModeFunc(), - field: 'bymonth', - items: months, - value: this.monthOfYearByRules(), - width: recurrentEditorSelectBoxWidth, - displayExpr: 'text', - valueExpr: 'value', - elementAttr: { - class: MONTH_OF_YEAR, - }, - onValueChanged: (args) => this.valueChangedHandler(args), - }, - visible: freq === 'yearly', - label: { - visible: false, - }, - }; - } - - private createByMonthDayEditor(freq) { - return { - dataField: 'bymonthday', - editorType: 'dxNumberBox', - editorOptions: { - stylingMode: getStylingModeFunc(), - min: 1, - max: 31, - format: '#', - width: recurrentEditorNumberBoxWidth, - field: 'bymonthday', - showSpinButtons: true, - useLargeSpinButtons: false, - value: this.dayOfMonthByRules(), - elementAttr: { - class: DAY_OF_MONTH, - }, - onValueChanged: (args) => this.valueChangedHandler(args), - }, - visible: freq === 'monthly' || freq === 'yearly', - label: { - visible: false, - }, - }; - } - - private createRepeatEndEditor() { - const repeatType = this.recurrenceRule.getRepeatEndRule(); - - return [{ - colSpan: 2, - template: messageLocalization.format('dxScheduler-recurrenceEnd'), - }, { - colSpan: 1, - label: { visible: false }, - dataField: 'repeatEnd', - editorType: 'dxRadioGroup', - editorOptions: { - items: repeatEndTypes, - value: repeatType, - valueExpr: 'type', - field: 'repeatEnd', - itemTemplate: (itemData) => { - if (itemData.type === 'count') { - return messageLocalization.format('dxScheduler-recurrenceAfter'); - } - if (itemData.type === 'until') { - return messageLocalization.format('dxScheduler-recurrenceOn'); - } - - return messageLocalization.format('dxScheduler-recurrenceNever'); - }, - layout: 'vertical', - elementAttr: { class: REPEAT_END_TYPE_EDITOR }, - onValueChanged: (args) => this.repeatEndValueChangedHandler(args), - }, - }, { - colSpan: 1, - itemType: 'group', - items: [ - this.getRepeatUntilEditorOptions(), - this.getRepeatCountEditorOptions(), - ], - }]; - } - - private renderEditors($container) { - this.recurrenceForm = this.createComponent($container, Form, { - items: this.editors, - showValidationSummary: false, - scrollingEnabled: true, - showColonAfterLabel: false, - labelLocation: 'top', - }); - - this.changeRepeatEndInputsVisibility(); - } - - getRecurrenceForm() { - return this.recurrenceForm; - } - - changeValueByVisibility(value) { - if (value) { - if (!this.option('value')) { - this.handleDefaults(); - } - } else { - this.recurrenceRule.makeRules(''); - this.option('value', ''); - } - } - - private handleDefaults() { - this.recurrenceRule.makeRule('freq', frequenciesMessages[defaultRecurrenceTypeIndex].value); - this.changeEditorValue(); - } - - private changeEditorValue() { - this.option('value', this.recurrenceRule.getRecurrenceString() ?? ''); - } - - private daysOfWeekByRules() { - let daysByRule = this.recurrenceRule.getDaysFromByDayRule(); - if (!daysByRule.length) { - daysByRule = this.getDefaultByDayValue(); - } - - return daysByRule; - } - - private getDefaultByDayValue() { - const startDate = this.option('startDate') as any; - const startDay = startDate.getDay(); - return [days[startDay]]; - } - - private dayOfMonthByRules() { - let dayByRule = this.recurrenceRule.getRules().bymonthday; - - if (!dayByRule) { - dayByRule = (this.option('startDate') as any).getDate(); - } - - return dayByRule; - } - - private monthOfYearByRules() { - let monthByRule = this.recurrenceRule.getRules().bymonth; - - if (!monthByRule) { - monthByRule = (this.option('startDate') as any).getMonth() + 1; - } - - return String(monthByRule); - } - - private repeatEndValueChangedHandler(args) { - const { value } = args; - - this.changeRepeatEndInputsVisibility(value); - - if (value === 'until') { - this.recurrenceRule.makeRule(value, this.getUntilValue()); - } - if (value === 'count') { - this.recurrenceRule.makeRule(value, this.recurrenceForm.option('formData.count')); - } - if (value === 'never') { - this.recurrenceRule.makeRule('count', ''); - this.recurrenceRule.makeRule('until', ''); - } - - this.changeEditorValue(); - this.updateRepeatInputAriaLabel(); - } - - private changeRepeatEndInputsVisibility(value = this.recurrenceRule.getRepeatEndRule()) { - if (value === 'until') { - this.recurrenceForm.itemOption('until', 'visible', true); - this.recurrenceForm.itemOption('count', 'visible', false); - } - if (value === 'count') { - this.recurrenceForm.itemOption('until', 'visible', false); - this.recurrenceForm.itemOption('count', 'visible', true); - } - if (value === 'never') { - this.recurrenceForm.itemOption('until', 'visible', false); - this.recurrenceForm.itemOption('count', 'visible', false); - } - } - - private getRepeatCountEditorOptions() { - const count = this.recurrenceRule.getRules().count || 1; - - return { - dataField: 'count', - cssClass: REPEAT_COUNT_EDITOR, - label: { visible: false }, - editorType: 'dxNumberBox', - editorOptions: { - stylingMode: getStylingModeFunc(), - field: 'count', - format: `# ${messageLocalization.format('dxScheduler-recurrenceRepeatCount')}`, - width: repeatInputWidth, - min: 1, - showSpinButtons: true, - useLargeSpinButtons: false, - value: count, - onValueChanged: this.repeatCountValueChangeHandler.bind(this), - inputAttr: { 'aria-label': messageLocalization.format('dxScheduler-recurrenceOccurrenceLabel') }, - }, - }; - } - - private updateRepeatInputAriaLabel(): void { - const radioButtons = this.getEditorByField('repeatEnd').itemElements(); - const untilLabel = messageLocalization.format('dxScheduler-recurrenceOn'); - const untilValue = this.recurrenceForm.getEditor('until').option('value'); - const untilValueFormat = `${dateLocalization.format(untilValue, 'd')} ${dateLocalization.format(untilValue, 'monthAndYear')}`; - const isUntilVisible = this.recurrenceForm.itemOption('until').visible; - - const countLabel = messageLocalization.format('dxScheduler-recurrenceAfter'); - const countPostfix = messageLocalization.format('dxScheduler-recurrenceRepeatCount'); - const countValue = this.recurrenceForm.getEditor('count').option('value'); - const isCountVisible = this.recurrenceForm.itemOption('count').visible; - - radioButtons[1].setAttribute('aria-label', isUntilVisible ? `${untilLabel} ${untilValueFormat}` : untilLabel); - radioButtons[2].setAttribute('aria-label', isCountVisible ? `${countLabel} ${countValue} ${countPostfix}` : countLabel); - } - - private repeatCountValueChangeHandler(args) { - if (this.recurrenceRule.getRepeatEndRule() === 'count') { - const { value } = args; - this.recurrenceRule.makeRule('count', value); - this.changeEditorValue(); - this.updateRepeatInputAriaLabel(); - } - } - - private getRepeatUntilEditorOptions() { - const until = this.getUntilValue(); - - return { - dataField: 'until', - label: { visible: false }, - cssClass: REPEAT_UNTIL_DATE_EDITOR, - editorType: 'dxDateBox', - editorOptions: { - stylingMode: getStylingModeFunc(), - field: 'until', - value: until, - type: 'date', - width: repeatInputWidth, - onValueChanged: this.repeatUntilValueChangeHandler.bind(this), - calendarOptions: { - firstDayOfWeek: this.getFirstDayOfWeek(), - }, - useMaskBehavior: true, - inputAttr: { 'aria-label': messageLocalization.format('dxScheduler-recurrenceUntilDateLabel') }, - }, - }; - } - - private formatUntilDate(date: Date): Date { - const untilDate = this.recurrenceRule.getRules().until; - const isSameDate = dateUtils.sameDate(untilDate, date); - - return untilDate && isSameDate - ? date - : dateUtils.setToDayEnd(date); - } - - private repeatUntilValueChangeHandler(args) { - if (this.recurrenceRule.getRepeatEndRule() === 'until') { - const dateInTimeZone = this.formatUntilDate(new Date(args.value)); - const getStartDateTimeZone: any = this.option('getStartDateTimeZone'); - const appointmentTimeZone = getStartDateTimeZone(); - - const path = appointmentTimeZone ? 'fromAppointment' : 'fromGrid'; - const dateInLocaleTimeZone = (this.option('timeZoneCalculator') as any) - .createDate(dateInTimeZone, path, appointmentTimeZone); - - this.recurrenceRule.makeRule('until', dateInLocaleTimeZone); - this.changeEditorValue(); - this.updateRepeatInputAriaLabel(); - } - } - - private valueChangedHandler(args) { - const { value, previousValue } = args; - const field = args.component.option('field'); - - if (!this.option('visible')) { - this.option('value', ''); - } else { - this.recurrenceRule.makeRule(field, value); - if (field === 'freq') { - this.makeRepeatOnRule(value); - this.changeRepeatOnVisibility(value, previousValue); - } - this.changeEditorValue(); - } - } - - private makeRepeatOnRule(value) { - if (value === 'daily' || value === 'hourly') { - this.recurrenceRule.makeRule('byday', ''); - this.recurrenceRule.makeRule('bymonth', ''); - this.recurrenceRule.makeRule('bymonthday', ''); - } - if (value === 'weekly') { - this.recurrenceRule.makeRule('byday', this.daysOfWeekByRules()); - this.recurrenceRule.makeRule('bymonth', ''); - this.recurrenceRule.makeRule('bymonthday', ''); - } - - if (value === 'monthly') { - this.recurrenceRule.makeRule('bymonthday', this.dayOfMonthByRules()); - this.recurrenceRule.makeRule('bymonth', ''); - this.recurrenceRule.makeRule('byday', ''); - } - - if (value === 'yearly') { - this.recurrenceRule.makeRule('bymonthday', this.dayOfMonthByRules()); - this.recurrenceRule.makeRule('bymonth', this.monthOfYearByRules()); - this.recurrenceRule.makeRule('byday', ''); - } - } - - _optionChanged(args) { - switch (args.name) { - case 'readOnly': - this.recurrenceForm?.option('readOnly', args.value); - this.weekEditor?.option('readOnly', args.value); - // @ts-expect-error - super._optionChanged(args); - break; - case 'value': - this.recurrenceRule.makeRules(args.value); - - this.changeRepeatIntervalLabel(); - this.changeRepeatEndInputsVisibility(); - this.changeEditorsValue(this.recurrenceRule.getRules()); - - // @ts-expect-error - super._optionChanged(args); - break; - case 'startDate': - this.makeRepeatOnRule(this.recurrenceRule.getRules().freq); - - if (isDefined(this.recurrenceRule.getRecurrenceString())) { - this.changeEditorValue(); - } - - break; - case 'firstDayOfWeek': - if (this.weekEditor) { - const localDaysNames = dateLocalization.getDayNames('abbreviated'); - const dayNames = days.slice(args.value).concat(days.slice(0, args.value)); - - const itemsButtonGroup = localDaysNames.slice(args.value).concat(localDaysNames.slice(0, args.value)).map((item, index) => ({ text: item, key: dayNames[index] })); - - this.weekEditor.option('items', itemsButtonGroup); - } - if (this.recurrenceForm.itemOption('until').visible) { - this.recurrenceForm.getEditor('until').option('calendarOptions.firstDayOfWeek', this.getFirstDayOfWeek()); - } - break; - default: - // @ts-expect-error - super._optionChanged(args); - } - } - - private changeRepeatOnVisibility(freq, previousFreq) { - if (freq !== previousFreq) { - this.recurrenceForm.itemOption('byday', 'visible', false); - this.recurrenceForm.itemOption('bymonthday', 'visible', false); - this.recurrenceForm.itemOption('bymonth', 'visible', false); - - this.recurrenceForm.itemOption('repeatOnLabel', 'visible', freq && freq !== 'daily' && freq !== 'hourly'); - - if (freq === 'weekly') { - this.recurrenceForm.itemOption('byday', 'visible', true); - } - if (freq === 'monthly') { - this.recurrenceForm.itemOption('bymonthday', 'visible', true); - } - if (freq === 'yearly') { - this.recurrenceForm.itemOption('bymonthday', 'visible', true); - this.recurrenceForm.itemOption('bymonth', 'visible', true); - } - } - } - - private changeRepeatIntervalLabel() { - const { freq } = this.recurrenceRule.getRules(); - - freq && this.recurrenceForm.itemOption('intervalLabel', 'template', messageLocalization.format(`dxScheduler-recurrenceRepeat${freq.charAt(0).toUpperCase()}${freq.substr(1).toLowerCase()}`)); - } - - private changeEditorsValue(rules) { - this.recurrenceForm.getEditor('freq').option('value', (rules.freq || frequenciesMessages[defaultRecurrenceTypeIndex].value).toLowerCase()); - - this.changeDayOfWeekValue(); - this.changeDayOfMonthValue(); - this.changeMonthOfYearValue(); - - this.changeIntervalValue(rules.interval); - - this.changeRepeatCountValue(); - this.changeRepeatEndValue(); - this.changeRepeatUntilValue(); - } - - private changeIntervalValue(value) { - this.recurrenceForm.getEditor('interval').option('value', value || 1); - } - - private changeRepeatEndValue() { - const repeatType = this.recurrenceRule.getRepeatEndRule(); - - this.recurrenceForm.getEditor('repeatEnd').option('value', repeatType); - } - - private changeDayOfWeekValue() { - const isEditorVisible = this.recurrenceForm.itemOption('byday').visible; - if (isEditorVisible) { - const days = this.daysOfWeekByRules(); - this.getEditorByField('byday').option('selectedItemKeys', days); - } - } - - private changeDayOfMonthValue() { - const isEditorVisible = this.recurrenceForm.itemOption('bymonthday').visible; - if (isEditorVisible) { - const day = this.dayOfMonthByRules(); - this.recurrenceForm.getEditor('bymonthday').option('value', day); - } - } - - private changeMonthOfYearValue() { - const isEditorVisible = this.recurrenceForm.itemOption('bymonth').visible; - if (isEditorVisible) { - const month = this.monthOfYearByRules(); - this.recurrenceForm.getEditor('bymonth').option('value', month); - } - } - - private changeRepeatCountValue() { - const count = this.recurrenceRule.getRules().count || 1; - this.recurrenceForm.getEditor('count').option('value', count); - } - - private changeRepeatUntilValue() { - this.recurrenceForm.getEditor('until').option('value', this.getUntilValue()); - } - - private getUntilValue() { - const untilDate = this.recurrenceRule.getRules().until; - - if (!untilDate) { - return this.formatUntilDate(new Date()); - } - - const getStartDateTimeZone: any = this.option('getStartDateTimeZone'); - const appointmentTimeZone = getStartDateTimeZone(); - - const path = appointmentTimeZone ? 'toAppointment' : 'toGrid'; - - return (this.option('timeZoneCalculator') as any).createDate(untilDate, path, appointmentTimeZone); - } -} - -registerComponent('dxRecurrenceEditor', RecurrenceEditor as any); - -export default RecurrenceEditor; diff --git a/packages/devextreme/js/__internal/scheduler/m_scheduler.ts b/packages/devextreme/js/__internal/scheduler/m_scheduler.ts index 7b446445240b..017c70cd211d 100644 --- a/packages/devextreme/js/__internal/scheduler/m_scheduler.ts +++ b/packages/devextreme/js/__internal/scheduler/m_scheduler.ts @@ -38,9 +38,7 @@ import { dateUtilsTs } from '@ts/core/utils/date'; import { createA11yStatusContainer } from './a11y_status/a11y_status_render'; import { getA11yStatusText } from './a11y_status/a11y_status_text'; import { AppointmentForm } from './appointment_popup/m_form'; -import { AppointmentForm as AppointmentLegacyForm } from './appointment_popup/m_legacy_form'; -import { ACTION_TO_APPOINTMENT, AppointmentPopup as AppointmentLegacyPopup } from './appointment_popup/m_legacy_popup'; -import { AppointmentPopup } from './appointment_popup/m_popup'; +import { ACTION_TO_APPOINTMENT, AppointmentPopup } from './appointment_popup/m_popup'; import AppointmentCollection from './appointments/m_appointment_collection'; import type { AppointmentsProperties } from './appointments_new/appointments'; import { Appointments } from './appointments_new/appointments'; @@ -81,7 +79,6 @@ import { isAgendaWorkspaceComponent } from './utils/is_agenda_workpace_component import { VIEWS } from './utils/options/constants_view'; import type { NormalizedView } from './utils/options/types'; import { setAppointmentGroupValues } from './utils/resource_manager/appointment_groups_utils'; -import { createResourceEditorModel } from './utils/resource_manager/popup_utils'; import { ResourceManager } from './utils/resource_manager/resource_manager'; import AppointmentLayoutManager from './view_model/appointments_layout_manager'; import { AppointmentDataSource } from './view_model/m_appointment_data_source'; @@ -943,7 +940,6 @@ class Scheduler extends SchedulerOptionsBaseWidget { allowDeleting: Boolean(editing), allowResizing: Boolean(editing), allowDragging: Boolean(editing), - legacyForm: false, }; if (isObject(editing)) { @@ -1100,7 +1096,7 @@ class Scheduler extends SchedulerOptionsBaseWidget { private createAppointmentPopupForm() { if (this.appointmentForm) { - this.appointmentForm.form?.dispose(); + this.appointmentForm.dispose(); } this.appointmentForm = this.createAppointmentForm(); @@ -1130,12 +1126,6 @@ class Scheduler extends SchedulerOptionsBaseWidget { getTimeZoneCalculator: () => this.timeZoneCalculator, }; - if (this.editing.legacyForm) { - (scheduler as any).createResourceEditorModel = () => createResourceEditorModel(this.resourceManager.resourceById); - - return new AppointmentLegacyForm(scheduler); - } - return new AppointmentForm(scheduler); } @@ -1162,9 +1152,7 @@ class Scheduler extends SchedulerOptionsBaseWidget { this._workSpace.updateScrollPosition(startDate, appointmentGroupValues, inAllDayRow); }, }; - return this.editing.legacyForm - ? new AppointmentLegacyPopup(scheduler, form) - : new AppointmentPopup(scheduler, form); + return new AppointmentPopup(scheduler, form); } private getAppointmentTooltipOptions() { @@ -1624,7 +1612,6 @@ class Scheduler extends SchedulerOptionsBaseWidget { if (isPopupEditing) { this.appointmentPopup.show(singleRawAppointment, { - isToolbarVisible: true, // TODO: remove when legacyForm is deleted action: ACTION_TO_APPOINTMENT.EXCLUDE_FROM_SERIES, excludeInfo: { sourceAppointment: rawAppointment, @@ -1907,13 +1894,6 @@ class Scheduler extends SchedulerOptionsBaseWidget { this._fireContentReadyAction(); } - /// #DEBUG - // TODO: remove when legacyForm is deleted - getAppointmentDetailsForm() { // for tests - return this.appointmentForm.form; - } - /// #ENDDEBUG - getAppointmentsInstance() { return this._appointments; } @@ -2006,7 +1986,6 @@ class Scheduler extends SchedulerOptionsBaseWidget { if (isCreateAppointment) { delete this.editAppointmentData; // TODO this.editing.allowAdding && this.appointmentPopup.show(rawAppointment, { - isToolbarVisible: true, // TODO: remove when legacyForm is deleted action: ACTION_TO_APPOINTMENT.CREATE, }); } else { @@ -2016,7 +1995,6 @@ class Scheduler extends SchedulerOptionsBaseWidget { this.editAppointmentData = rawAppointment; // TODO this.appointmentPopup.show(rawAppointment, { - isToolbarVisible: this.editing.allowUpdating, // TODO: remove when legacyForm is deleted action: ACTION_TO_APPOINTMENT.UPDATE, }); }, false, true); diff --git a/packages/devextreme/js/__internal/scheduler/utils/options/constants.ts b/packages/devextreme/js/__internal/scheduler/utils/options/constants.ts index 8bbab436d6c8..f90336158407 100644 --- a/packages/devextreme/js/__internal/scheduler/utils/options/constants.ts +++ b/packages/devextreme/js/__internal/scheduler/utils/options/constants.ts @@ -103,7 +103,6 @@ export const DEFAULT_SCHEDULER_INTERNAL_OPTIONS: SchedulerInternalOptions = { indicatorTime: undefined, renovateRender: true, editing: { - legacyForm: false, // @ts-expect-error copy from default so that you can rewrite it ...DEFAULT_SCHEDULER_OPTIONS.editing, popup: {}, diff --git a/packages/devextreme/js/__internal/scheduler/utils/options/types.ts b/packages/devextreme/js/__internal/scheduler/utils/options/types.ts index b3e17098bce7..507cb2090c06 100644 --- a/packages/devextreme/js/__internal/scheduler/utils/options/types.ts +++ b/packages/devextreme/js/__internal/scheduler/utils/options/types.ts @@ -23,9 +23,7 @@ export type NormalizedView = View | AgendaView; export interface SchedulerInternalOptions { indicatorTime?: Date; renovateRender: boolean; - editing: Properties['editing'] | { - legacyForm: boolean; - }; + editing: Properties['editing']; _draggingMode: 'outlook' | 'default'; _appointmentTooltipOffset: { x: number; y: number }; appointmentPopupTemplate: template; diff --git a/packages/devextreme/js/__internal/scheduler/utils/resource_manager/popup_utils.test.ts b/packages/devextreme/js/__internal/scheduler/utils/resource_manager/popup_utils.test.ts deleted file mode 100644 index 5875f5bbd601..000000000000 --- a/packages/devextreme/js/__internal/scheduler/utils/resource_manager/popup_utils.test.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { - describe, expect, it, -} from '@jest/globals'; -import { - getResourceManagerMock, -} from '@ts/scheduler/__mock__/resource_manager.mock'; - -import { createResourceEditorModel } from './popup_utils'; - -describe('popup utils', () => { - describe('createResourceEditorModel', () => { - it('should return resource editor model', () => { - const manager = getResourceManagerMock(); - - expect( - createResourceEditorModel(manager.resourceById), - ).toEqual([ - { - dataField: 'nested.priorityId', - editorOptions: { - dataSource: expect.anything(), - displayExpr: 'text', - stylingMode: 'outlined', - valueExpr: 'id', - }, - editorType: 'dxSelectBox', - label: { text: 'Priority' }, - }, - { - dataField: 'assigneeId', - editorOptions: { - dataSource: expect.anything(), - displayExpr: 'name', - stylingMode: 'outlined', - valueExpr: 'guid', - }, - editorType: 'dxTagBox', - label: { text: 'Assignee' }, - }, - { - dataField: 'roomId', - editorOptions: { - dataSource: expect.anything(), - displayExpr: 'text', - stylingMode: 'outlined', - valueExpr: 'id', - }, - editorType: 'dxSelectBox', - label: { text: 'Room' }, - }, - ]); - }); - - it('Resource editor should always have label', () => { - expect( - createResourceEditorModel({ - roomId: { resourceIndex: 'roomId', dataAccessor: {} }, - } as any), - ).toEqual([ - { - dataField: 'roomId', - editorOptions: { - stylingMode: 'outlined', - }, - editorType: 'dxSelectBox', - label: { - text: 'roomId', - }, - }, - ]); - }); - }); -}); diff --git a/packages/devextreme/js/__internal/scheduler/utils/resource_manager/popup_utils.ts b/packages/devextreme/js/__internal/scheduler/utils/resource_manager/popup_utils.ts deleted file mode 100644 index c044bc8a4ac4..000000000000 --- a/packages/devextreme/js/__internal/scheduler/utils/resource_manager/popup_utils.ts +++ /dev/null @@ -1,24 +0,0 @@ -import type { SimpleItem } from '@js/ui/form'; -import { current, isFluent } from '@js/ui/themes'; - -import type { ResourceLoader } from '../loader/resource_loader'; - -export const createResourceEditorModel = ( - resourceById: Record, -): SimpleItem[] => Object - .values(resourceById) - .map((resourceLoader) => { - const dataField = resourceLoader.resourceIndex; - - return { - editorOptions: { - dataSource: resourceLoader.dataSource, - displayExpr: resourceLoader.dataAccessor.textExpr, - valueExpr: resourceLoader.dataAccessor.idExpr, - stylingMode: isFluent(current()) ? 'filled' : 'outlined', - }, - dataField, - editorType: resourceLoader.allowMultiple ? 'dxTagBox' : 'dxSelectBox', - label: { text: resourceLoader.resourceName ?? dataField }, - }; - }); diff --git a/packages/devextreme/testing/helpers/scheduler/helpers.js b/packages/devextreme/testing/helpers/scheduler/helpers.js index ff0457009b81..ecd95dbd2703 100644 --- a/packages/devextreme/testing/helpers/scheduler/helpers.js +++ b/packages/devextreme/testing/helpers/scheduler/helpers.js @@ -566,14 +566,14 @@ export class SchedulerTestWrapper extends ElementWrapper { hide: () => $(CLASSES.dialog).find('.dx-closebutton.dx-button').trigger('dxclick') }, - getPopup: () => $('.dx-overlay-wrapper.dx-scheduler-appointment-popup, .dx-overlay-wrapper.dx-scheduler-legacy-appointment-popup'), + getPopup: () => $('.dx-overlay-wrapper.dx-scheduler-appointment-popup'), getRecurrenceDialog: () => $(`${CLASSES.dialog}${CLASSES.popup}`), getPopupTitleElement: () => this.appointmentPopup.getPopup().find('.dx-popup-title'), hasVerticalScroll: () => { const scrollableContainer = this.appointmentPopup.getPopup().find('.dx-scrollable-container').get(0); return scrollableContainer.scrollHeight > scrollableContainer.clientHeight; }, - getPopupInstance: () => $('.dx-scheduler-appointment-popup.dx-widget, .dx-scheduler-legacy-appointment-popup.dx-widget').dxPopup('instance'), + getPopupInstance: () => $('.dx-scheduler-appointment-popup.dx-widget').dxPopup('instance'), isVisible: () => this.appointmentPopup.getPopup().length !== 0, setPopupHeight: height => this.appointmentPopup.getPopupInstance().option('height', height), getToolbarElementByLocation: location => { @@ -601,11 +601,10 @@ export class SchedulerTestWrapper extends ElementWrapper { this.appointmentForm = { getFormInstance: () => this.appointmentPopup.getPopup().find('.dx-form').dxForm('instance'), getEditor: name => this.appointmentForm.getFormInstance().getEditor(name), - setSubject: (value, fieldName = 'text') => this.appointmentForm.getEditor(fieldName).option('value', value), - setStartDate: (value) => this.appointmentForm.getEditor('startDate').option('value', value), - setEndDate: (value) => this.appointmentForm.getEditor('endDate').option('value', value), + setSubject: (value, fieldName = 'subjectEditor') => this.appointmentForm.getEditor(fieldName).option('value', value), + setStartDate: (value) => this.appointmentForm.getEditor('startDateEditor').option('value', value), + setEndDate: (value) => this.appointmentForm.getEditor('endDateEditor').option('value', value), - hasFormSingleColumn: () => $('.dx-responsivebox').first().hasClass('dx-responsivebox-screen-xs'), getRecurrentAppointmentFormDialogButtons: () => $('.dx-dialog-buttons .dx-button'), clickFormDialogButton: (index = 0) => this.appointmentForm.getRecurrentAppointmentFormDialogButtons().eq(index).trigger('dxclick'), getPendingEditorsCount: () => $(this.appointmentForm.getFormInstance().element()).find('.dx-validation-pending').length, diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/appointment.editing.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/appointment.editing.tests.js index 4ec7e23ebe92..0555241d9dc3 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/appointment.editing.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/appointment.editing.tests.js @@ -86,41 +86,6 @@ module('Integration: Appointment editing', { }; } }, () => { - test('Scheduler appointment popup should correctly update recurrence appointment', async function(assert) { - const tasks = [{ - text: 'Recurrence task', - start: new Date(2017, 2, 13), - end: new Date(2017, 2, 13, 0, 30), - recurrenceRule: 'FREQ=WEEKLY;BYDAY=MO,TH;COUNT=10' - }]; - - const scheduler = await this.createInstance({ - dataSource: tasks, - currentDate: new Date(2017, 2, 13), - currentView: 'month', - recurrenceEditMode: 'series', - views: ['month'], - startDateExpr: 'start', - endDateExpr: 'end', - editing: { legacyForm: true }, - }); - - scheduler.appointments.dblclick(0); - - const form = scheduler.instance.getAppointmentDetailsForm(); - const repeatSwitch = form.getEditor('repeat'); - repeatSwitch.option('value', false); - - scheduler.appointmentPopup.clickDoneButton(); - - assert.deepEqual(scheduler.instance.option('dataSource')[0], { - text: 'Recurrence task', - start: new Date(2017, 2, 13), - end: new Date(2017, 2, 13, 0, 30), - recurrenceRule: '' - }, 'Appointment was updated correctly'); - }); - test('updateAppointment method should be called with right args when task was resized, timelineMonth view', async function(assert) { const data = [{ text: 'Task 1', @@ -206,32 +171,6 @@ module('Integration: Appointment editing', { assert.expect(2); }); - test('Add new appointment', async function(assert) { - const data = new DataSource({ - store: this.tasks - }); - - const scheduler = await this.createInstance({ - currentDate: new Date(2015, 1, 9), - dataSource: data, - editing: { legacyForm: true } - }); - const addAppointment = scheduler.instance.addAppointment; - const spy = sinon.spy(() => new Deferred()); - const newItem = { startDate: new Date(2015, 1, 1, 1), endDate: new Date(2015, 1, 1, 2), text: 'caption' }; - scheduler.instance.addAppointment = spy; - try { - scheduler.instance.showAppointmentPopup(newItem, true); - - $('.dx-scheduler-legacy-appointment-popup .dx-popup-done').trigger('dxclick'); - - assert.ok(spy.calledOnce, 'Add method is called'); - assert.deepEqual(spy.getCall(0).args[0], newItem, 'New item is correct'); - } finally { - scheduler.instance.addAppointment = addAppointment; - } - }); - test('Add new appointment with delay(T381444)', async function(assert) { const done = assert.async(); const data = []; @@ -306,37 +245,6 @@ module('Integration: Appointment editing', { const popup = scheduler.instance.appointmentPopup.popup; }); - // TODO: update editors in popup - test('Update appointment', async function(assert) { - const data = new DataSource({ - store: this.tasks - }); - - const scheduler = await this.createInstance({ - currentDate: new Date(2015, 1, 9), - dataSource: data, - editing: { legacyForm: true } - }); - - const updateAppointment = scheduler.instance.updateAppointment; - const spy = sinon.spy(() => new Deferred()); - const updatedItem = this.tasks[0]; - scheduler.instance.updateAppointment = spy; - try { - scheduler.instance.showAppointmentPopup(updatedItem); - - $('.dx-scheduler-legacy-appointment-popup .dx-popup-done').trigger('dxclick'); - - hide(); - - assert.ok(spy.calledOnce, 'Update method is called'); - assert.deepEqual(spy.getCall(0).args[0], updatedItem, 'Target item is correct'); - assert.deepEqual(spy.getCall(0).args[1], updatedItem, 'New data is correct'); - } finally { - scheduler.instance.updateAppointment = updateAppointment; - } - }); - test('Scheduler should add only one appointment at multiple "done" button clicks on appointment form', async function(assert) { const a = { text: 'a', startDate: new Date(2017, 7, 9), endDate: new Date(2017, 7, 9, 0, 15) }; const scheduler = await createWrapper({ diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/appointment.monthView.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/appointment.monthView.tests.js index 77b4b65e3c2c..08035e6edd61 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/appointment.monthView.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/appointment.monthView.tests.js @@ -7,7 +7,6 @@ import Color from 'color'; import { DataSource } from 'common/data/data_source/data_source'; import { CustomStore } from 'common/data/custom_store'; import browser from 'core/utils/browser'; -import { APPOINTMENT_FORM_GROUP_NAMES } from '__internal/scheduler/appointment_popup/m_legacy_form'; import { initTestMarkup, createWrapper, @@ -385,93 +384,6 @@ module('Integration: Appointments in Month view', { assert.equal($appointment.length, 2, 'appointment is rendered'); }); - test('Scheduler appointment popup should be opened correctly for recurrence appointments after multiple opening(T710140)', async function(assert) { - const tasks = [{ - text: 'Recurrence task', - start: new Date(2017, 2, 13), - end: new Date(2017, 2, 13, 0, 30), - recurrenceRule: 'FREQ=WEEKLY;BYDAY=MO,TH;COUNT=10' - }]; - - const scheduler = await createInstance({ - dataSource: tasks, - currentDate: new Date(2017, 2, 13), - currentView: 'month', - views: ['month'], - startDateExpr: 'start', - endDateExpr: 'end', - editing: { - legacyForm: true, - } - }); - - scheduler.instance.showAppointmentPopup(tasks[0]); - $('.dx-dialog-buttons .dx-button').eq(0).trigger('dxclick'); - const form = scheduler.instance.getAppointmentDetailsForm(); - const descriptionEditor = form.getEditor('description'); - - descriptionEditor.option('value', 'Recurrence task 1'); - - scheduler.instance.hideAppointmentPopup(); - scheduler.instance.showAppointmentPopup(tasks[0]); - - $('.dx-dialog-buttons .dx-button').eq(0).trigger('dxclick'); - - const popup = scheduler.instance.appointmentPopup.popup; - const $buttonGroup = $(popup.$content()).find('.dx-buttongroup'); - - assert.deepEqual($buttonGroup.eq(0).dxButtonGroup('instance').option('selectedItemKeys'), ['MO', 'TH'], 'Right button group select item keys'); - }); - - test('Scheduler appointment popup should be opened correctly for recurrence appointments after opening for ordinary appointments(T710140)', async function(assert) { - const tasks = [{ - text: 'Task', - start: new Date(2017, 2, 13), - end: new Date(2017, 2, 13, 0, 30) - }, { - text: 'Recurrence task', - start: new Date(2017, 2, 13), - end: new Date(2017, 2, 13, 0, 30), - recurrenceRule: 'FREQ=WEEKLY;BYDAY=MO,TH;COUNT=10' - }]; - - const scheduler = await createInstance({ - dataSource: tasks, - currentDate: new Date(2017, 2, 13), - currentView: 'month', - views: ['month'], - startDateExpr: 'start', - endDateExpr: 'end', - editing: { - legacyForm: true, - } - }); - - scheduler.instance.showAppointmentPopup(tasks[0]); - - let form = scheduler.instance.getAppointmentDetailsForm(); - const descriptionEditor = form.getEditor('description'); - - descriptionEditor.option('value', 'Task 1'); - - scheduler.instance.hideAppointmentPopup(); - scheduler.instance.showAppointmentPopup(tasks[1]); - - $('.dx-dialog-buttons .dx-button').eq(0).trigger('dxclick'); - - const popup = scheduler.instance.appointmentPopup.popup; - const $buttonGroup = $(popup.$content()).find('.dx-buttongroup'); - - $buttonGroup.eq(0).dxButtonGroup('instance').option('selectedItemKeys'), ['MO', 'TH'], 'Right button group select item keys'; - - scheduler.instance.hideAppointmentPopup(); - scheduler.instance.showAppointmentPopup(tasks[0]); - - form = scheduler.instance.getAppointmentDetailsForm(); - - assert.equal(form.itemOption(APPOINTMENT_FORM_GROUP_NAMES.Recurrence).visible, false, 'Recurrence editor is hidden. Popup is correct'); - }); - test('Long term appoinment inflict index shift in other appointments (T737780)', async function(assert) { const data = [ { diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/appointment.week.based.views.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/appointment.week.based.views.tests.js index 0ac27d900990..05e0d4a991c8 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/appointment.week.based.views.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/appointment.week.based.views.tests.js @@ -248,29 +248,6 @@ module('Integration: Appointment Day, Week views', { } }); - test('Appointment should be copied before sending to the details view', async function(assert) { - const task = { - text: 'Task 1', - startDate: 1429776000000, - endDate: 1429794000000 - }; - - const scheduler = await createInstance({ - dataSource: new DataSource({ - store: [task] - }), - currentDate: new Date(2015, 3, 23), - editing: { legacyForm: true } - }); - - scheduler.instance.showAppointmentPopup(task); - - const detailsForm = scheduler.instance.getAppointmentDetailsForm(); - const formData = detailsForm.option('formData'); - - assert.notEqual(formData, task, 'Appointment data is copied'); - }); - test('Non-grid-aligned appointments should be resized correctly', async function(assert) { const scheduler = await createInstance({ currentDate: new Date(2015, 1, 9), @@ -809,40 +786,6 @@ module('Integration: Appointment Day, Week views', { assert.equal($appointmentRecurringIcon.css('display'), 'none', 'Appointment recurring icon isn\'t visible'); }); - test('Appointment startDate and endDate should have correct format in the details view after allDay appoitment opening (T505119)', async function(assert) { - const tasks = [{ - text: 'AllDay task', - start: new Date(2017, 2, 13), - end: new Date(2017, 2, 13, 0, 30), - AllDay: true - }, { - text: 'Short task', - start: new Date(2017, 2, 13), - end: new Date(2017, 2, 13, 0, 30) - }]; - - const scheduler = await createInstance({ - dataSource: tasks, - currentDate: new Date(2017, 2, 13), - currentView: 'week', - views: ['week'], - startDateExpr: 'start', - endDateExpr: 'end', - allDayExpr: 'AllDay', - editing: { legacyForm: true } - }); - scheduler.instance.showAppointmentPopup(tasks[0]); - scheduler.instance.hideAppointmentPopup(); - scheduler.instance.showAppointmentPopup(tasks[1]); - - const detailsForm = scheduler.instance.getAppointmentDetailsForm(); - const startDateEditor = detailsForm.getEditor('start'); - const endDateEditor = detailsForm.getEditor('end'); - - assert.equal(startDateEditor.option('type'), 'datetime', 'start date is correct'); - assert.equal(endDateEditor.option('type'), 'datetime', 'end date is correct'); - }); - test('Scheduler should not throw error at deferred appointment loading (T518327)', async function(assert) { const data = [{ text: 'Task 1', startDate: new Date(2017, 4, 22, 16), endDate: new Date(2017, 4, 24, 1) }]; @@ -892,66 +835,6 @@ module('Integration: Appointment Day, Week views', { } }); - test('FormData should be reset on saveChanges, dateSerializationFormat is set in initial appointment data (T569673)', async function(assert) { - const task = { text: 'Task', StartDate: '2016-05-25T09:40:00', - EndDate: '2016-05-25T10:40:00' }; - - const scheduler = await createInstance({ - dataSource: [task], - currentDate: new Date(2016, 4, 25), - currentView: 'week', - views: ['week'], - startDateExpr: 'StartDate', - endDateExpr: 'EndDate', - editing: { legacyForm: true }, - onAppointmentFormOpening: function(data) { - const form = data.form; - let startDate = data.appointmentData.StartDate; - const endDate = data.appointmentData.EndDate; - - form.option('items', [ - { - dataField: 'StartDate', - editorType: 'dxDateBox', - editorOptions: { - value: startDate, - type: 'datetime', - onValueChanged: function(args) { - startDate = args.value; - form.getEditor('EndDate') - .option('value', new Date(1464160900000)); - } - } - }, { - name: 'EndDate', - dataField: 'EndDate', - editorType: 'dxDateBox', - editorOptions: { - value: endDate, - type: 'datetime', - readOnly: true - } - } - ]); - }, - height: 800 - }); - - scheduler.instance.showAppointmentPopup(task, true); - - const detailsForm = scheduler.instance.getAppointmentDetailsForm(); - const startDateEditor = detailsForm.getEditor('StartDate'); - - startDateEditor.option('value', '2016-05-25T10:40:00'); - - $('.dx-scheduler-legacy-appointment-popup .dx-popup-done').trigger('dxclick').trigger('dxclick'); - - const $appointments = scheduler.instance.$element().find('.' + APPOINTMENT_CLASS); - - const endDateFormat = dateSerialization.getDateSerializationFormat(dataUtils.data($appointments[1], 'dxItemData').EndDate); - assert.deepEqual(endDateFormat, 'yyyy-MM-ddTHH:mm:ss', 'Appointment EndDate format is OK'); - }); - test('A long appointment should not change start date if resized from the bottom', async function(assert) { const expectedStartDate = new Date(2018, 4, 21, 0, 30); const scheduler = await createInstance({ diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/common.events.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/common.events.tests.js index 1cc60e62406e..fee559f2b6cf 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/common.events.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/common.events.tests.js @@ -615,29 +615,6 @@ QUnit.module('Events', { assert.deepEqual(appointments.option('onAppointmentDblClick')(), scheduler.instance.option('onAppointmentDblClick')(), 'scheduler has correct onAppointmentDblClick after option change'); }); - QUnit.test('onAppointmentFormOpening event should be fired while details form is opening', async function(assert) { - const stub = sinon.stub(); - const data = { - text: 'One', - location: 'NY' - }; - const scheduler = await createWrapper({ - currentView: 'month', - onAppointmentFormOpening: stub, - editing: { - legacyForm: true - }, - }); - - scheduler.instance.showAppointmentPopup(data); - - const args = stub.getCall(0).args[0]; - - assert.ok(stub.calledOnce, 'Event was fired'); - assert.equal(args.appointmentData, data, 'Appointment data is OK'); - assert.equal(args.form, scheduler.instance.getAppointmentDetailsForm(), 'Appointment form is OK'); - }); - QUnit.test('Option changed', async function(assert) { const scheduler = await createWrapper(); diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/common.options.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/common.options.tests.js index b472ed64da73..575f8438f9cd 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/common.options.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/common.options.tests.js @@ -585,7 +585,6 @@ QUnit.module('Options', () => { allowResizing: true, allowDragging: true, allowTimeZoneEditing: false, - legacyForm: false, form: { iconsShowMode: 'main' }, diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/editing.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/editing.tests.js index 01d374a2d30e..01fd7366d7ce 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/editing.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/editing.tests.js @@ -77,132 +77,6 @@ QUnit.test('Appointment should not be draggable & resizable', async function(ass assert.ok(appointments.option('allowResize'), 'Resize is allowed'); }); -QUnit.test('ReadOnly option should be passed to the details appointment view', async function(assert) { - await this.createInstance({ - editing: { - allowUpdating: false, - legacyForm: true - } - }); - - this.instance.showAppointmentPopup({ - text: 'a', - startDate: new Date(2015, 5, 15, 10), - endDate: new Date(2015, 5, 15, 11) - }); - - let detailsAppointmentView = this.instance.getAppointmentDetailsForm(); - - assert.ok(detailsAppointmentView.option('readOnly'), 'ReadOnly option is correct'); - - this.instance.option('editing.allowUpdating', true); - this.instance.showAppointmentPopup({ - text: 'a', - startDate: new Date(2015, 5, 15, 10), - endDate: new Date(2015, 5, 15, 11) - }); - detailsAppointmentView = this.instance.getAppointmentDetailsForm(); - - assert.notOk(detailsAppointmentView.option('readOnly'), 'ReadOnly option is correct'); -}); - -QUnit.test('Details appointment view should be readOnly if editing.allowUpdating=false', async function(assert) { - await this.createInstance({ - editing: { - allowUpdating: false, - legacyForm: true - } - }); - - this.instance.showAppointmentPopup({ - text: 'a', - startDate: new Date(2015, 5, 15, 10), - endDate: new Date(2015, 5, 15, 11) - }); - - let detailsAppointmentView = this.instance.getAppointmentDetailsForm(); - - assert.ok(detailsAppointmentView.option('readOnly'), 'ReadOnly option is correct'); - - this.instance.option('editing', { - allowUpdating: true - }); - this.instance.showAppointmentPopup({ - text: 'a', - startDate: new Date(2015, 5, 15, 10), - endDate: new Date(2015, 5, 15, 11) - }); - detailsAppointmentView = this.instance.getAppointmentDetailsForm(); - - assert.notOk(detailsAppointmentView.option('readOnly'), 'ReadOnly option is correct'); -}); - -QUnit.test('Details appointment view shouldn\'t be readOnly when adding new appointment if editing.allowUpdating=false', async function(assert) { - await this.createInstance({ - currentDate: new Date(2015, 5, 14), - editing: { - allowUpdating: false, - allowAdding: true, - legacyForm: true - } - }); - - this.instance.showAppointmentPopup({ - text: 'a', - startDate: new Date(2015, 12, 15, 10), - endDate: new Date(2015, 12, 15, 11) - }, true); - - const detailsAppointmentView = this.instance.getAppointmentDetailsForm(); - - assert.notOk(detailsAppointmentView.option('readOnly'), 'ReadOnly option is correct'); -}); - -QUnit.test('Details appointment form should be readOnly after adding new appointment if editing.allowUpdating=false', async function(assert) { - await this.createInstance({ - currentDate: new Date(2015, 5, 14), - editing: { - allowUpdating: false, - legacyForm: true - }, - dataSource: [] - }); - - const a = { text: 'a', startDate: new Date(2015, 5, 14, 0), endDate: new Date(2015, 5, 14, 0, 30) }; - - this.instance.showAppointmentPopup(a, true); - this.instance.hideAppointmentPopup(); - - this.instance.showAppointmentPopup(a); - - const detailsAppointmentView = this.instance.getAppointmentDetailsForm(); - - assert.ok(detailsAppointmentView.option('readOnly'), 'ReadOnly option is correct'); - this.instance.hideAppointmentPopup(); -}); - -QUnit.test('Details form of new appointment shouldn\'t be readOnly after try to change existing appointment if editing.allowUpdating=false', async function(assert) { - const first = { text: 'first', startDate: new Date(2015, 5, 14, 0), endDate: new Date(2015, 5, 14, 0, 30) }; - const second = { text: 'second', startDate: new Date(2015, 5, 14, 1), endDate: new Date(2015, 5, 14, 1, 30) }; - - await this.createInstance({ - currentDate: new Date(2015, 5, 14), - editing: { - allowUpdating: false, - legacyForm: true - }, - dataSource: [first] - }); - this.instance.showAppointmentPopup(first); - this.instance.hideAppointmentPopup(); - this.instance.showAppointmentPopup(second, true); - - const detailsAppointmentView = this.instance.getAppointmentDetailsForm(); - - assert.notOk(detailsAppointmentView.option('readOnly'), 'ReadOnly option is correct'); - this.instance.hideAppointmentPopup(); -}); - QUnit.module('Editing option: complex object', { beforeEach: function() { this.createInstance = function(options) { diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/integration.adaptivity.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/integration.adaptivity.tests.js index c565791c2555..8437ac20fb84 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/integration.adaptivity.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/integration.adaptivity.tests.js @@ -146,113 +146,6 @@ module('Mobile tooltip', moduleConfig, () => { }); }); -if(isDesktopEnvironment()) { - module('Appointment form on desktop', { - beforeEach() { - fx.off = true; - }, - - afterEach() { - fx.off = false; - resetWindowWidth(); - } - }, () => { - test('Items has layout with one column when the form\'s width < 600px', async function(assert) { - const scheduler = await createInstance({ editing: { legacyForm: true } }); - setWindowWidth(500); - scheduler.appointments.compact.click(); - scheduler.tooltip.clickOnItem(); - - assert.ok(scheduler.appointmentForm.hasFormSingleColumn(), 'Appointment form has single column'); - }); - - test('Items with recurrence editor has layout with one column when the form\'s width < 600px', async function(assert) { - const scheduler = await createInstance({ editing: { legacyForm: true } }); - setWindowWidth(500); - scheduler.option('dataSource', [{ - startDate: new Date(2015, 1, 1), - endDate: new Date(2015, 1, 2), - recurrenceRule: 'FREQ=WEEKLY' - }]); - scheduler.appointments.compact.click(); - scheduler.tooltip.clickOnItem(); - $('.dx-dialog-buttons .dx-button').eq(0).trigger('dxclick'); - - assert.ok(scheduler.appointmentForm.hasFormSingleColumn(), 'Appointment form has single column'); - }); - - test('Items has layout with non-one column when the form\'s width > 600px', async function(assert) { - const scheduler = await createInstance({ editing: { legacyForm: true } }); - setWindowWidth(700); - scheduler.appointments.compact.click(); - scheduler.tooltip.clickOnItem(); - - assert.notOk(scheduler.appointmentForm.hasFormSingleColumn(), 'Appointment form has not single column'); - }); - - test('Items with recurrence editor has layout with non-one column when the form\'s width > 600px', async function(assert) { - const scheduler = await createInstance({ editing: { legacyForm: true } }); - setWindowWidth(700); - scheduler.option('dataSource', [{ - startDate: new Date(2015, 1, 1), - endDate: new Date(2015, 1, 2), - recurrenceRule: 'FREQ=WEEKLY' - }]); - scheduler.appointments.compact.click(); - scheduler.tooltip.clickOnItem(); - $('.dx-dialog-buttons .dx-button').eq(0).trigger('dxclick'); - - assert.notOk(scheduler.appointmentForm.hasFormSingleColumn(), 'Appointment form has not single column'); - }); - - test('Items has layout with one column when the form\'s width < 600px on window resizing', async function(assert) { - const scheduler = await createInstance({ editing: { legacyForm: true } }); - setWindowWidth(700); - scheduler.appointments.compact.click(); - scheduler.tooltip.clickOnItem(); - - setWindowWidth(500); - resizeCallbacks.fire(); - - assert.ok(scheduler.appointmentForm.hasFormSingleColumn(), 'Appointment form has single column'); - }); - - test('Items has layout with non-one column when the form\'s width > 600px on window resizing', async function(assert) { - const scheduler = await createInstance({ editing: { legacyForm: true } }); - setWindowWidth(500); - scheduler.appointments.compact.click(); - scheduler.tooltip.clickOnItem(); - - setWindowWidth(700); - resizeCallbacks.fire(); - - assert.notOk(scheduler.appointmentForm.hasFormSingleColumn(), 'Appointment form has not single column'); - }); - }); -} - -if(!isDesktopEnvironment()) { - module('Appointment form on mobile', { - beforeEach() { - fx.off = true; - setWindowWidth(800); - }, - - afterEach() { - fx.off = false; - resetWindowWidth(); - } - }, () => { - test('Items has layout with one column', async function(assert) { - const scheduler = await createInstance({ editing: { legacyForm: true } }); - scheduler.appointments.compact.click(); - scheduler.tooltip.clickOnItem(); - - assert.ok(scheduler.appointmentForm.hasFormSingleColumn(), 'Appointment form has single column'); - }); - }); -} - if(isDesktopEnvironment()) { module('Appointment popup size, desktop', { beforeEach() { @@ -264,10 +157,10 @@ if(isDesktopEnvironment()) { resetWindowWidth(); } }, () => { - test('The fullscreen mode is enabled of popup when window\'s width < 1000px', async function(assert) { - setWindowWidth(900); + test('The fullscreen mode is enabled of popup when window\'s width < 485px', async function(assert) { + setWindowWidth(400); - const scheduler = await createInstance({ editing: { legacyForm: true } }); + const scheduler = await createInstance({ }); scheduler.appointments.compact.click(); scheduler.tooltip.clickOnItem(); const popup = scheduler.appointmentPopup.getPopupInstance(); @@ -276,66 +169,21 @@ if(isDesktopEnvironment()) { assert.equal(popup.option('maxWidth'), '100%', 'maxWidth'); }); - test('The fullscreen mode is disabled of popup when window\'s width > 1000px', async function(assert) { - setWindowWidth(1001); + test('The fullscreen mode is enabled of popup when the window\'s width < 485px by resizing the window', async function(assert) { + setWindowWidth(600); - const scheduler = await createInstance({ editing: { legacyForm: true } }); + const scheduler = await createInstance({ }); scheduler.appointments.compact.click(); scheduler.tooltip.clickOnItem(); const popup = scheduler.appointmentPopup.getPopupInstance(); - assert.notOk(popup.option('fullScreen'), 'The fullscreen mode is disabled'); - assert.equal(popup.option('maxWidth'), 485, 'maxWidth'); - }); - - test('The fullscreen mode is disabled of popup when window\'s width > 1000px, with recurrence editor', async function(assert) { - setWindowWidth(1001); - - const scheduler = await createInstance({ editing: { legacyForm: true } }); - scheduler.option('dataSource', [{ - startDate: new Date(2015, 1, 1), - endDate: new Date(2015, 1, 2), - recurrenceRule: 'FREQ=WEEKLY' - }]); - await waitAsync(0); - scheduler.appointments.compact.click(); - scheduler.tooltip.clickOnItem(); - $('.dx-dialog-buttons .dx-button').eq(0).trigger('dxclick'); - const popup = scheduler.appointmentPopup.getPopupInstance(); - - assert.notOk(popup.option('fullScreen'), 'The fullscreen mode is disabled'); - assert.equal(popup.option('maxWidth'), 970, 'maxWidth'); - }); - - test('The fullscreen mode is enabled of popup when the window\'s width < 1000px by resizing the window', async function(assert) { - setWindowWidth(1001); - - const scheduler = await createInstance({ editing: { legacyForm: true } }); - scheduler.appointments.compact.click(); - scheduler.tooltip.clickOnItem(); - const popup = scheduler.appointmentPopup.getPopupInstance(); - - setWindowWidth(767); + setWindowWidth(400); resizeCallbacks.fire(); assert.ok(popup.option('fullScreen'), 'The fullscreen mode is enabled'); assert.equal(popup.option('maxWidth'), '100%', 'maxWidth'); }); - test('The fullscreen mode is disabled of popup when the window\'s width > 1000px by resizing the window', async function(assert) { - setWindowWidth(799); - - const scheduler = await createInstance({ editing: { legacyForm: true } }); - scheduler.appointments.compact.click(); - scheduler.tooltip.clickOnItem(); - const popup = scheduler.appointmentPopup.getPopupInstance(); - - setWindowWidth(1001); - resizeCallbacks.fire(); - - assert.notOk(popup.option('fullScreen'), 'The fullscreen mode is disabled'); - assert.equal(popup.option('maxWidth'), 485, 'maxWidth'); - }); }); } @@ -350,10 +198,10 @@ if(!isDesktopEnvironment()) { resetWindowWidth(); } }, () => { - test('The fullscreen mode is enabled of popup when window\'s width < 500px', async function(assert) { - setWindowWidth(499); + test('The fullscreen mode is enabled of popup when window\'s width < 485px', async function(assert) { + setWindowWidth(400); - const scheduler = await createInstance({ editing: { legacyForm: true } }); + const scheduler = await createInstance({ }); scheduler.appointments.compact.click(); scheduler.tooltip.clickOnItem(); const popup = scheduler.appointmentPopup.getPopupInstance(); @@ -362,22 +210,22 @@ if(!isDesktopEnvironment()) { assert.equal(popup.option('maxWidth'), '100%', 'maxWidth'); }); - test('The fullscreen mode is disabled of popup when window\'s width > 500px', async function(assert) { + test('The fullscreen mode is disabled of popup when window\'s width > 485px', async function(assert) { setWindowWidth(501); - const scheduler = await createInstance({ editing: { legacyForm: true } }); + const scheduler = await createInstance({ }); scheduler.appointments.compact.click(); scheduler.tooltip.clickOnItem(); const popup = scheduler.appointmentPopup.getPopupInstance(); assert.notOk(popup.option('fullScreen'), 'The fullscreen mode is disabled'); - assert.equal(popup.option('maxWidth'), 350, 'maxWidth'); + assert.equal(popup.option('maxWidth'), 380, 'maxWidth'); }); - test('The fullscreen mode is disabled of popup when window\'s width > 500px, with recurrence editor', async function(assert) { + test('The fullscreen mode is disabled of popup when window\'s width > 485px, with recurrence editor', async function(assert) { setWindowWidth(501); - const scheduler = await createInstance({ editing: { legacyForm: true } }); + const scheduler = await createInstance({ }); scheduler.option('dataSource', [{ startDate: new Date(2015, 1, 1), endDate: new Date(2015, 1, 2), @@ -389,7 +237,7 @@ if(!isDesktopEnvironment()) { const popup = scheduler.appointmentPopup.getPopupInstance(); assert.notOk(popup.option('fullScreen'), 'The fullscreen mode is disabled'); - assert.equal(popup.option('maxWidth'), 350, 'maxWidth'); + assert.equal(popup.option('maxWidth'), 380, 'maxWidth'); }); }); } @@ -403,13 +251,12 @@ module('Appointment popup buttons', moduleConfig, () => { test('Buttons location of the top toolbar for the iOs device', async function(assert) { this.realDeviceMock = sinon.stub(devices, 'current').returns({ platform: 'ios' }); try { - const scheduler = await createInstance({ editing: { legacyForm: true } }); + const scheduler = await createInstance({ }); scheduler.appointments.compact.click(); scheduler.tooltip.clickOnItem(); const popup = scheduler.appointmentPopup; - assert.ok(popup.hasToolbarButtonsInSection(TOOLBAR_TOP_LOCATION, SECTION_BEFORE, [CANCEL_BUTTON]), 'the \'Cancel\' button is located inside the \'before\' section'); - assert.ok(popup.hasToolbarButtonsInSection(TOOLBAR_TOP_LOCATION, SECTION_AFTER, [DONE_BUTTON]), 'the \'Done\' button is located inside the \'after\' section'); + assert.ok(popup.hasToolbarButtonsInSection(TOOLBAR_TOP_LOCATION, SECTION_AFTER, [CANCEL_BUTTON, DONE_BUTTON]), 'the \'Cancel\' and \'Done\' buttons are located inside the \'after\' section'); } finally { this.realDeviceMock.restore(); } @@ -418,12 +265,12 @@ module('Appointment popup buttons', moduleConfig, () => { test('Buttons location of the top toolbar for the desktop', async function(assert) { this.realDeviceMock = sinon.stub(devices, 'current').returns({ platform: 'generic' }); try { - const scheduler = await createInstance({ editing: { legacyForm: true } }); + const scheduler = await createInstance({ }); scheduler.appointments.compact.click(); scheduler.tooltip.clickOnItem(); const popup = scheduler.appointmentPopup; - assert.ok(popup.hasToolbarButtonsInSection(TOOLBAR_BOTTOM_LOCATION, SECTION_AFTER, [DONE_BUTTON, CANCEL_BUTTON]), 'the \'Cancel\' and \'Done\' buttons are located in the \'after\' section'); + assert.ok(popup.hasToolbarButtonsInSection(TOOLBAR_TOP_LOCATION, SECTION_AFTER, [DONE_BUTTON, CANCEL_BUTTON]), 'the \'Cancel\' and \'Done\' buttons are located in the \'after\' section'); } finally { this.realDeviceMock.restore(); } @@ -432,12 +279,12 @@ module('Appointment popup buttons', moduleConfig, () => { test('Buttons location of the top toolbar for the android device', async function(assert) { this.realDeviceMock = sinon.stub(devices, 'current').returns({ platform: 'android' }); try { - const scheduler = await createInstance({ editing: { legacyForm: true } }); + const scheduler = await createInstance({ }); scheduler.appointments.compact.click(); scheduler.tooltip.clickOnItem(); const popup = scheduler.appointmentPopup; - assert.ok(popup.hasToolbarButtonsInSection(TOOLBAR_BOTTOM_LOCATION, SECTION_AFTER, [CANCEL_BUTTON, DONE_BUTTON]), 'the \'Cancel\' and \'Done\' buttons are located in the \'after\' section'); + assert.ok(popup.hasToolbarButtonsInSection(TOOLBAR_TOP_LOCATION, SECTION_AFTER, [CANCEL_BUTTON, DONE_BUTTON]), 'the \'Cancel\' and \'Done\' buttons are located in the \'after\' section'); } finally { this.realDeviceMock.restore(); } diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/integration.agenda.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/integration.agenda.tests.js index bf9e6e10f6f9..002e62210148 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/integration.agenda.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/integration.agenda.tests.js @@ -1212,31 +1212,6 @@ module('Integration: Agenda', moduleConfig, () => { }); }); - test('Long appointment parts popup should have original data', async function(assert) { - const instance = await createInstance({ - views: ['agenda'], - currentView: 'agenda', - currentDate: new Date(2016, 1, 24), - startDayHour: 8, - endDayHour: 20, - startDateExpr: 'Start', - dataSource: [ - { Start: new Date(2016, 1, 24, 1), endDate: new Date(2016, 1, 27, 1, 30), text: 'a' } - ], - editing: { legacyForm: true } - }); - - const $appointment = $(instance.$element()).find('.dx-scheduler-appointment').eq(1); - $appointment.trigger(dblclickEvent.name); - - const detailsForm = instance.getAppointmentDetailsForm(); - const formData = detailsForm.option('formData'); - - assert.deepEqual(formData.Start, new Date(2016, 1, 24, 1), 'start is correct'); - assert.deepEqual(formData.endDate, new Date(2016, 1, 27, 1, 30), 'end is correct'); - assert.equal(formData.text, 'a', 'text is correct'); - }); - test('Long appointment should be rendered correctly after changing view', async function(assert) { const instance = await createInstance({ views: ['agenda', 'month'], diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/integration.appointmentCollector.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/integration.appointmentCollector.tests.js index 3c580c6865dd..56b77f5d001a 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/integration.appointmentCollector.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/integration.appointmentCollector.tests.js @@ -60,11 +60,10 @@ module('Integration: collector', baseConfig, () => { currentDate: new Date(2017, 4, 25), height: 600, onAppointmentFormOpening: e => { - const startDate = e.form.getEditor('startDate').option('value'); + const startDate = e.form.getEditor('startDateEditor').option('value'); assert.equal(startDate.getDate(), 16, 'Recurrence appointment date should be display equal targetedAppointmentData date in form'); }, editing: { - legacyForm: true }, maxAppointmentsPerCell: 2 }); diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/integration.appointmentTooltip.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/integration.appointmentTooltip.tests.js index 77d1006c646a..1f63e201dfc0 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/integration.appointmentTooltip.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/integration.appointmentTooltip.tests.js @@ -335,8 +335,6 @@ module('Integration: Appointment tooltip', moduleConfig, () => { }, 'show has a right appointment data arg'); - assert.equal(args[1].isToolbarVisible, true, 'show has a right createNewAppointment arg'); - assert.notOk(scheduler.tooltip.isVisible(), 'tooltip was hidden'); }); diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/integration.base.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/integration.base.tests.js index a4fbeed8c982..288b42b430bb 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/integration.base.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/integration.base.tests.js @@ -257,13 +257,6 @@ QUnit.test('Scheduler should not throw an error when the details form is opened } }); -QUnit.test('The \'scrollingEnabled\' option of an appointment form should be \'true\'', async function(assert) { - await this.createInstance({ editing: { legacyForm: true } }); - this.instance.showAppointmentPopup({ startDate: new Date() }); - - assert.strictEqual(this.instance.getAppointmentDetailsForm().option('scrollingEnabled'), true, 'the scrollingEnabled option is OK'); -}); - QUnit.module('Integration: Date options with ISO8601', { beforeEach: function() { this.defaultForceIsoDateParsing = config().forceIsoDateParsing; diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/integration.recurringAppointments.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/integration.recurringAppointments.tests.js index 0ac102184caf..6e0f4d8b634e 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/integration.recurringAppointments.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/integration.recurringAppointments.tests.js @@ -660,63 +660,14 @@ supportedScrollingModes.forEach(scrollingMode => { $('.dx-dialog-buttons .dx-button').eq(1).trigger('dxclick'); }); - test('Recurrent Task editing, single mode', async function(assert) { - const data = new DataSource({ - store: [ - { - text: 'Task 1', - startDate: new Date(2015, 1, 9, 1, 0), - endDate: new Date(2015, 1, 9, 2, 0), - recurrenceRule: 'FREQ=DAILY' - } - ] - }); - - const updatedItem = { - text: 'Task 2', - startDate: new Date(2015, 1, 11, 3), - endDate: new Date(2015, 1, 11, 4), - }; - - const scheduler = await this.createInstance({ - currentDate: new Date(2015, 1, 9), - dataSource: data, - currentView: 'week', - firstDayOfWeek: 1, - editing: { legacyForm: true } - }); - - const clock = sinon.useFakeTimers(); - await scheduler.appointments.click(2, clock); - scheduler.tooltip.clickOnItem(); - $('.dx-dialog-buttons .dx-button').eq(1).trigger('dxclick'); - - const $title = $('.dx-textbox').eq(0); - const title = $title.dxTextBox('instance'); - const $startDate = $('.dx-datebox').eq(0); - const startDate = $startDate.dxDateBox('instance'); - - title.option('value', 'Task 2'); - startDate.option('value', new Date(2015, 1, 11, 3, 0)); - $('.dx-button.dx-popup-done').eq(0).trigger('dxclick'); - await clock.tickAsync(300); - clock.restore(); - - const updatedSingleItem = scheduler.instance.option('dataSource').items()[1]; - const updatedRecurringItem = scheduler.instance.option('dataSource').items()[0]; - const exceptionDate = new Date(2015, 1, 11, 1, 0, 0, 0); - - assert.deepEqual(updatedSingleItem, updatedItem, 'New data is correct'); - - assert.equal(updatedRecurringItem.recurrenceException, dateSerialization.serializeDate(exceptionDate, 'yyyyMMddTHHmmssZ'), 'Exception for recurrence appointment is correct'); - }); - test('Recurrent Task editing, single mode, should not reference copy recurrent data (T1228488)', async function(assert) { const updatedItem = { text: 'Task 2', customData: { texts: ['123', '456'] }, startDate: new Date(2015, 1, 11, 3), endDate: new Date(2015, 1, 11, 4), + allDay: false, + recurrenceRule: '', }; const scheduler = await this.createInstance({ @@ -732,7 +683,7 @@ supportedScrollingModes.forEach(scrollingMode => { onAppointmentAdding: (e) => { e.appointmentData.customData.texts.push('456'); }, - editing: { legacyForm: true }, + firstDayOfWeek: 1 }); @@ -743,11 +694,11 @@ supportedScrollingModes.forEach(scrollingMode => { const $title = $('.dx-textbox').eq(0); const title = $title.dxTextBox('instance'); - const $startDate = $('.dx-datebox').eq(0); - const startDate = $startDate.dxDateBox('instance'); + const $startTime = $('.dx-datebox').eq(1); + const startTime = $startTime.dxDateBox('instance'); title.option('value', 'Task 2'); - startDate.option('value', new Date(2015, 1, 11, 3, 0)); + startTime.option('value', new Date(2015, 1, 11, 3, 0)); $('.dx-button.dx-popup-done').eq(0).trigger('dxclick'); await clock.tickAsync(300); clock.restore(); @@ -759,78 +710,6 @@ supportedScrollingModes.forEach(scrollingMode => { assert.deepEqual(updatedRecurringItem.customData.texts, ['123'], 'Recurrence data is correct'); }); - test('Recurrent Task edition canceling, single mode', async function(assert) { - const data = new DataSource({ - store: [ - { - text: 'Task 1', - startDate: new Date(2015, 1, 9, 1, 0), - endDate: new Date(2015, 1, 9, 2, 0), - recurrenceRule: 'FREQ=DAILY' - } - ] - }); - - const scheduler = await this.createInstance({ - currentDate: new Date(2015, 1, 9), - dataSource: data, - currentView: 'week', - firstDayOfWeek: 1 - }); - - const clock = sinon.useFakeTimers(); - $(scheduler.instance.$element()).find('.dx-scheduler-appointment').eq(2).trigger('dxclick'); - await clock.tickAsync(300); - $('.dx-scheduler-appointment-tooltip-buttons .dx-button').eq(1).trigger('dxclick'); - $('.dx-dialog-buttons .dx-button').eq(1).trigger('dxclick'); - $('.dx-button.dx-popup-cancel').eq(0).trigger('dxclick'); - - $(scheduler.instance.$element()).find('.dx-scheduler-appointment').eq(2).trigger('dxclick'); - await clock.tickAsync(300); - $('.dx-scheduler-appointment-tooltip-buttons .dx-button').eq(1).trigger('dxclick'); - $('.dx-dialog-buttons .dx-button').eq(0).trigger('dxclick'); - $('.dx-button.dx-popup-done').eq(0).trigger('dxclick'); - clock.restore(); - - const items = scheduler.instance.option('dataSource').items(); - - assert.equal(items.length, 1, 'Items are correct'); - }); - - test('Recurrent Task editing, single mode - canceling', async function(assert) { - const data = new DataSource({ - store: [ - { - text: 'Task 1', - startDate: new Date(2015, 1, 9, 1, 0), - endDate: new Date(2015, 1, 9, 2, 0), - recurrenceRule: 'FREQ=DAILY' - } - ] - }); - - const scheduler = await this.createInstance({ - currentDate: new Date(2015, 1, 9), - dataSource: data, - currentView: 'week', - firstDayOfWeek: 1 - }); - - const clock = sinon.useFakeTimers(); - $(scheduler.instance.$element()).find('.dx-scheduler-appointment').eq(2).trigger('dxclick'); - await clock.tickAsync(300); - $('.dx-scheduler-appointment-tooltip-buttons .dx-button').eq(1).trigger('dxclick'); - $('.dx-dialog-buttons .dx-button').eq(1).trigger('dxclick'); - - $('.dx-button.dx-popup-cancel').eq(0).trigger('dxclick'); - await clock.tickAsync(300); - clock.restore(); - - const recurrentItem = scheduler.instance.option('dataSource').items()[0]; - - assert.equal(recurrentItem.recurrenceException, undefined, 'Exception for recurrence appointment is correct'); - }); - test('Recurrent Task editing, confirmation tooltip should be shown after double click on recurrent appointment', async function(assert) { const data = new DataSource({ store: [ @@ -859,56 +738,6 @@ supportedScrollingModes.forEach(scrollingMode => { $('.dx-dialog-buttons .dx-button').eq(1).trigger('dxclick'); }); - test('Recurrent Task editing, single mode - double click', async function(assert) { - const data = new DataSource({ - store: [ - { - text: 'Task 1', - startDate: new Date(2015, 1, 9, 1, 0), - endDate: new Date(2015, 1, 9, 2, 0), - recurrenceRule: 'FREQ=DAILY' - } - ] - }); - - const updatedItem = { - text: 'Task 2', - startDate: new Date(2015, 1, 11, 3), - endDate: new Date(2015, 1, 11, 4) - }; - - const scheduler = await this.createInstance({ - currentDate: new Date(2015, 1, 9), - dataSource: data, - currentView: 'week', - firstDayOfWeek: 1, - editing: { legacyForm: true } - }); - const clock = sinon.useFakeTimers(); - $(scheduler.instance.$element()).find('.dx-scheduler-appointment').eq(2).trigger(dblclickEvent.name); - await clock.tickAsync(300); - - $('.dx-dialog-buttons .dx-button').eq(1).trigger('dxclick'); - - const $title = $('.dx-textbox').eq(0); - const title = $title.dxTextBox('instance'); - const $startDate = $('.dx-datebox').eq(0); - const startDate = $startDate.dxDateBox('instance'); - - title.option('value', 'Task 2'); - startDate.option('value', new Date(2015, 1, 11, 3, 0)); - $('.dx-button.dx-popup-done').eq(0).trigger('dxclick'); - await clock.tickAsync(300); - clock.restore(); - - const updatedSingleItem = scheduler.instance.option('dataSource').items()[1]; - const updatedRecurringItem = scheduler.instance.option('dataSource').items()[0]; - const exceptionDate = new Date(2015, 1, 11, 1, 0, 0, 0); - - assert.deepEqual(updatedSingleItem, updatedItem, 'New data is correct'); - assert.equal(updatedRecurringItem.recurrenceException, dateSerialization.serializeDate(exceptionDate, 'yyyyMMddTHHmmssZ'), 'Exception for recurrence appointment is correct'); - }); - test('Recurrent allDay task dragging on month view, single mode', async function(assert) { const data = new DataSource({ store: [ @@ -1317,47 +1146,6 @@ supportedScrollingModes.forEach(scrollingMode => { assert.equal($appointments.length, 11, 'correct number of the appointments'); }); - test('Single changed appointment should be rendered correctly in specified timeZone', async function(assert) { - if(!isDesktopEnvironment()) { - assert.ok(true, 'This test is for desktop only'); - return; - } - - const scheduler = await this.createInstance({ - dataSource: [{ - text: 'Recurrence', - startDate: '2018-05-23T10:00:00Z', - endDate: '2018-05-23T10:30:00Z', - recurrenceRule: 'FREQ=DAILY' - }], - editing: { legacyForm: true }, - views: ['week'], - currentView: 'week', - currentDate: new Date(2018, 4, 23), - timeZone: 'Etc/UTC', - height: 2000, - width: 800 - }); - - const clock = sinon.useFakeTimers(); - $(scheduler.instance.$element()).find('.dx-scheduler-appointment').eq(0).trigger('dxclick').trigger('dxclick'); - - $('.dx-dialog-buttons .dx-button').eq(1).trigger('dxclick'); - - const $startDate = $('.dx-datebox').eq(0); - const startDate = $startDate.dxDateBox('instance'); - const expectedStartDate = new Date(2018, 4, 23, 9, 0); - - startDate.option('value', expectedStartDate); - $('.dx-button.dx-popup-done').eq(0).trigger('dxclick'); - await clock.tickAsync(300); - clock.restore(); - - const actualStartDate = $(scheduler.instance.$element()).find('.dx-scheduler-appointment').eq(3).dxSchedulerAppointment('instance').option('startDate'); - - assert.deepEqual(actualStartDate, expectedStartDate, 'appointment starts in 9AM'); - }); - test('Recurrent appointment considers firstDayOfWeek of Scheduler, WEEKLY,INTERVAL=2 (T744191)', async function(assert) { const scheduler = await this.createInstance({ dataSource: [{ @@ -1678,7 +1466,7 @@ supportedScrollingModes.forEach(scrollingMode => { endDate: apptEndDate, recurrenceRule: 'FREQ=MINUTELY;COUNT=3' }], - editing: { legacyForm: true }, + currentDate: apptStartDate, }); @@ -1688,8 +1476,8 @@ supportedScrollingModes.forEach(scrollingMode => { scheduler.appointments.dblclick(2); scheduler.appointmentForm.clickFormDialogButton(1); - const formStartDate = scheduler.appointmentForm.getEditor('startDate'); - const formEndDate = scheduler.appointmentForm.getEditor('endDate'); + const formStartDate = scheduler.appointmentForm.getEditor('startDateEditor'); + const formEndDate = scheduler.appointmentForm.getEditor('endDateEditor'); assert.deepEqual(formStartDate.option('value'), new Date(2019, 2, 30, 2, 2), 'Appointment third occurrence sets right startDate in appointmentForm'); assert.deepEqual(formEndDate.option('value'), new Date(2019, 2, 30, 3, 2), 'Appointment third occurrence sets right endDate in appointmentForm'); @@ -1706,7 +1494,7 @@ supportedScrollingModes.forEach(scrollingMode => { endDate: apptEndDate, recurrenceRule: 'FREQ=HOURLY;COUNT=3' }], - editing: { legacyForm: true }, + currentDate: apptStartDate, }); @@ -1716,8 +1504,8 @@ supportedScrollingModes.forEach(scrollingMode => { scheduler.appointments.dblclick(2); scheduler.appointmentForm.clickFormDialogButton(1); - const formStartDate = scheduler.appointmentForm.getEditor('startDate'); - const formEndDate = scheduler.appointmentForm.getEditor('endDate'); + const formStartDate = scheduler.appointmentForm.getEditor('startDateEditor'); + const formEndDate = scheduler.appointmentForm.getEditor('endDateEditor'); assert.deepEqual(formStartDate.option('value'), new Date(2019, 2, 30, 4, 0), 'Appointment third occurrence sets right startDate in appointmentForm'); assert.deepEqual(formEndDate.option('value'), new Date(2019, 2, 30, 5, 0), 'Appointment third occurrence sets right endDate in appointmentForm'); diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/integration.resources.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/integration.resources.tests.js index e4e80637fedd..1d708a84bb12 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/integration.resources.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/integration.resources.tests.js @@ -177,7 +177,7 @@ QUnit.module('Integration: Resources', moduleConfig, () => { onAppointmentFormOpeningRaised = true; }, - editing: { legacyForm: true }, + resources: resources, dataSource: dataSource, currentDate: new Date(2015, 1, 9) @@ -192,175 +192,6 @@ QUnit.module('Integration: Resources', moduleConfig, () => { assert.ok(onAppointmentFormOpeningRaised, 'onAppointmentFormOpening event should be raised'); }); - QUnit.test('Editor for resource should be passed to details view', async function(assert) { - const task1 = { - text: 'Task 1', - ownerId: 1, - startDate: new Date(2015, 1, 9, 1, 0), - endDate: new Date(2015, 1, 9, 2, 0) - }; - const task2 = { - text: 'Task 2', - roomId: 1, - startDate: new Date(2015, 1, 9, 1, 0), - endDate: new Date(2015, 1, 9, 2, 0) - }; - const roomResource = [ - { - text: '#1', - id: 1, - color: '#606060' - }, { - text: '#2', - id: 2, - color: '#606066' - } - ]; - const resources = [ - { - field: 'ownerId', - allowMultiple: true, - dataSource: [{ - text: 'Jack', - id: 1, - color: '#606060' - }, { - text: 'Mike', - id: 2, - color: '#ff0000' - }] - }, { - field: 'roomId', - allowMultiple: false, - dataSource: new DataSource(roomResource) - }]; - - const scheduler = await createWrapper({ - resources: resources, - dataSource: new DataSource({ - store: [task1, task2] - }), - currentDate: new Date(2015, 1, 9), - editing: { legacyForm: true } - }); - - scheduler.instance.showAppointmentPopup(task1); - - let taskDetailsView = scheduler.instance.getAppointmentDetailsForm(); - - const ownerEditor = taskDetailsView.option('items')[0].items[6]; - await ownerEditor.editorOptions.dataSource.load(); - - assert.ok(taskDetailsView.getEditor('ownerId'), 'Editor is exist'); - assert.equal(ownerEditor.editorType, 'dxTagBox', 'Editor is dxTagBox'); - assert.deepEqual(ownerEditor.editorOptions.dataSource.items(), resources[0].dataSource, 'Data source is OK'); - assert.deepEqual(taskDetailsView.option('formData').ownerId, [1], 'Value is OK'); - - scheduler.instance.hideAppointmentPopup(); - scheduler.instance.showAppointmentPopup(task2); - taskDetailsView = scheduler.instance.getAppointmentDetailsForm(); - - const roomEditor = taskDetailsView.option('items')[0].items[7]; - - roomEditor.editorOptions.dataSource.load(); - - assert.ok(taskDetailsView.getEditor('roomId'), 'Editor is exist'); - assert.equal(roomEditor.editorType, 'dxSelectBox', 'Editor is dxSelectBox'); - - assert.strictEqual(taskDetailsView.option('formData').roomId, 1, 'Value is OK'); - assert.deepEqual(roomEditor.editorOptions.dataSource.items(), roomResource, 'Data source is OK'); - }); - - QUnit.test('Editor for resource should be passed to details view for scheduler with groups', async function(assert) { - const task = { - text: 'Task 1', - ownerId: 1, - startDate: new Date(2015, 1, 9, 1, 0), - endDate: new Date(2015, 1, 9, 2, 0) - }; - const resources = [{ - field: 'ownerId', - allowMultiple: true, - valueExpr: 'uid', - displayExpr: 'name', - dataSource: [ - { uid: 1, name: 'Jack', color: '#606060' }, - { uid: 2, name: 'Mike', color: '#ff0000' }, - ] - }]; - - const scheduler = await createWrapper({ - resources: resources, - groups: ['ownerId'], - dataSource: new DataSource({ - store: [task] - }), - currentDate: new Date(2015, 1, 9), - editing: { legacyForm: true } - }); - - scheduler.instance.showAppointmentPopup(task); - - const taskDetailsView = scheduler.instance.getAppointmentDetailsForm(); - const ownerEditor = taskDetailsView.option('items')[0].items[6]; - - assert.equal(ownerEditor.editorType, 'dxTagBox', 'Editor is dxTagBox'); - assert.deepEqual(ownerEditor.editorOptions.dataSource.items(), resources[0].dataSource, 'Data source is OK'); - assert.equal(ownerEditor.editorOptions.valueExpr, resources[0].valueExpr, 'valueExpr is OK'); - assert.equal(ownerEditor.editorOptions.displayExpr, resources[0].displayExpr, 'displayExpr is OK'); - }); - - QUnit.test('Editor for resource with right value should be passed to details view when fieldExpr is used', async function(assert) { - const appointment = { - 'Price': 10, - 'startDate': new Date(2015, 4, 24, 9, 10, 0, 0), - 'endDate': new Date(2015, 4, 24, 11, 1, 0, 0), - 'Movie': { - 'ID': 3 - }, - 'TheatreId': 1 - }; - - const resources = [{ - fieldExpr: 'Movie.ID', - useColorAsDefault: true, - allowMultiple: false, - dataSource: [{ - 'ID': 1, - 'Color': 'blue' - }, { - 'ID': 3, - 'Color': 'red' - }], - valueExpr: 'ID', - colorExpr: 'Color' - }, { - fieldExpr: 'TheatreId', - dataSource: [{ - id: 1 - }, { - id: 2 - }] - }]; - - const scheduler = await createWrapper({ - resources: resources, - dataSource: [appointment], - currentDate: new Date(2015, 4, 24), - editing: { legacyForm: true } - }); - - scheduler.instance.showAppointmentPopup(appointment); - - const taskDetailsView = scheduler.instance.getAppointmentDetailsForm(); - const movieEditor = taskDetailsView.option('items')[0].items[6]; - - movieEditor.editorOptions.dataSource.load(); - - assert.deepEqual(movieEditor.editorOptions.dataSource.items(), resources[0].dataSource, 'Data source is OK'); - assert.strictEqual(taskDetailsView.option('formData').Movie.ID, 3, 'Value is OK'); - }); - QUnit.test('Appointments should be repainted if \'groups\' option is changed', async function(assert) { const scheduler = await createWrapper({ dataSource: new DataSource({ @@ -475,49 +306,6 @@ QUnit.module('Integration: Resources', moduleConfig, () => { assert.equal(getHexColor($appointments.eq(1)), '#0000ff', 'Color is OK'); }); - QUnit.test('Resources should not be reloaded when details popup is opening', async function(assert) { - const loadStub = sinon.stub().returns([ - { text: 'o1', id: 1 }, - { text: 'o2', id: 2 } - ]); - const byKeyStub = sinon.stub(); - const data = [{ - text: 'a', - startDate: new Date(2015, 4, 26, 5), - endDate: new Date(2015, 4, 26, 5, 30), - ownerId: 1 - }, { - text: 'b', - startDate: new Date(2015, 4, 26, 5), - endDate: new Date(2015, 4, 26, 5, 30), - ownerId: 2 - }]; - const scheduler = await createWrapper({ - dataSource: new DataSource({ - store: data - }), - currentDate: new Date(2015, 4, 26), - groups: ['ownerId'], - resources: [{ - fieldExpr: 'ownerId', - allowMultiple: true, - dataSource: new CustomStore({ - load: loadStub, - byKey: byKeyStub - }) - }], - editing: { legacyForm: true } - }); - - assert.equal(loadStub.callCount, 1, 'Resources are loaded only once'); - - scheduler.instance.showAppointmentPopup(data[0]); - - // TODO: replace with 2 after edit form refactor - assert.equal(loadStub.callCount, 3, 'Store requested in select box'); - assert.equal(byKeyStub.callCount, 0, 'Resources are loaded only once'); - }); - [true, false].forEach((renovateRender) => { QUnit.test(`Resources should be set correctly is the resources[].dataSource option is changed(T396746) when renovateRender is ${renovateRender}`, async function(assert) { const resourceData = [{ id: 1, text: 'John', color: 'red' }]; diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/legacyAppointmentPopup.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/legacyAppointmentPopup.tests.js deleted file mode 100644 index fd570f89c2d2..000000000000 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/legacyAppointmentPopup.tests.js +++ /dev/null @@ -1,1995 +0,0 @@ -import 'fluent_blue_light.css!'; - -import { initTestMarkup, createWrapper, isDesktopEnvironment } from '../../helpers/scheduler/helpers.js'; -import { waitAsync } from '../../helpers/scheduler/waitForAsync.js'; - -import $ from 'jquery'; -import devices from '__internal/core/m_devices'; -import SelectBox from 'ui/select_box'; -import fx from 'common/core/animation/fx'; -import { DataSource } from 'common/data/data_source/data_source'; -import resizeCallbacks from 'core/utils/resize_callbacks'; -import messageLocalization from 'common/core/localization/message'; -import { APPOINTMENT_FORM_GROUP_NAMES } from '__internal/scheduler/appointment_popup/m_legacy_form'; -import { dateToMilliseconds as toMs } from 'core/utils/date'; -import '__internal/scheduler/m_scheduler'; -import 'ui/switch'; -import viewPort from 'core/utils/view_port'; -import browser from 'core/utils/browser'; -import timezoneUtils from '__internal/scheduler/m_utils_time_zone'; - - -const { module, test, testStart } = QUnit; - -const APPOINTMENT_POPUP_WIDTH = 485; -const APPOINTMENT_POPUP_WIDTH_WITH_RECURRENCE = 970; -const checkFormWithRecurrenceEditor = (assert, instance, visibility) => { - const width = visibility === true ? APPOINTMENT_POPUP_WIDTH_WITH_RECURRENCE : APPOINTMENT_POPUP_WIDTH; - const colSpan = visibility === true ? 1 : 2; - const form = instance.getAppointmentDetailsForm(); - - assert.equal(form.itemOption(APPOINTMENT_FORM_GROUP_NAMES.Recurrence).visible, - visibility, `Recurrence Editor is ${visibility === true ? 'visible' : 'not visible'}`); - - assert.equal(form.itemOption(APPOINTMENT_FORM_GROUP_NAMES.Main).colSpan, colSpan, 'colSpan of main group is correct'); - assert.equal(form.itemOption(APPOINTMENT_FORM_GROUP_NAMES.Recurrence).colSpan, colSpan, 'colSpan of recurrence group is correct'); - - assert.equal(instance.appointmentPopup.popup.option('maxWidth'), width, 'maxWidth of popup is correct'); -}; - -const createInstance = (options) => { - const defaultOption = { - dataSource: [], - maxAppointmentsPerCell: 2, - editing: { - legacyForm: true, - } - }; - - return createWrapper($.extend(true, defaultOption, options)); -}; - -const moduleOptions = { - beforeEach: function() { - fx.off = true; - this.tasks = [ - { - text: 'Task 1', - startDate: new Date(2015, 1, 9, 1, 0), - endDate: new Date(2015, 1, 9, 2, 0) - }, - { - text: 'Task 2', - startDate: new Date(2015, 1, 9, 11, 0), - endDate: new Date(2015, 1, 9, 12, 0) - } - ]; - }, - afterEach: function() { - fx.off = false; - } -}; - -const defaultData = [ - { - text: 'recurrent-app', - startDate: new Date(2017, 4, 1, 9, 30), - endDate: new Date(2017, 4, 1, 11), - recurrenceRule: 'FREQ=DAILY;COUNT=5' - }, { - text: 'common-app', - startDate: new Date(2017, 4, 9, 9, 30), - endDate: new Date(2017, 4, 9, 11), - } -]; - -const createScheduler = (options = {}) => { - const defaultOption = { - dataSource: defaultData, - views: ['month'], - currentView: 'month', - currentDate: new Date(2017, 4, 25), - firstDayOfWeek: 1, - startDayHour: 9, - height: 600, - width: 600, - editing: { - legacyForm: true, - } - }; - - return createWrapper($.extend(defaultOption, options)); -}; - -const setWindowWidth = width => { - Object.defineProperty(document.documentElement, 'clientWidth', { - get: () => width, - configurable: true - }); -}; - -const resetWindowWidth = () => delete document.documentElement.clientWidth; - -testStart(() => { - initTestMarkup(); - viewPort.value($('.shadow-container').get(0)); -}); - -const moduleConfig = { - beforeEach() { - fx.off = true; - }, - - afterEach() { - fx.off = false; - } -}; - -QUnit.module('Appointment popup form', moduleConfig, () => { - test('Original appointment\'s fields shouldn\'t fill if used fieldExpr', async function(assert) { - const data = []; - const textExpValue = 'Subject'; - - const scheduler = await createScheduler({ - dataSource: data, - views: ['week'], - currentView: 'week', - currentDate: new Date(2021, 4, 27), - textExpr: textExpValue, - onAppointmentAdded: ({ appointmentData }) => { - assert.strictEqual(appointmentData[textExpValue], 'qwerty', 'Mapped text property should be fill on onAppointmentAdded event'); - assert.strictEqual(appointmentData.text, undefined, 'Original text property should be undefined on onAppointmentAdded event'); - }, - height: 600 - }); - scheduler.instance.showAppointmentPopup(); - scheduler.appointmentForm.setSubject('qwerty', textExpValue); - scheduler.appointmentPopup.clickDoneButton(); - - assert.strictEqual(data[0].Subject, 'qwerty', 'Mapped text property should be fill'); - assert.strictEqual(data[0].text, undefined, 'Original text property should be undefined'); - }); - - QUnit.test('Recurrence form should work properly if recurrenceRule property mapped recurrenceRuleExpr', async function(assert) { - const scheduler = await createScheduler({ - dataSource: [{ - text: 'Watercolor Landscape', - startDate: new Date(2017, 4, 1, 9, 30), - endDate: new Date(2017, 4, 1, 11), - customRecurrenceRule: 'FREQ=WEEKLY;BYDAY=TU,FR;COUNT=10' - }], - views: ['month'], - currentView: 'month', - currentDate: new Date(2017, 4, 25), - recurrenceRuleExpr: 'customRecurrenceRule', - height: 600 - }); - - scheduler.appointments.dblclick(0); - scheduler.appointmentPopup.dialog.clickEditSeries(); - - const form = scheduler.instance.appointmentPopup.form.form; - - assert.ok(form.getEditor('repeat').option('value'), 'repeat checkbox should be checked'); - assert.ok(form.option('items')[1].visible, 'recurrence form should be visible'); - - scheduler.instance.appointmentPopup.popup.hide(); - scheduler.instance.showAppointmentPopup(); - - assert.notOk(form.getEditor('repeat').option('value'), 'repeat checkbox should be unchecked if empty form'); - assert.notOk(form.option('items')[1].visible, 'recurrence form should be invisible if empty form'); - }); - - QUnit.test('showAppointmentPopup method should be work properly with no argument', async function(assert) { - const cases = [ - () => { - const appointmentText = 'app'; - - const textEditor = scheduler.appointmentForm.getEditor('text'); - const startDateEditor = scheduler.appointmentForm.getEditor('startDate'); - const endDateEditor = scheduler.appointmentForm.getEditor('endDate'); - - textEditor.option('value', appointmentText); - startDateEditor.option('value', new Date(2017, 4, 22, 9, 30)); - endDateEditor.option('value', new Date(2017, 4, 22, 9, 45)); - - scheduler.appointmentPopup.clickDoneButton(); - - assert.equal(scheduler.appointments.find(appointmentText).length, 1, 'new appointment should be created with base options'); - }, - () => { - const appointmentText = 'app'; - - const textEditor = scheduler.appointmentForm.getEditor('text'); - const startDateEditor = scheduler.appointmentForm.getEditor('startDate'); - const endDateEditor = scheduler.appointmentForm.getEditor('endDate'); - - - textEditor.option('value', appointmentText); - startDateEditor.option('value', new Date(2017, 4, 22, 9, 30)); - endDateEditor.option('value', new Date(2017, 4, 22, 9, 45)); - - scheduler.appointmentPopup.clickCancelButton(); - - assert.equal(scheduler.appointments.getAppointmentCount(), 0, 'new appointment shouldn\'t created'); - }, - () => { - const appointmentText = 'all day app'; - - const textEditor = scheduler.appointmentForm.getEditor('text'); - const startDateEditor = scheduler.appointmentForm.getEditor('startDate'); - const endDateEditor = scheduler.appointmentForm.getEditor('endDate'); - const visibilityChangedEditor = scheduler.appointmentForm.getEditor('visibilityChanged'); - - textEditor.option('value', appointmentText); - startDateEditor.option('value', new Date(2017, 4, 22, 10, 30)); - endDateEditor.option('value', new Date(2017, 4, 22, 10, 45)); - visibilityChangedEditor.option('value', true); - - scheduler.appointmentPopup.clickDoneButton(); - - assert.equal(scheduler.appointments.find(appointmentText).length, 21, 'recurrence appointments should be created'); - } - ]; - - const scheduler = await createScheduler(); - - scheduler.option('dataSource', []); - await waitAsync(10); - scheduler.instance.showAppointmentPopup(); - cases[0](); - - scheduler.option('dataSource', []); - await waitAsync(10); - scheduler.instance.showAppointmentPopup(); - cases[1](); - - scheduler.option('dataSource', []); - await waitAsync(10); - scheduler.instance.showAppointmentPopup(); - cases[2](); - }); - - QUnit.test('Appointment popup form should have two named groups', async function(assert) { - const scheduler = await createScheduler({ dataSource: [] }); - const data = { - text: 'appointment', - startDate: new Date(2017, 4, 1, 9, 30), - endDate: new Date(2017, 4, 1, 11), - }; - - scheduler.instance.showAppointmentPopup(data); - const form = scheduler.instance.getAppointmentDetailsForm(); - - assert.equal(form.option('items')[0].name, APPOINTMENT_FORM_GROUP_NAMES.Main, 'first group name is correct'); - assert.equal(form.option('items')[1].name, APPOINTMENT_FORM_GROUP_NAMES.Recurrence, 'second group name is correct'); - }); - - QUnit.test('Appointment popup should be with correct dates after change allDay switch and w/o saving (T832711)', async function(assert) { - const scheduler = await createScheduler({ dataSource: [] }); - const data = { - text: 'all day apo', - startDate: new Date(2017, 4, 1, 9, 30), - endDate: new Date(2017, 4, 1, 11), - allDay: true - }; - - scheduler.instance.showAppointmentPopup(data); - const allDayEditor = scheduler.appointmentForm.getEditor('allDay'); - allDayEditor.option('value', false); - scheduler.appointmentPopup.clickCancelButton(); - - scheduler.instance.showAppointmentPopup(data); - - assert.deepEqual(scheduler.appointmentForm.getEditor('startDate').option('value'), data.startDate); - assert.deepEqual(scheduler.appointmentForm.getEditor('endDate').option('value'), data.endDate); - }); - - QUnit.test('onAppointmentFormOpening event should pass e.popup argument', async function(assert) { - const data = [{ - text: 'Website Re-Design Plan', - startDate: new Date(2017, 4, 22, 9, 30), - endDate: new Date(2017, 4, 22, 11, 30) - }]; - - const scheduler = await createScheduler({ - dataSource: data, - onAppointmentFormOpening: (e) => { - assert.equal(e.popup.NAME, 'dxPopup', 'e.popup should be instance of dxPopup'); - - e.popup.option('showTitle', true); - e.popup.option('title', 'Information'); - } - }); - - scheduler.appointments.dblclick(); - assert.equal(scheduler.appointmentPopup.getPopupTitleElement().length, 1, 'title should be visible, after set dxPopup property on onAppointmentFormOpening'); - }); - - QUnit.test('onAppointmentFormOpening event should handle e.cancel value', async function(assert) { - const data = [{ - text: 'Website Re-Design Plan', - startDate: new Date(2017, 4, 22, 9, 30), - endDate: new Date(2017, 4, 22, 11, 30) - }]; - - const scheduler = await createScheduler({ dataSource: data }); - - const testCases = [ - { - expected: true, - handler: undefined, - text: 'appointment popup should visible in default setting case' - }, { - expected: false, - handler: e => e.cancel = true, - text: 'appointment popup should prevent visible in \'e.cancel = true\' case' - }, { - expected: true, - handler: e => e.cancel = false, - text: 'appointment popup should visible in \'e.cancel = false\' case' - } - ]; - - testCases.forEach(({ handler, expected, text }) => { - scheduler.option('onAppointmentFormOpening', handler); - - scheduler.appointments.dblclick(); - assert.equal(scheduler.appointmentPopup.isVisible(), expected, text + ' if call from UI'); - scheduler.instance.appointmentPopup.popup.option('visible', false); - - scheduler.instance.showAppointmentPopup(data[0]); - assert.equal(scheduler.appointmentPopup.isVisible(), expected, text + ' if call showAppointmentPopup method'); - scheduler.instance.appointmentPopup.popup.option('visible', false); - }); - }); - - QUnit.test('Appointment popup shouldn\'t render recurrence editor, if previous was with recurrence', async function(assert) { - const scheduler = await createScheduler(); - - scheduler.appointments.dblclick(); - scheduler.appointmentPopup.dialog.clickEditSeries(); - - assert.ok(scheduler.appointmentPopup.form.isRecurrenceEditorVisible(), 'Recurrence editor should visible'); - assert.equal(scheduler.appointmentPopup.form.getSubject(), 'recurrent-app', 'Subject should equal selected recurrence appointment'); - - scheduler.appointmentPopup.clickCancelButton(); - - scheduler.appointments.dblclick(5); - - assert.notOk(scheduler.appointmentPopup.form.isRecurrenceEditorVisible(), 'Recurrence editor shouldn\'t visible'); - assert.equal(scheduler.appointmentPopup.form.getSubject(), 'common-app', 'Subject in form should equal selected common appointment'); - }); - - QUnit.test('Appointment popup should work properly', async function(assert) { - const NEW_EXPECTED_SUBJECT = 'NEW SUBJECT'; - const scheduler = await createScheduler({}); - const appointmentPopup = scheduler.appointmentPopup; - - assert.notOk(appointmentPopup.isVisible(), 'Appointment popup should be invisible in on init'); - - await scheduler.appointments.click(scheduler.appointments.getAppointmentCount() - 1); - scheduler.tooltip.clickOnItem(); - appointmentPopup.form.setSubject(NEW_EXPECTED_SUBJECT); - - assert.ok(appointmentPopup.isVisible(), 'Appointment popup should be visible after showAppointmentPopup method'); - appointmentPopup.clickDoneButton(); - - const dataItem = scheduler.instance.option('dataSource')[1]; - assert.equal(Object.keys(dataItem).length, 3, 'In appointment properties shouldn\'t added excess properties'); - assert.equal(dataItem.text, NEW_EXPECTED_SUBJECT, `Text property of appointment should be changed on ${NEW_EXPECTED_SUBJECT}`); - - await scheduler.appointments.click(0); - scheduler.tooltip.clickOnItem(); - appointmentPopup.dialog.clickEditSeries(); - - assert.ok(appointmentPopup.form.isRecurrenceEditorVisible(), 'Recurrence editor should be visible after click on recurrence appointment'); - assert.equal(appointmentPopup.form.getSubject(), defaultData[0].text, 'Subject in form should equal selected appointment'); - }); - - QUnit.test('Recurrence repeat-end editor should have default \'never\' value after reopening appointment popup', async function(assert) { - const firstAppointment = { startDate: new Date(2015, 1, 9), endDate: new Date(2015, 1, 9, 1), text: 'caption 1' }; - const secondAppointment = { startDate: new Date(2015, 1, 9), endDate: new Date(2015, 1, 9, 1), text: 'caption 2' }; - const scheduler = await createScheduler(); - - scheduler.instance.showAppointmentPopup(firstAppointment); - - let form = scheduler.instance.getAppointmentDetailsForm(); - let visibilityChanged = form.getEditor('visibilityChanged'); - visibilityChanged.option('value', true); - - const repeatEndEditor = form.getEditor('recurrenceRule').getEditorByField('repeatEnd'); - repeatEndEditor.option('value', 'count'); - scheduler.appointmentPopup.clickDoneButton(); - - scheduler.instance.showAppointmentPopup(secondAppointment); - form = scheduler.instance.getAppointmentDetailsForm(); - visibilityChanged = form.getEditor('visibilityChanged'); - visibilityChanged.option('value', true); - - assert.strictEqual(repeatEndEditor.option('value'), 'never', 'Repeat-type editor value is ok'); - }); - - QUnit.test('Update appointment if CustomStore', async function(assert) { - const data = [{ - startDate: new Date(2015, 4, 24, 9), - endDate: new Date(2015, 4, 24, 11) - }]; - const scheduler = await createScheduler({ - views: ['day'], - dataSource: { - key: 'id', - load: () => data, - update: (key, values) => { - return new Promise(resolve => { - setTimeout(() => { - const appointmentData = data.filter(item => item.id === key)[0]; - $.extend(appointmentData, values); - scheduler.instance.repaint(); - resolve(); - }, 200); - }); - }, - }, - currentDate: new Date(2015, 4, 24), - startDayHour: 8, - endDayHour: 18 - }); - - scheduler.instance.showAppointmentPopup({ - startDate: new Date(2015, 4, 24, 9), - endDate: new Date(2015, 4, 24, 11), - text: 'Subject' - }); - - scheduler.appointmentForm.setSubject('New Subject'); - - const deferred = scheduler.appointmentPopup.saveAppointmentData(); - - assert.notOk(scheduler.appointmentPopup.getInstance().tryLockSaveChanges(), 'Save changes already locked'); - - assert.ok(scheduler.appointmentPopup.hasLoadPanel(), 'has load panel'); - - await waitAsync(250); - - deferred.done(() => { - assert.notOk(scheduler.appointmentPopup.hasLoadPanel(), 'has no load panel'); - assert.equal(scheduler.appointments.getTitleText(0), 'New Subject', 'Subject is correct'); - }); - }); - - QUnit.test('Insert appointment if CustomStore', async function(assert) { - const done = assert.async(); - const data = []; - const scheduler = await createScheduler({ - views: ['day'], - dataSource: { - key: 'id', - load: () => data, - insert: appointmentData => new Promise(resolve => { - setTimeout(() => { - appointmentData.id = data.length; - data.push(appointmentData); - resolve(); - done(); - }, 200); - }) - }, - currentDate: new Date(2015, 4, 24), - startDayHour: 8, - endDayHour: 18 - }); - - scheduler.instance.showAppointmentPopup(); - - scheduler.appointmentForm.setSubject('New Subject'); - scheduler.appointmentForm.setStartDate(new Date(2015, 4, 24, 9)); - scheduler.appointmentForm.setEndDate(new Date(2015, 4, 24, 11)); - - const deferred = scheduler.appointmentPopup.saveAppointmentData(); - - assert.ok(scheduler.appointmentPopup.hasLoadPanel(), 'has load panel'); - - await waitAsync(250); - - deferred.done(() => { - assert.notOk(scheduler.appointmentPopup.hasLoadPanel(), 'has no load panel'); - assert.equal(scheduler.appointments.getTitleText(0), 'New Subject', 'Subject is correct'); - }); - }); - - [true, false].forEach(cancel => { - QUnit.test(`onAppointmentUpdating and e.cancel=${cancel} (T907281)`, async function(assert) { - const data = [{ - startDate: new Date(2015, 4, 24, 9), - endDate: new Date(2015, 4, 24, 11), - text: 'Subject' - }]; - const scheduler = await createScheduler({ - views: ['day'], - dataSource: data, - currentDate: new Date(2015, 4, 24), - startDayHour: 8, - endDayHour: 18, - onAppointmentUpdating: e => e.cancel = cancel - }); - - scheduler.instance.showAppointmentPopup(data[0]); - - scheduler.appointmentForm.setSubject('New Subject'); - - scheduler.appointmentPopup.saveAppointmentData(); - - assert.notOk(scheduler.appointmentPopup.hasLoadPanel(), 'Has no load panel'); - - const subject = cancel ? 'Subject' : 'New Subject'; - assert.equal(scheduler.appointments.getTitleText(0), subject, 'Subject is correct'); - }); - - QUnit.test(`onAppointmentAdding and e.cancel=${cancel}`, async function(assert) { - const scheduler = await createScheduler({ - views: ['day'], - dataSource: [], - currentDate: new Date(2015, 4, 24), - startDayHour: 8, - endDayHour: 18, - onAppointmentAdding: e => e.cancel = cancel - }); - - scheduler.instance.showAppointmentPopup(); - - scheduler.appointmentForm.setStartDate(new Date(2015, 4, 24, 9)); - scheduler.appointmentForm.setEndDate(new Date(2015, 4, 24, 11)); - scheduler.appointmentForm.setSubject('New Subject'); - - scheduler.appointmentPopup.saveAppointmentData(); - - assert.notOk(scheduler.appointmentPopup.hasLoadPanel(), 'Has no load panel'); - - const subject = cancel ? '' : 'New Subject'; - assert.equal(scheduler.appointments.getTitleText(0), subject, 'Subject is correct'); - }); - - QUnit.test(`onAppointmentDeleting and e.cancel=${cancel}`, async function(assert) { - const data = [{ - text: 'Some Text', - startDate: new Date(2015, 4, 24, 9), - endDate: new Date(2015, 4, 24, 11) - }]; - const scheduler = await createScheduler({ - views: ['day'], - dataSource: data, - currentDate: new Date(2015, 4, 24), - startDayHour: 8, - endDayHour: 18, - onAppointmentDeleting: e => e.cancel = cancel - }); - - scheduler.instance.deleteAppointment(data[0]); - await waitAsync(10); - - assert.notOk(scheduler.appointmentPopup.hasLoadPanel(), 'Has no load panel'); - - const subject = cancel ? 'Some Text' : ''; - assert.equal(scheduler.appointments.getTitleText(0), subject, 'Subject is correct'); - }); - }); - - QUnit.module('toolbar', () => { - [true, false].forEach(allowUpdatingValue => { - const data = [{ - text: 'Website Re-Design Plan', - startDate: new Date(2017, 4, 22, 9, 30), - endDate: new Date(2017, 4, 22, 11, 30), - disabled: true - }, { - text: 'Book Flights to San Fran for Sales Trip', - startDate: new Date(2017, 4, 22, 12, 0), - endDate: new Date(2017, 4, 22, 13, 0), - }]; - - QUnit.test(`done button visibility in case allowUpdatingValue = ${allowUpdatingValue}`, async function(assert) { - const scheduler = await createWrapper({ - dataSource: data, - views: ['week'], - currentView: 'week', - currentDate: new Date(2017, 4, 25), - editing: { - allowUpdating: allowUpdatingValue, - legacyForm: true - } - }); - - const assertText = `done button visibility should be equal to = ${allowUpdatingValue}`; - for(let i = 0; i < scheduler.appointments.getAppointmentCount(); i++) { - scheduler.appointments.dblclick(i); - assert.equal(scheduler.appointmentPopup.getDoneButton().length > 0, allowUpdatingValue, assertText); - scheduler.appointmentPopup.clickCancelButton(); - } - }); - }); - - QUnit.test('toolbar should be re-rendered after change editing option', async function(assert) { - const scheduler = await createWrapper({ - dataSource: [], - views: ['week'], - currentView: 'week', - currentDate: new Date(2017, 4, 25), - editing: { - allowUpdating: true, - legacyForm: true - } - }); - - const dataObj = { - text: 'a', - startDate: new Date(2015, 5, 15, 10), - endDate: new Date(2015, 5, 15, 11) - }; - - scheduler.instance.showAppointmentPopup(dataObj); - assert.ok(scheduler.appointmentPopup.getDoneButton().length > 0, '"done" button should be visible'); - - scheduler.option('editing', { - allowUpdating: false - }); - - scheduler.instance.showAppointmentPopup(dataObj); - assert.notOk(scheduler.appointmentPopup.getDoneButton().length > 0, '"done" button shouldn\'t be visible after set allowUpdating option to false'); - - scheduler.instance.showAppointmentPopup(); - assert.ok(scheduler.appointmentPopup.getDoneButton().length > 0, '"done" button should be visible in case \'create new appointment\''); - }); - }); -}); - -if(isDesktopEnvironment()) { - QUnit.module('Appointment Popup and Recurrence Editor visibility', { - beforeEach() { - fx.off = true; - setWindowWidth(1000); - }, - - afterEach() { - fx.off = false; - resetWindowWidth(); - } - }); - - QUnit.test('Recurrence editor container should be visible if recurrence rule was set', async function(assert) { - const scheduler = await createScheduler(); - scheduler.instance.showAppointmentPopup({ startDate: new Date(2018, 5, 18), endDate: Date(2018, 5, 18), text: 'a', recurrenceRule: 'FREQ=WEEKLY' }); - $('.dx-dialog-buttons .dx-button').eq(0).trigger('dxclick'); - - checkFormWithRecurrenceEditor(assert, scheduler.instance, true); - }); - - QUnit.test('Recurrence editor container should be visible after changing its visibility value', async function(assert) { - const scheduler = await createScheduler(); - scheduler.instance.showAppointmentPopup({ startDate: new Date(2018, 5, 18), endDate: Date(2018, 5, 18), text: 'a' }); - - const form = scheduler.instance.getAppointmentDetailsForm(); - checkFormWithRecurrenceEditor(assert, scheduler.instance, false); - - form.getEditor('visibilityChanged').option('value', true); - checkFormWithRecurrenceEditor(assert, scheduler.instance, true); - - form.getEditor('visibilityChanged').option('value', false); - checkFormWithRecurrenceEditor(assert, scheduler.instance, false); - }); - - QUnit.test('Popup should show or not show reccurence editor after many opening with different data', async function(assert) { - const scheduler = await createScheduler(); - scheduler.instance.showAppointmentPopup({ startDate: new Date(2018, 5, 18), endDate: Date(2018, 5, 18), text: 'a' }); - checkFormWithRecurrenceEditor(assert, scheduler.instance, false); - scheduler.instance.appointmentPopup.popup.hide(); - scheduler.instance.showAppointmentPopup({ startDate: new Date(2018, 5, 18), endDate: Date(2018, 5, 18), text: 'b', recurrenceRule: 'FREQ=WEEKLY' }); - $('.dx-dialog-buttons .dx-button').eq(0).trigger('dxclick'); - checkFormWithRecurrenceEditor(assert, scheduler.instance, true); - scheduler.instance.appointmentPopup.popup.hide(); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2018, 5, 18), endDate: Date(2018, 5, 18), text: 'c' }); - checkFormWithRecurrenceEditor(assert, scheduler.instance, false); - }); - - QUnit.test('Popup should show or not to show reccurence editor after many opening with and change visibility', async function(assert) { - const scheduler = await createScheduler(); - scheduler.instance.showAppointmentPopup({ startDate: new Date(2018, 5, 18), endDate: Date(2018, 5, 18), text: 'a' }); - - const form = scheduler.instance.getAppointmentDetailsForm(); - form.getEditor('visibilityChanged').option('value', true); - scheduler.instance.appointmentPopup.popup.hide(); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2018, 5, 18), endDate: Date(2018, 5, 18), text: 'b', recurrenceRule: 'FREQ=WEEKLY' }); - $('.dx-dialog-buttons .dx-button').eq(0).trigger('dxclick'); - checkFormWithRecurrenceEditor(assert, scheduler.instance, true); - }); - - QUnit.test('Popup should not contain recurrence editor, if recurrenceRuleExpr is null', async function(assert) { - const scheduler = await createScheduler(); - const appointment = { - startDate: new Date(2015, 1, 1, 1), - endDate: new Date(2015, 1, 1, 2), - text: 'caption', - recurrenceRule: 'FREQ=YEARLY' - }; - - scheduler.instance.option('recurrenceRuleExpr', null); - scheduler.instance.showAppointmentPopup(appointment); - - const form = scheduler.instance.getAppointmentDetailsForm(); - - assert.ok(!form.getEditor(null), 'Editor is not rendered'); - assert.equal(scheduler.instance.appointmentPopup.popup.option('maxWidth'), APPOINTMENT_POPUP_WIDTH); - assert.equal(form.option('items')[0].colSpan, 2, 'colSpan of main group'); - - scheduler.instance.option('recurrenceRuleExpr', 'recurrenceRule'); - - scheduler.instance.showAppointmentPopup(appointment); - $('.dx-dialog-buttons .dx-button').eq(0).trigger('dxclick'); - - checkFormWithRecurrenceEditor(assert, scheduler.instance, true, APPOINTMENT_POPUP_WIDTH_WITH_RECURRENCE, 1); - }); - - QUnit.test('Popup should not contain recurrence editor, if recurrenceRuleExpr is \'\'', async function(assert) { - const scheduler = await createScheduler(); - const appointment = { - startDate: new Date(2015, 1, 1, 1), - endDate: new Date(2015, 1, 1, 2), - text: 'caption', - recurrenceRule: 'FREQ=YEARLY' - }; - - scheduler.instance.option('recurrenceRuleExpr', ''); - scheduler.instance.showAppointmentPopup(appointment); - const form = scheduler.instance.getAppointmentDetailsForm(); - - assert.ok(!form.getEditor(null), 'Editor is not rendered'); - assert.equal(scheduler.instance.appointmentPopup.popup.option('maxWidth'), APPOINTMENT_POPUP_WIDTH); - assert.equal(form.option('items')[0].colSpan, 2, 'colSpan of main group'); - }); - - QUnit.test('Multiple showing appointment popup for recurrence appointments and after update options should work correct', async function(assert) { - const scheduler = await createScheduler(); - scheduler.instance.showAppointmentPopup({ - text: 'Appointment 1', - startDate: new Date(2017, 4, 1, 9, 30), - endDate: new Date(2017, 4, 1, 11) - }); - - scheduler.instance.hideAppointmentPopup(true); - scheduler.instance.option('recurrenceEditMode', 'series'); - - scheduler.instance.showAppointmentPopup({ - text: 'Appointment 2', - startDate: new Date(2017, 4, 1, 9, 30), - endDate: new Date(2017, 4, 1, 11), - recurrenceRule: 'FREQ=WEEKLY;BYDAY=MO,TH' - }); - - checkFormWithRecurrenceEditor(assert, scheduler.instance, true); - }); -} - -QUnit.module('Appointment Popup Content', moduleOptions, () => { - QUnit.test('appointmentPopup should not prevent mouse/touch events by default (T968188)', async function(assert) { - const scheduler = await createInstance({}); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1), endDate: new Date(2015, 1, 2) }); - - const appointmentPopupOptions = scheduler.instance.appointmentPopup.popup.option(); - - assert.strictEqual(appointmentPopupOptions.enableBodyScroll, false, 'enable body scroll'); - assert.strictEqual(appointmentPopupOptions.preventScrollEvents, false, 'prevent scroll events'); - }); - - QUnit.test('showAppointmentPopup method with passed a recurrence appointment should render popup(T698732)', async function(assert) { - const appointments = [ - { - text: 'TEST_TEXT', - startDate: new Date(2017, 4, 1, 9, 30), - endDate: new Date(2017, 4, 1, 11), - recurrenceRule: 'FREQ=WEEKLY;BYDAY=MO,TH;COUNT=10' - } - ]; - - const scheduler = await createInstance({ - dataSource: appointments, - currentDate: new Date(2017, 4, 25), - startDayHour: 9, - }); - - scheduler.instance.showAppointmentPopup(appointments[0], false); - - const popupChoiceAppointmentEdit = $('.dx-popup-normal.dx-resizable').not('.dx-state-invisible'); - assert.equal(popupChoiceAppointmentEdit.length, 1, 'Popup with choice edit mode is rendered'); - - popupChoiceAppointmentEdit.find('.dx-popup-bottom .dx-button:eq(1)').trigger('dxclick'); - assert.equal($('.dx-scheduler-legacy-appointment-popup').length, 2, 'Appointment popup is rendered'); - - const form = scheduler.instance.getAppointmentDetailsForm(); - const startDateBox = form.getEditor('startDate'); - const endDateBox = form.getEditor('endDate'); - - assert.equal(startDateBox.option('value').valueOf(), appointments[0].startDate.valueOf(), 'Value in start dateBox valid'); - assert.equal(endDateBox.option('value').valueOf(), appointments[0].endDate.valueOf(), 'Value in end dateBox valid'); - }); - - QUnit.test('showAppointmentPopup should render a popup only once', async function(assert) { - const scheduler = await createInstance({}); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1), endDate: new Date(2015, 1, 2) }); - - assert.equal($('.dx-scheduler-legacy-appointment-popup').length, 2, 'Popup is rendered'); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1), endDate: new Date(2015, 1, 2) }); - assert.equal($('.dx-scheduler-legacy-appointment-popup').length, 2, 'Popup is rendered'); - }); - - QUnit.test('showAppointmentPopup should work correctly after scheduler repainting', async function(assert) { - const scheduler = await createInstance({}); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1), endDate: new Date(2015, 1, 2) }); - - assert.equal($('.dx-scheduler-legacy-appointment-popup').length, 2, 'Popup is rendered'); - scheduler.instance.repaint(); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1), endDate: new Date(2015, 1, 2) }); - assert.equal($('.dx-scheduler-legacy-appointment-popup').length, 2, 'Popup is rendered'); - }); - - QUnit.test('changing editing should work correctly after showing popup', async function(assert) { - const scheduler = await createInstance({}); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1), endDate: new Date(2015, 1, 2) }); - scheduler.instance.hideAppointmentPopup(true); - - scheduler.instance.option('editing.allowUpdating', false); - scheduler.instance.option('editing.allowUpdating', true); - - assert.ok(true, 'OK'); - }); - - QUnit.test('hideAppointmentPopup should hide a popup', async function(assert) { - const scheduler = await createInstance({}); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1), endDate: new Date(2015, 1, 2) }); - - assert.equal($('.dx-scheduler-legacy-appointment-popup').length, 2, 'Popup is rendered'); - scheduler.instance.hideAppointmentPopup(); - assert.equal($('.dx-scheduler-legacy-appointment-popup').length, 1, 'Popup is hidden'); - }); - - QUnit.test('hideAppointmentPopup should hide a popup and save changes', async function(assert) { - const scheduler = await createInstance({ - currentDate: new Date(2016, 9, 10), - currentView: 'month', - }); - - scheduler.instance.showAppointmentPopup({ text: '1', startDate: new Date(2016, 9, 10), endDate: new Date(2016, 9, 11) }, true); - - assert.equal($('.dx-scheduler-legacy-appointment-popup').length, 2, 'Popup is rendered'); - scheduler.instance.hideAppointmentPopup(true); - assert.equal($('.dx-scheduler-legacy-appointment-popup').length, 1, 'Popup is hidden'); - assert.equal($('.dx-scheduler-appointment').length, 1, 'appointment is created'); - }); - - QUnit.test('showAppointmentPopup should render a popup form only once', async function(assert) { - const scheduler = await createInstance({}); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1), endDate: new Date(2015, 1, 2), text: 'appointment 1' }); - - const $form = $('.dx-scheduler-legacy-appointment-popup').find('.dx-form').not('.dx-recurrence-editor-container'); - assert.equal($form.length, 1, 'Form was rendered'); - - scheduler.instance.hideAppointmentPopup(); - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1), endDate: new Date(2015, 1, 2), text: 'appointment 2' }); - - assert.equal($form.find('.dx-textbox').eq(0).dxTextBox('instance').option('text'), 'appointment 2', 'Form data is correct'); - }); - - QUnit.test('popup should have right height', async function(assert) { - const scheduler = await createInstance({}); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1), endDate: new Date(2015, 1, 2), text: 'appointment 1' }); - - const popup = scheduler.instance.appointmentPopup.popup; - - assert.equal(popup.option('height'), 'auto', 'popup has correct height'); - assert.equal(popup.option('maxHeight'), '100%', 'popup has correct max-height'); - }); - - QUnit.test('showAppointmentPopup should render a popup content only once', async function(assert) { - const scheduler = await createInstance({}); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1), endDate: new Date(2015, 1, 2), text: 'appointment 1' }); - - const popup = scheduler.instance.appointmentPopup.popup; - let contentReadyCalled = 0; - - popup.option('onContentReady', function() { - contentReadyCalled++; - }); - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1), endDate: new Date(2015, 1, 2), text: 'appointment 2' }); - - assert.equal(contentReadyCalled, 0, 'Content wasn\'t rerendered'); - }); - - QUnit.test('Popup should contain editors and components with right dx-rtl classes and rtlEnabled option value', async function(assert) { - const scheduler = await createWrapper({ rtlEnabled: true, editing: { legacyForm: true } }); - - scheduler.instance.showAppointmentPopup({}); - - const $innerSwitch = $('.dx-scheduler-legacy-appointment-popup .dx-switch').eq(0); - - assert.ok($innerSwitch.hasClass('dx-rtl'), 'Inner editor has dx-rtl class'); - assert.equal($innerSwitch.dxSwitch('instance').option('rtlEnabled'), true, 'rtlEnabled option value is right'); - }); - - QUnit.test('Popup should contains start datebox with right value', async function(assert) { - const scheduler = await createInstance({}); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1, 1), endDate: new Date(2015, 1, 1, 2), text: 'caption' }); - - const $popupContent = $('.dx-scheduler-legacy-appointment-popup .dx-popup-content'); - const $dateBox = $popupContent.find('.dx-datebox').eq(0); - - assert.equal($dateBox.length, 1, 'Start date box is rendered'); - assert.deepEqual($dateBox.dxDateBox('instance').option('value'), new Date(2015, 1, 1, 1), 'value is right'); - }); - - QUnit.test('Calendar of the start datebox should have right firstDayOfWeek value', async function(assert) { - if(devices.current().deviceType === 'desktop') { - const scheduler = await createInstance({ - firstDayOfWeek: 4, - }); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1, 1), endDate: new Date(2015, 1, 1, 2), text: 'caption' }); - - const $popupContent = $('.dx-scheduler-legacy-appointment-popup .dx-popup-content'); - const startDateBox = $popupContent.find('.dx-datebox').eq(0).dxDateBox('instance'); - - startDateBox.open(); - const calendar = startDateBox._popup.$content().find('.dx-calendar').dxCalendar('instance'); - - assert.equal(calendar.option('firstDayOfWeek'), 4, 'firstDayOfWeek is right'); - } else { - assert.ok(true, 'It doesn\'t make sense on mobile devices'); - } - }); - - QUnit.test('Popup should contains end datebox with right value', async function(assert) { - const scheduler = await createInstance({}); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1, 1), endDate: new Date(2015, 1, 1, 2), text: 'caption' }); - - const $popupContent = $('.dx-scheduler-legacy-appointment-popup .dx-popup-content'); - const $dateBox = $popupContent.find('.dx-datebox').eq(1); - - assert.equal($dateBox.length, 1, 'End datebox is rendered'); - assert.deepEqual($dateBox.dxDateBox('instance').option('value'), new Date(2015, 1, 1, 2), 'value is right'); - }); - - QUnit.test('Calendar of the end datebox should have right firstDayOfWeek value', async function(assert) { - if(devices.current().deviceType === 'desktop') { - const scheduler = await createInstance({ - firstDayOfWeek: 4, - }); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1, 1), endDate: new Date(2015, 1, 1, 2), text: 'caption' }); - - const $popupContent = $('.dx-scheduler-legacy-appointment-popup .dx-popup-content'); - const endDateBox = $popupContent.find('.dx-datebox').eq(1).dxDateBox('instance'); - - endDateBox.open(); - const calendar = endDateBox._popup.$content().find('.dx-calendar').dxCalendar('instance'); - - assert.equal(calendar.option('firstDayOfWeek'), 4, 'firstDayOfWeek is right'); - } else { - assert.ok(true, 'It doesn\'t make sense on mobile devices'); - } - }); - - QUnit.test('Changing startDateBox value should change endDateBox value if needed', async function(assert) { - const scheduler = await createInstance({}); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1), endDate: new Date(2015, 1, 3), text: 'caption' }); - const form = scheduler.instance.getAppointmentDetailsForm(); - const startDateBox = form.getEditor('startDate'); - const endDateBox = form.getEditor('endDate'); - - startDateBox.option('value', new Date(2015, 1, 4)); - - assert.deepEqual(endDateBox.option('value'), new Date(2015, 1, 6), 'endDate value is right'); - - startDateBox.option('value', new Date(2015, 1, 3)); - - assert.deepEqual(endDateBox.option('value'), new Date(2015, 1, 6), 'endDate value is right'); - }); - - QUnit.test('Changing startDateBox value should change endDateBox value if needed(when startDate and endDate are strings)', async function(assert) { - const scheduler = await createInstance({}); - - scheduler.instance.showAppointmentPopup({ startDate: '1/1/2015', endDate: '1/3/2015', text: 'caption' }); - const form = scheduler.instance.getAppointmentDetailsForm(); - const startDateBox = form.getEditor('startDate'); - const endDateBox = form.getEditor('endDate'); - - startDateBox.option('value', new Date(2015, 1, 4)); - - assert.deepEqual(endDateBox.option('value'), new Date(2015, 1, 6), 'endDate value is right'); - - startDateBox.option('value', new Date(2015, 1, 3)); - - assert.deepEqual(endDateBox.option('value'), new Date(2015, 1, 6), 'endDate value is right'); - }); - - QUnit.test('startDateBox value should be valid', async function(assert) { - const scheduler = await createInstance({}); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1), endDate: new Date(2015, 1, 3), text: 'caption' }); - const form = scheduler.instance.getAppointmentDetailsForm(); - const startDateBox = form.getEditor('startDate'); - - startDateBox.option('value', undefined); - - assert.deepEqual(startDateBox.option('value'), new Date(2015, 1, 1), 'startDate value is initial value'); - }); - - QUnit.test('Changing endDateBox value should change startDateBox value if needed', async function(assert) { - const scheduler = await createInstance({}); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 10), endDate: new Date(2015, 1, 13), text: 'caption' }); - - const $popupContent = $('.dx-scheduler-legacy-appointment-popup .dx-popup-content'); - const startDateBox = $popupContent.find('.dx-datebox').eq(0).dxDateBox('instance'); - const endDateBox = $popupContent.find('.dx-datebox').eq(1).dxDateBox('instance'); - - endDateBox.option('value', new Date(2015, 1, 9)); - - assert.deepEqual(startDateBox.option('value'), new Date(2015, 1, 6), 'startDate value is right'); - - endDateBox.option('value', new Date(2015, 1, 10)); - - assert.deepEqual(startDateBox.option('value'), new Date(2015, 1, 6), 'startDate value is right'); - }); - - QUnit.test('Changing endDateBox value should change startDateBox value if needed(when startDate and endDate are strings)', async function(assert) { - const scheduler = await createInstance({}); - - scheduler.instance.showAppointmentPopup({ startDate: '1/10/2015', endDate: '1/13/2015', text: 'caption' }); - - const $popupContent = $('.dx-scheduler-legacy-appointment-popup .dx-popup-content'); - const startDateBox = $popupContent.find('.dx-datebox').eq(0).dxDateBox('instance'); - const endDateBox = $popupContent.find('.dx-datebox').eq(1).dxDateBox('instance'); - - endDateBox.option('value', new Date(2015, 0, 9)); - - assert.deepEqual(startDateBox.option('value'), new Date(2015, 0, 6), 'startDate value is right'); - - endDateBox.option('value', new Date(2015, 0, 10)); - - assert.deepEqual(startDateBox.option('value'), new Date(2015, 0, 6), 'startDate value is right'); - }); - - QUnit.test('endDateBox value should be valid', async function(assert) { - const scheduler = await createInstance({}); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1), endDate: new Date(2015, 1, 3), text: 'caption' }); - const form = scheduler.instance.getAppointmentDetailsForm(); - const endDateBox = form.getEditor('endDate'); - - endDateBox.option('value', undefined); - - assert.deepEqual(endDateBox.option('value'), new Date(2015, 1, 3), 'endDate value is initial value'); - }); - - QUnit.test('Popup should contains caption textbox with right value', async function(assert) { - const scheduler = await createInstance({}); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1, 1), endDate: new Date(2015, 1, 1, 2), text: 'caption' }); - - const form = scheduler.instance.getAppointmentDetailsForm(); - const textBox = form.getEditor('text'); - - assert.equal(textBox.$element().length, 1, 'Caption text is rendered'); - assert.equal(textBox.option('value'), 'caption', 'value is right'); - }); - - QUnit.test('Confirm dialog should be shown when showAppointmentPopup for recurrence appointment was called', async function(assert) { - const scheduler = await createInstance({}); - - const startDate = new Date(2015, 1, 1, 1); - - scheduler.instance.showAppointmentPopup({ - startDate: startDate, - endDate: new Date(2015, 1, 1, 2), - text: 'caption', - recurrenceRule: 'FREQ=YEARLY' - }); - - assert.ok($('.dx-dialog').length, 'Dialog was shown'); - $('.dx-dialog-buttons .dx-button').eq(0).trigger('dxclick'); - }); - - QUnit.test('Recurrence Editor should have right freq editor value if recurrence rule was set on init', async function(assert) { - const scheduler = await createInstance({}); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2018, 5, 18), endDate: Date(2018, 5, 18), text: 'a', recurrenceRule: 'FREQ=WEEKLY' }); - $('.dx-dialog-buttons .dx-button').eq(0).trigger('dxclick'); - - const form = scheduler.instance.getAppointmentDetailsForm(); - const recurrenceEditor = form.getEditor('recurrenceRule'); - const freqEditor = recurrenceEditor.getEditorByField('freq'); - - assert.equal(freqEditor.option('value'), 'weekly', 'value is right'); - }); - - QUnit.test('Popup should contain recurrence editor with right config', async function(assert) { - const scheduler = await createInstance({ - recurrenceEditMode: 'series', - firstDayOfWeek: 5, - }); - - const startDate = new Date(2015, 1, 1, 1); - - scheduler.instance.showAppointmentPopup({ - startDate: startDate, - endDate: new Date(2015, 1, 1, 2), - text: 'caption', - recurrenceRule: 'FREQ=YEARLY' - }); - - const form = scheduler.instance.getAppointmentDetailsForm(); - const recurrenceEditor = form.getEditor('recurrenceRule'); - - assert.equal(recurrenceEditor.option('value'), 'FREQ=YEARLY', 'value is right'); - assert.deepEqual(recurrenceEditor.option('startDate'), startDate, 'startDate value is right'); - assert.equal(recurrenceEditor.option('firstDayOfWeek'), 5, 'firstDayOfWeek value is right'); - }); - - QUnit.test('Recurrence editor should change value if freq editor value changed', async function(assert) { - const scheduler = await createInstance({}); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2018, 5, 18), endDate: Date(2018, 5, 18), text: 'a', recurrenceRule: 'FREQ=WEEKLY' }); - $('.dx-dialog-buttons .dx-button').eq(0).trigger('dxclick'); - - const form = scheduler.instance.getAppointmentDetailsForm(); - const recurrenceEditor = form.getEditor('recurrenceRule'); - const freqEditor = recurrenceEditor.getEditorByField('freq'); - - freqEditor.option('value', 'daily'); - - assert.equal(recurrenceEditor.option('value'), 'FREQ=DAILY', 'recEditor has right value'); - }); - - QUnit.test('Recurrence editor should has right startDate after form items change', async function(assert) { - const scheduler = await createInstance({ - onAppointmentFormOpening: function(e) { - const items = e.form.option('items'); - - items.push({ - dataField: 'location', - editorType: 'dxTextBox', - label: { - text: 'Location' - } - }); - - e.form.option('items', items); - }, - }); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2016, 5, 4), endDate: new Date(2016, 5, 5), recurrenceRule: 'FREQ=WEEKLY' }); - $('.dx-dialog-buttons .dx-button').eq(0).trigger('dxclick'); - - const form = scheduler.instance.getAppointmentDetailsForm(); - const recEditor = form.getEditor('recurrenceRule'); - - assert.deepEqual(recEditor.option('startDate'), new Date(2016, 5, 4), 'startDate is ok'); - }); - - QUnit.test('Popup should contains description editor', async function(assert) { - const scheduler = await createInstance({}); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1, 1), endDate: new Date(2015, 1, 1, 2), text: 'caption', description: 'First task of this day' }); - - const form = scheduler.instance.getAppointmentDetailsForm(); - const descriptionEditor = form.getEditor('description'); - - assert.equal(descriptionEditor.$element().length, 1, 'Description editor is rendered'); - assert.equal(descriptionEditor.option('value'), 'First task of this day', 'value is right'); - }); - - QUnit.test('Popup should contains allDay editor', async function(assert) { - const scheduler = await createInstance({}); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1, 1), endDate: new Date(2015, 1, 1, 2), text: 'caption', description: 'First task of this day', allDay: true }); - - const form = scheduler.instance.getAppointmentDetailsForm(); - const allDayEditor = form.getEditor('allDay'); - - assert.equal(allDayEditor.option('value'), true, 'value is right'); - }); - - QUnit.test('allDay changing should switch date & type in editors', async function(assert) { - const scheduler = await createInstance({ - startDayHour: 5, - }); - - scheduler.instance.showAppointmentPopup({ - startDate: new Date(2015, 1, 1, 6), - endDate: new Date(2015, 1, 2, 7), text: 'caption', description: 'First task of this day' - }); - - const $popupContent = $('.dx-scheduler-legacy-appointment-popup .dx-popup-content'); - const $allDayEditor = $popupContent.find('.dx-switch').eq(0); - const allDayEditor = $allDayEditor.dxSwitch('instance'); - - allDayEditor.option('value', true); - - const startDate = $popupContent.find('.dx-datebox').eq(0).dxDateBox('instance'); - const endDate = $popupContent.find('.dx-datebox').eq(1).dxDateBox('instance'); - - assert.deepEqual(startDate.option('value'), new Date(2015, 1, 1), 'value is right'); - assert.equal(startDate.option('type'), 'date', 'type is right'); - - assert.deepEqual(endDate.option('value'), new Date(2015, 1, 1), 'value is right'); - assert.equal(endDate.option('type'), 'date', 'type is right'); - - allDayEditor.option('value', false); - - assert.equal(startDate.option('type'), 'datetime', 'type is right after turning off allDay'); - assert.equal(endDate.option('type'), 'datetime', 'type is right after turning off allDay'); - assert.deepEqual(startDate.option('value'), new Date(2015, 1, 1, 5), 'startdate is OK'); - assert.deepEqual(endDate.option('value'), new Date(2015, 1, 1, 5, 30), 'enddate is OK'); - }); - - QUnit.test('allDay changing should switch only type in editors, if startDate is undefined', async function(assert) { - const scheduler = await createInstance({}); - - scheduler.instance.showAppointmentPopup({ - text: 'test appointment', - allDay: true - }, true, null); - - const $popupContent = $('.dx-scheduler-legacy-appointment-popup .dx-popup-content'); - const $allDayEditor = $popupContent.find('.dx-switch').eq(0); - const allDayEditor = $allDayEditor.dxSwitch('instance'); - - allDayEditor.option('value', false); - - const startDate = $popupContent.find('.dx-datebox').eq(0).dxDateBox('instance'); - const endDate = $popupContent.find('.dx-datebox').eq(1).dxDateBox('instance'); - - assert.equal(startDate.option('type'), 'datetime', 'type is right'); - assert.equal(endDate.option('type'), 'datetime', 'type is right'); - assert.deepEqual(startDate.option('value'), null, 'value is right'); - assert.deepEqual(endDate.option('value'), null, 'value is right'); - - allDayEditor.option('value', true); - - assert.equal(startDate.option('type'), 'date', 'type is right after turning off allDay'); - assert.equal(endDate.option('type'), 'date', 'type is right after turning off allDay'); - assert.deepEqual(startDate.option('value'), null, 'startdate is OK'); - assert.deepEqual(endDate.option('value'), null, 'enddate is OK'); - }); - - QUnit.test('There are no exceptions when select date on the appointment popup, startDate > endDate', async function(assert) { - const scheduler = await createInstance({}); - - const date = new Date(); - - scheduler.instance.showAppointmentPopup({ - allDay: true, - text: '', - startDate: date, - endDate: date, - recurrence: null, - recurrenceException: null - }); - - const $popupContent = $('.dx-scheduler-legacy-appointment-popup .dx-popup-content'); - const startDate = $popupContent.find('.dx-datebox').eq(0).dxDateBox('instance'); - const dateToTest = new Date(); - - dateToTest.setDate(date.getDate() + 5); - - startDate.option('value', dateToTest); - - assert.ok(true, 'There are no exceptions'); - }); - - QUnit.test('There are no exceptions when select date on the appointment popup,startDate < endDate', async function(assert) { - const scheduler = await createInstance({}); - - const date = new Date(); - - scheduler.instance.showAppointmentPopup({ - allDay: true, - text: '', - startDate: date, - endDate: date, - recurrence: null, - recurrenceException: null - }); - - const $popupContent = $('.dx-scheduler-legacy-appointment-popup .dx-popup-content'); - const endDate = $popupContent.find('.dx-datebox').eq(1).dxDateBox('instance'); - const dateToTest = new Date(); - - dateToTest.setDate(date.getDate() - 5); - - endDate.option('value', dateToTest); - - assert.ok(true, 'There are no exceptions'); - }); - - QUnit.test('There are no exceptions when select date on the appointment popup,if dates are undefined', async function(assert) { - const scheduler = await createInstance({}); - - const date = new Date(); - - scheduler.instance.showAppointmentPopup({ - allDay: true, - text: '', - recurrence: null, - recurrenceException: null - }, true, null); - - const $popupContent = $('.dx-scheduler-legacy-appointment-popup .dx-popup-content'); - const startDate = $popupContent.find('.dx-datebox').eq(0).dxDateBox('instance'); - const endDate = $popupContent.find('.dx-datebox').eq(1).dxDateBox('instance'); - const dateToTest = new Date(); - - dateToTest.setDate(date.getDate() - 5); - - startDate.option('value', date); - endDate.option('value', dateToTest); - - assert.ok(true, 'There are no exceptions'); - }); - - QUnit.test('Validate works always before done click', async function(assert) { - const data = new DataSource({ - store: this.tasks - }); - - const scheduler = await createInstance({ - dataSource: data, - }); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1, 1), endDate: new Date(2015, 1, 1, 2), text: 'caption' }); - - const form = scheduler.instance.getAppointmentDetailsForm(); - const validation = sinon.stub(form, 'validate'); - - $('.dx-scheduler-legacy-appointment-popup .dx-popup-done').trigger('dxclick'); - - assert.ok(validation.calledOnce); - }); - - QUnit.test('Load panel should not be shown if validation is fail', async function(assert) { - const scheduler = await createInstance({ - dataSource: { - store: this.tasks - }, - maxAppointmentsPerCell: 2, - onAppointmentFormOpening: function(data) { - const form = data.form; - - form.option('items', [{ - name: 'description', - dataField: 'description', - editorType: 'dxTextArea', - validationRules: [{ - type: 'required', - message: 'Login is required' - }] - }]); - } - }); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1, 1), endDate: new Date(2015, 1, 1, 2), text: 'caption' }); - - scheduler.appointmentPopup.clickDoneButton(); - - assert.notOk(scheduler.appointmentPopup.hasLoadPanel()); - }); - - QUnit.test('Done button default configuration should be correct', async function(assert) { - const scheduler = await createInstance({ - onAppointmentFormOpening: function(e) { - const popup = e.component.appointmentPopup.popup; - const buttons = popup.option('toolbarItems'); - const doneButton = buttons[0]; - - assert.equal(doneButton.options.text, messageLocalization.format('Done'), 'done button text is ok'); - }, - onAppointmentAdding: function(e) { - e.cancel = true; - } - }); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1, 1), endDate: new Date(2015, 1, 1, 2), text: 'caption' }); - - scheduler.appointmentPopup.clickDoneButton(); - }); - - QUnit.test('Done button custom configuration should be correct', async function(assert) { - const scheduler = await createInstance({ - dataSource: new DataSource({ - store: this.tasks - }), - onAppointmentFormOpening: function(e) { - const popup = e.component.appointmentPopup.popup; - const buttons = popup.option('toolbarItems'); - buttons[0].options = { text: 'Text 1' }; - popup.option('toolbarItems', buttons); - }, - onAppointmentAdding: function(e) { - e.cancel = true; - } - }); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1, 1), endDate: new Date(2015, 1, 1, 2), text: 'caption' }); - - assert.notOk(scheduler.appointmentPopup.hasLoadPanel(), 'has no load panel'); - - const doneButtonInstance = scheduler.appointmentPopup.getDoneButton().dxButton('instance'); - assert.equal(doneButtonInstance.option('text'), 'Text 1', 'done button text is ok'); - - scheduler.appointmentPopup.clickDoneButton(); - - assert.notOk(scheduler.appointmentPopup.isVisible()); - }); - - QUnit.test('Load panel should be hidden if event validation fail', async function(assert) { - const scheduler = await createInstance({ - dataSource: new DataSource({ - store: this.tasks - }), - onAppointmentFormAdding: function(e) { - e.cancel = true; - } - }); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1, 1), endDate: new Date(2015, 1, 1, 2), text: 'caption' }); - - assert.notOk(scheduler.appointmentPopup.hasLoadPanel(), 'has no load panel'); - - scheduler.appointmentPopup.clickDoneButton(); - - assert.notOk(scheduler.appointmentPopup.isVisible()); - }); - - QUnit.test('Load panel should be hidden at the second appointment form opening', async function(assert) { - const task = { startDate: new Date(2017, 1, 1), endDate: new Date(2017, 1, 1, 0, 10), text: 'caption' }; - const scheduler = await createInstance({ - dataSource: [task] - }); - - scheduler.instance.showAppointmentPopup(task); - scheduler.appointmentPopup.clickDoneButton(); - - scheduler.instance.showAppointmentPopup(task); - - assert.notOk(scheduler.appointmentPopup.hasLoadPanel(), 'has no load panel'); - }); - - QUnit.test('startDateBox & endDateBox should have required validation rules', async function(assert) { - const scheduler = await createInstance({}); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1, 1), endDate: new Date(2015, 1, 1, 2), text: 'caption' }); - - const form = scheduler.instance.getAppointmentDetailsForm(); - - assert.deepEqual(form.itemOption(`${APPOINTMENT_FORM_GROUP_NAMES.Main}.startDate`).validationRules, [{ type: 'required' }]); - assert.deepEqual(form.itemOption(`${APPOINTMENT_FORM_GROUP_NAMES.Main}.endDate`).validationRules, [{ type: 'required' }]); - }); - - QUnit.test('Changes shouldn\'t be saved if form is invalid', async function(assert) { - const data = new DataSource({ - store: this.tasks - }); - - const scheduler = await createInstance({ - dataSource: data, - }); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1, 1), endDate: new Date(2015, 1, 1, 2), text: 'caption' }, true); - - const form = scheduler.instance.getAppointmentDetailsForm(); - const addingAppointment = sinon.stub(scheduler.instance, 'addAppointment'); - - sinon.stub(form, 'validate').returns({ isValid: false }); - - $('.dx-scheduler-legacy-appointment-popup .dx-popup-done').trigger('dxclick'); - - assert.notOk(addingAppointment.calledOnce); - }); - - QUnit.test('Appointment popup should contain resources and recurrence editor', async function(assert) { - const rooms = [ - { - text: 'Room Test', - id: 4, - }]; - - const scheduler = await createInstance({ - resources: [{ label: 'Room', fieldExpr: 'roomId', dataSource: rooms }], - }); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1), endDate: new Date(2015, 1, 2), roomId: 4, recurrenceRule: 'FREQ=WEEKLY' }); - $('.dx-dialog-buttons .dx-button').eq(0).trigger('dxclick'); - const form = scheduler.instance.getAppointmentDetailsForm(); - const items = form.option('items'); - - assert.equal(items.length, 2, 'Main group and recurrence editor added'); - assert.equal(items[0].items.length, 7, 'Count of editors with resources is correct'); - assert.equal(items[0].items[6].label.text, 'Room', 'Recources is the last element in the main group of editors'); - }); -}); - -QUnit.module('Appointment Popup', moduleOptions, () => { - QUnit.test('focus is called on popup hiding', async function(assert) { - const scheduler = await createInstance({}); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1), endDate: new Date(2015, 1, 2) }); - - const spy = sinon.spy(scheduler.instance, 'focus'); - - $('.dx-scheduler-legacy-appointment-popup .dx-overlay-content .dx-popup-cancel').trigger('dxclick'); - - assert.ok(spy.calledOnce, 'focus is called'); - }); - - QUnit.test('Multiple showing appointment popup for recurrence appointments should work correctly', async function(assert) { - const scheduler = await createInstance({}); - - scheduler.instance.showAppointmentPopup({ - text: 'Appointment 1', - startDate: new Date(2017, 4, 1, 9, 30), - endDate: new Date(2017, 4, 1, 11) - }); - - scheduler.instance.hideAppointmentPopup(true); - scheduler.instance.option('recurrenceEditMode', 'series'); - - scheduler.instance.showAppointmentPopup({ - text: 'Appointment 2', - startDate: new Date(2017, 4, 1, 9, 30), - endDate: new Date(2017, 4, 1, 11), - recurrenceRule: 'FREQ=WEEKLY;BYDAY=MO,TH;COUNT=10' - }); - - const popup = scheduler.instance.appointmentPopup.popup; - const $buttonGroup = $(popup.$content()).find('.dx-buttongroup'); - - assert.deepEqual($buttonGroup.eq(0).dxButtonGroup('instance').option('selectedItemKeys'), ['MO', 'TH'], 'Right buttons was checked'); - }); - - QUnit.test('Appointment popup will render even if no appointmentData is provided (T734413)', async function(assert) { - const currentDate = new Date(2020, 2, 4); - const cellDuration = 60; - - const scheduler = await createInstance({ - currentDate, - cellDuration, - }); - - scheduler.instance.showAppointmentPopup({}, true); - scheduler.instance.hideAppointmentPopup(true); - scheduler.instance.showAppointmentPopup({}, true); - const { startDate, endDate } = scheduler.appointmentForm.getFormInstance().option('formData'); - const appointmentPopup = scheduler.appointmentPopup; - - assert.equal(startDate.getTime(), currentDate.getTime(), 'startDate is currentDate in Appointment Form'); - assert.equal(endDate.getTime(), new Date(currentDate.getTime() + cellDuration * toMs('minute')).getTime(), 'endDate is currentDate + cellDuration in Appointment Form'); - assert.ok(appointmentPopup.isVisible(), 'Popup is rendered'); - - const $popup = appointmentPopup.getPopup(); - const $startDate = $popup.find('input[name=\'startDate\']')[0]; - const $endDate = $popup.find('input[name=\'endDate\']')[0]; - - assert.equal($startDate.value, '2020-03-04T00:00:00', 'startDate is specified'); - assert.equal($endDate.value, '2020-03-04T01:00:00', 'endDate is specified'); - }); - - QUnit.test('Appointment popup will render with currentDate on showAppointmentPopup with no arguments', async function(assert) { - const currentDate = new Date(2020, 2, 4); - const cellDuration = 60; - - const scheduler = await createInstance({ - currentDate, - cellDuration, - }); - - scheduler.instance.showAppointmentPopup(); - - const { startDate, endDate } = scheduler.appointmentForm.getFormInstance().option('formData'); - const appointmentPopup = scheduler.appointmentPopup; - - assert.equal(startDate.getTime(), currentDate.getTime(), 'startDate is currentDate in Appointment Form'); - assert.equal(endDate.getTime(), new Date(currentDate.getTime() + cellDuration * toMs('minute')).getTime(), 'endDate is currentDate + cellDuration in Appointment Form'); - assert.ok(appointmentPopup.isVisible(), 'Popup is rendered'); - - const $popup = appointmentPopup.getPopup(); - const $startDate = $popup.find('input[name=\'startDate\']')[0]; - const $endDate = $popup.find('input[name=\'endDate\']')[0]; - - assert.equal($startDate.value, '2020-03-04T00:00:00', 'startDate is specified'); - assert.equal($endDate.value, '2020-03-04T01:00:00', 'endDate is specified'); - }); - - QUnit.test('Appointment form will have right dates on multiple openings (T727713)', async function(assert) { - const appointments = [ - { - text: 'Appointment1', - startDate: new Date(2017, 4, 2, 8, 30), - endDate: new Date(2017, 4, 2, 11), - }, { - text: 'Appointment2', - startDate: new Date(2017, 4, 1, 10), - endDate: new Date(2017, 4, 1, 11), - } - ]; - - const scheduler = await createInstance({ - dataSource: appointments, - currentView: 'week', - views: ['week'], - currentDate: new Date(2017, 4, 1), - }); - - scheduler.instance.option(); - scheduler.instance.showAppointmentPopup(appointments[1], false); - let formData = scheduler.appointmentForm.getFormInstance().option('formData'); - - assert.deepEqual(formData.startDate, appointments[1].startDate, 'First opening appointment form has right startDate'); - assert.deepEqual(formData.endDate, appointments[1].endDate, 'First opening appointment form has right endDate'); - - scheduler.instance.hideAppointmentPopup(); - - const form = scheduler.instance.getAppointmentDetailsForm(); - let formDataChangedCount = 0; - form.option('onOptionChanged', (args) => { - if(args.name === 'formData') formDataChangedCount++; - }); - - scheduler.appointments.dblclick(1); - formData = scheduler.appointmentForm.getFormInstance().option('formData'); - - assert.deepEqual(formData.startDate, appointments[0].startDate, 'Second opening appointment form has right startDate'); - assert.deepEqual(formData.endDate, appointments[0].endDate, 'Second opening appointment form has right endDate'); - assert.equal(formDataChangedCount, 1, 'Form data changed one time'); - }); - - QUnit.test('The vertical scroll bar is shown when an appointment popup fill to a small window\'s height', async function(assert) { - const scheduler = await createInstance({ - currentDate: new Date(2015, 1, 1), - currentView: 'day', - dataSource: [] - }); - - scheduler.instance.showAddAppointmentPopup({ - startDate: new Date(2015, 1, 1), - endDate: new Date(2015, 1, 1, 1), - allDay: true - }); - - const popup = scheduler.appointmentPopup; - popup.setPopupHeight(300); - - assert.ok(popup.hasVerticalScroll(), 'The popup has the vertical scrolling'); - }); - - QUnit.test('The resize event of appointment popup is triggered the the window is resize', async function(assert) { - const scheduler = await createInstance({ - currentDate: new Date(2015, 1, 1), - currentView: 'day', - dataSource: [] - }); - - scheduler.instance.showAddAppointmentPopup({ - startDate: new Date(2015, 1, 1), - endDate: new Date(2015, 1, 1, 1), - allDay: true - }); - - const $popup = scheduler.appointmentPopup.getPopupInstance().$element(); - let isResizeEventTriggered; - $($popup).on('dxresize', () => { - isResizeEventTriggered = true; - }); - resizeCallbacks.fire(); - assert.ok(isResizeEventTriggered, 'The resize event of popup is triggered'); - }); - - QUnit.test('Popup should not be closed until the valid value is typed', async function(assert) { - const startDate = new Date(2015, 1, 1, 1); - const validValue = 'Test'; - const done = assert.async(); - const scheduler = await createInstance({ - onAppointmentFormOpening: function(data) { - const items = data.form.option('items'); - items[0].items[0].validationRules = [ - { - type: 'async', - validationCallback: function(params) { - const d = $.Deferred(); - setTimeout(function() { - d.resolve(params.value === validValue); - }, 10); - return d.promise(); - } - } - ]; - - data.form.option('items', items); - } - }); - - scheduler.instance.showAppointmentPopup({ - startDate: startDate, - endDate: new Date(2015, 1, 1, 2), - text: 'caption' - }); - - scheduler.appointmentForm.setSubject('caption1'); - const firstSavePromise = scheduler.appointmentPopup.saveAppointmentData(); - - firstSavePromise.done(async() => { - assert.equal(scheduler.appointmentForm.getInvalidEditorsCount.call(scheduler), 1, 'the only invalid editor is displayed in the form'); - - scheduler.appointmentForm.setSubject(validValue); - await waitAsync(20); - const secondSavePromise = scheduler.appointmentPopup.saveAppointmentData(); - await waitAsync(20); - - secondSavePromise.done(() => { - assert.notOk(scheduler.appointmentPopup.getPopupInstance().option('visible'), 'the form is closed'); - - done(); - }); - }); - - assert.equal(scheduler.appointmentForm.getPendingEditorsCount.call(scheduler), 1, 'the only pending editor is displayed in the form'); - }); - - const performanceTest = QUnit.isInShadowDomMode() || browser.mozilla - ? QUnit.test.skip - : QUnit.test; - - performanceTest('Appointment popup opening performance should be ok', async function(assert) { - const maxOpeningTime = 250; - let resolvePopupShown = null; - const popupShownPromise = new Promise((resolve) => { resolvePopupShown = resolve; }); - - const scheduler = await createInstance({ - currentDate: new Date(2015, 1, 1, 1), - onAppointmentFormOpening: function(e) { - e.popup.option('onShown', () => { - resolvePopupShown(performance.now()); - }); - } - }); - await timezoneUtils.cacheTimeZones(); - - const startTime = performance.now(); - - scheduler.instance.showAppointmentPopup({ - startDate: new Date(2025, 1, 1, 1), - endDate: new Date(2025, 1, 1, 2), - text: 'caption' - }); - - const endTime = await popupShownPromise; - const openingTime = endTime - startTime; - - assert.ok(openingTime <= maxOpeningTime, `popup opening time greater than ${maxOpeningTime} ms`); - }); -}); - -module('Timezone Editors', moduleOptions, () => { - test('Popup should not contain startDateTimeZone editor by default', async function(assert) { - const scheduler = await createInstance(); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1, 1), endDate: new Date(2015, 1, 1, 2), text: 'caption', description: 'First task of this day', allDay: true }); - - const form = scheduler.instance.getAppointmentDetailsForm(); - const startDateTimezoneEditor = form.getEditor('startDateTimeZone'); - - assert.notOk(startDateTimezoneEditor, 'StartDateTZ editor isn\'t visible by default'); - }); - - test('Popup should not contain endDateTimeZone editor by default', async function(assert) { - const scheduler = await createInstance(); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1, 1), endDate: new Date(2015, 1, 1, 2), text: 'caption', description: 'First task of this day', allDay: true }); - - const form = scheduler.instance.getAppointmentDetailsForm(); - const endDateTimeZoneEditor = form.getEditor('endDateTimeZone'); - - assert.notOk(endDateTimeZoneEditor, 'EndDateTZ editor isn\'t visible by default'); - }); - - test('It should be possible to render startDateTimeZone editor on appt form', async function(assert) { - const scheduler = await createInstance({ - onAppointmentFormOpening: function(e) { - e.form.itemOption(`${APPOINTMENT_FORM_GROUP_NAMES.Main}.startDateTimeZone`, { visible: true }); - }, - }); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1, 1), endDate: new Date(2015, 1, 1, 2), text: 'caption', description: 'First task of this day', allDay: true }); - - const form = scheduler.instance.getAppointmentDetailsForm(); - const startDateTimezoneEditor = form.getEditor('startDateTimeZone'); - - assert.ok(startDateTimezoneEditor instanceof SelectBox, 'Editor is SelectBox'); - assert.equal(startDateTimezoneEditor.option('value'), null, 'Value is correct'); - }); - - test('It should be possible to render endDateTimeZone editor on appt form', async function(assert) { - const scheduler = await createInstance({ - onAppointmentFormOpening: function(e) { - e.form.itemOption(`${APPOINTMENT_FORM_GROUP_NAMES.Main}.endDateTimeZone`, { visible: true }); - }, - }); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1, 1), endDate: new Date(2015, 1, 1, 2), text: 'caption', description: 'First task of this day', allDay: true }); - - const form = scheduler.instance.getAppointmentDetailsForm(); - const endDateTimezoneEditor = form.getEditor('endDateTimeZone'); - - assert.ok(endDateTimezoneEditor instanceof SelectBox, 'Editor is SelectBox'); - assert.equal(endDateTimezoneEditor.option('value'), null, 'Value is correct'); - }); - - test('timeZone editors should have correct options', async function(assert) { - const scheduler = await createInstance({ - onAppointmentFormOpening: function(e) { - e.form.itemOption(`${APPOINTMENT_FORM_GROUP_NAMES.Main}.startDateTimeZone`, { visible: true }); - e.form.itemOption(`${APPOINTMENT_FORM_GROUP_NAMES.Main}.endDateTimeZone`, { visible: true }); - }, - }); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2015, 1, 1, 1), endDate: new Date(2015, 1, 1, 2), text: 'caption', description: 'First task of this day', allDay: true }); - - const form = scheduler.instance.getAppointmentDetailsForm(); - const startDateTimezoneEditor = form.getEditor('startDateTimeZone'); - const endDateTimezoneEditor = form.getEditor('startDateTimeZone'); - - [startDateTimezoneEditor, endDateTimezoneEditor].forEach(editor => { - assert.equal(editor.option('displayExpr'), 'title', 'displayExpr is correct'); - assert.equal(editor.option('valueExpr'), 'id', 'valueExpr is correct'); - assert.strictEqual(editor.option('searchEnabled'), true, 'searchEnabled is correct'); - assert.equal(editor.option('placeholder'), 'No timezone', 'placeholder is correct'); - - assert.ok(editor.option('dataSource') instanceof DataSource, 'editor has dataSource'); - assert.equal(editor.option('dataSource')._paginate, true, 'paging is enabled'); - assert.equal(editor.option('dataSource')._pageSize, 10, 'pageSize is correct'); - }); - }); - - QUnit.test('timeZone editors should have correct value & display value on init', async function(assert) { - const scheduler = await createInstance({ - editing: { - allowTimeZoneEditing: true, - }, - }); - await timezoneUtils.cacheTimeZones(); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2020, 1, 1, 1), startDateTimeZone: 'Europe/Paris', endDate: new Date(2020, 1, 1, 2), text: 'test_text' }); - - const form = scheduler.instance.getAppointmentDetailsForm(); - const startDateTimezoneEditor = form.getEditor('startDateTimeZone'); - const endDateTimezoneEditor = form.getEditor('startDateTimeZone'); - - [startDateTimezoneEditor, endDateTimezoneEditor].forEach(editor => { - assert.equal(editor.option('value'), 'Europe/Paris', 'value is ok'); - assert.ok(editor.option('displayValue').endsWith('Europe - Paris'), 'displayValue is ok'); - }); - }); - - QUnit.test('timeZone editor should have correct display value for timezones with different offsets ', async function(assert) { - const scheduler = await createInstance({ - editing: { - allowTimeZoneEditing: true, - }, - }); - await timezoneUtils.cacheTimeZones(); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2020, 1, 1, 1), endDate: new Date(2020, 1, 1, 2), text: 'test_text' }); - - const form = scheduler.instance.getAppointmentDetailsForm(); - const startDateTimezoneEditor = form.getEditor('startDateTimeZone'); - - startDateTimezoneEditor.option('value', 'Etc/UTC'); - assert.ok(startDateTimezoneEditor.option('displayValue').endsWith('Etc - UTC'), 'displayValue is ok'); - startDateTimezoneEditor.option('value', 'America/Los_Angeles'); - assert.ok(startDateTimezoneEditor.option('displayValue').endsWith('America - Los Angeles'), 'displayValue is ok'); - }); - - QUnit.test('dataSource of timezoneEditor should be filtered', async function(assert) { - const scheduler = await createInstance({ - editing: { - allowTimeZoneEditing: true, - }, - onAppointmentFormOpening: function(e) { - const startDateTimezoneEditor = e.form.getEditor('startDateTimeZone'); - const dataSource = startDateTimezoneEditor.option('dataSource'); - dataSource.paginate(false); - dataSource.filter(['id', 'contains', 'Pacific']); - startDateTimezoneEditor.option('opened', true); - } - }); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2020, 1, 1, 1), endDate: new Date(2020, 1, 1, 2), text: 'test_text' }); - - const form = scheduler.instance.getAppointmentDetailsForm(); - const startDateTimezoneEditor = form.getEditor('startDateTimeZone'); - const expectedItemCount = 45; // US/Pacific-New is excluded - assert.equal(startDateTimezoneEditor.option('items').length, expectedItemCount, 'Items are filtered'); - - }); - - test('startDateTimeZone and endDateTimeZone editor should be rendered with allowTimeZoneEditing option', async function(assert) { - const scheduler = await createInstance({ - editing: { - allowTimeZoneEditing: true, - }, - }); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2020, 1, 1, 1), endDate: new Date(2020, 1, 1, 2), text: 'test_text' }); - - const form = scheduler.instance.getAppointmentDetailsForm(); - const startDateTimezoneEditor = form.getEditor('startDateTimeZone'); - const endDateTimezoneEditor = form.getEditor('endDateTimeZone'); - - assert.ok(startDateTimezoneEditor.option('visible'), 'startDateTimeZone editor is visible'); - assert.ok(endDateTimezoneEditor.option('visible'), 'endDateTimeZone editor is visible'); - - assert.equal(startDateTimezoneEditor.option('value'), null, 'startDateTimeZone editor value should be null'); - assert.equal(endDateTimezoneEditor.option('value'), null, 'endDateTimeZone editor value should be null'); - }); - - test('Change value in startDateTimeZone editor should trigger change value in endDateTimeZone editor if allowTimeZoneEditing: true', async function(assert) { - const scheduler = await createInstance({ - editing: { - allowTimeZoneEditing: true, - }, - }); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2020, 1, 1, 1), endDate: new Date(2020, 1, 1, 2), text: 'test_text' }); - - const form = scheduler.instance.getAppointmentDetailsForm(); - const startDateTimezoneEditor = form.getEditor('startDateTimeZone'); - const endDateTimezoneEditor = form.getEditor('endDateTimeZone'); - - startDateTimezoneEditor.option('value', 'Africa/Cairo'); - - assert.equal(startDateTimezoneEditor.option('value'), 'Africa/Cairo', 'startDateTimeZone editor value should be "Africa/Cairo"'); - assert.equal(endDateTimezoneEditor.option('value'), 'Africa/Cairo', 'endDateTimeZone editor value should be "Africa/Cairo"'); - }); - - test('Change value in endDateTimeZone editor shouldn\'t trigger change value in startDateTimeZone editor if allowTimeZoneEditing: true', async function(assert) { - const scheduler = await createInstance({ - editing: { - allowTimeZoneEditing: true, - }, - }); - - scheduler.instance.showAppointmentPopup({ startDate: new Date(2020, 1, 1, 1), endDate: new Date(2020, 1, 1, 2), text: 'test_text' }); - - const form = scheduler.instance.getAppointmentDetailsForm(); - const startDateTimezoneEditor = form.getEditor('startDateTimeZone'); - const endDateTimezoneEditor = form.getEditor('endDateTimeZone'); - - startDateTimezoneEditor.option('value', 'Asia/Pyongyang'); - endDateTimezoneEditor.option('value', 'Africa/Cairo'); - - assert.equal(startDateTimezoneEditor.option('value'), 'Asia/Pyongyang', 'startDateTimeZone editor value should be "Africa/Cairo"'); - assert.equal(endDateTimezoneEditor.option('value'), 'Africa/Cairo', 'endDateTimeZone editor value should be "Africa/Cairo"'); - }); -}); diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/timezones.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/timezones.tests.js index 34f423f315b1..d5d612a56b18 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/timezones.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/timezones.tests.js @@ -95,129 +95,6 @@ const createScheduler = (options = {}) => { module('Common', moduleConfig, () => { if(isDesktopEnvironment()) { module('Appointments rendering when appointment timeZone is set', () => { - const cases = [{ - caseName: 'startDateTimeZone = endDateTimezone', - appointment: { - startDate: new Date(2020, 1, 4, 5).toString(), - startDateTimeZone: timeZones.Yekaterinburg, - endDateTimeZone: timeZones.Yekaterinburg, - endDate: new Date(2020, 1, 4, 6).toString(), - }, - expectedContent: `${dateLocalization.format(new Date(2020, 1, 4, 5), 'shorttime')} - ${dateLocalization.format(new Date(2020, 1, 4, 6), 'shorttime')}`, - expectedPosition: { - top: 380, - left: 0 - }, - expectedPopupDates: { - startDate: '2/4/2020, 7:00 AM', - endDate: '2/4/2020, 8:00 AM' - }, - expectedHeight: 100, - stubClientTimeZone: true - }, - { - caseName: 'startDateTimeZone != endDateTimezone', - appointment: { - startDate: new Date(2020, 1, 4, 5).toString(), - startDateTimeZone: timeZones.Moscow, - endDateTimeZone: timeZones.Yekaterinburg, - endDate: new Date(2020, 1, 4, 6).toString() - }, - expectedContent: `${dateLocalization.format(new Date(2020, 1, 4, 5), 'shorttime')} - ${dateLocalization.format(new Date(2020, 1, 4, 6), 'shorttime')}`, - expectedPosition: { - top: 380, - left: 0 - }, - expectedPopupDates: { - startDate: '2/4/2020, 5:00 AM', - endDate: '2/4/2020, 8:00 AM' - }, - expectedHeight: 100, - stubClientTimeZone: true - }, - { - caseName: 'startDateTimeZone = endDateTimezone and scheduler timeZone is set', - appointment: { - startDate: new Date('2020-02-04T14:00:00.000Z'), - endDate: new Date('2020-02-04T15:00:00.000Z'), - startDateTimeZone: 'Africa/Algiers', - endDateTimeZone: 'Africa/Algiers' - }, - schedulerTimeZone: timeZones.Yekaterinburg, - expectedContent: '7:00 PM - 8:00 PM', - expectedPosition: { - top: 1444, - left: 0 - }, - expectedPopupDates: { - startDate: '2/4/2020, 3:00 PM', - endDate: '2/4/2020, 4:00 PM' - }, - expectedHeight: 100, - stubClientTimeZone: false - }, - { - caseName: 'startDateTimeZone != endDateTimezone and scheduler timeZone is set', - appointment: { - startDate: new Date('2020-02-04T14:00:00.000Z'), - endDate: new Date('2020-02-04T15:00:00.000Z'), - startDateTimeZone: 'Africa/Algiers', - endDateTimeZone: 'Africa/Cairo' - }, - schedulerTimeZone: timeZones.Yekaterinburg, - expectedContent: '7:00 PM - 8:00 PM', - expectedPosition: { - top: 1444, - left: 0 - }, - expectedPopupDates: { - startDate: '2/4/2020, 3:00 PM', - endDate: '2/4/2020, 5:00 PM' - }, - expectedHeight: 100, - stubClientTimeZone: false - }]; - - const runTest = async(config, assert) => { - const scheduler = await createWrapper({ - currentDate: new Date(2020, 1, 4), - views: ['day'], - currentView: 'day', - firstDayOfWeek: 1, - dataSource: [config.appointment], - timeZone: config.schedulerTimeZone, - editing: config.editing, - }); - - assert.equal(scheduler.appointments.getDateText(), config.expectedContent, 'Appointment content has correct dates'); - assert.deepEqual(scheduler.appointments.getAppointmentPosition(), config.expectedPosition, 'Appointment is rendered in right cell'); - - scheduler.appointments.dblclick(0); - const form = scheduler.instance.getAppointmentDetailsForm(); - const startDateBox = form.getEditor('startDate'); - const endDateBox = form.getEditor('endDate'); - - assert.equal(startDateBox.option('text'), config.expectedPopupDates.startDate, 'Appointment popup has right startDate'); - assert.equal(endDateBox.option('text'), config.expectedPopupDates.endDate, 'Appointment popup has right endDate'); - }; - - cases.forEach(config => { - test(`Appointment should have correct size, position and popup content if ${config.caseName}`, async function(assert) { - const schedulerOptions = { ...config, editing: { legacyForm: true } }; - - if(config.stubClientTimeZone) { - const tzOffsetStub = sinon.stub(timeZoneUtils, 'getClientTimezoneOffset').returns(-10800000); - try { - await runTest(schedulerOptions, assert); - } finally { - tzOffsetStub.restore(); - } - } else { - await runTest(schedulerOptions, assert); - } - }); - }); - test('Appointments should be filtered correctly when remoteFiltering is enabled', async function(assert) { const dataSource = new DataSource({ store: new ArrayStore({ @@ -311,7 +188,6 @@ module('Common', moduleConfig, () => { allowTimeZoneEditing: true, allowAdding: true, allowUpdating: true, - legacyForm: true, }, height: 600, appointmentDragging: { @@ -319,8 +195,8 @@ module('Common', moduleConfig, () => { onAdd: e => { e.component.showAppointmentPopup(e.itemData, true); - const startDate = scheduler.appointmentForm.getEditor('startDate').option('value'); - const endDate = scheduler.appointmentForm.getEditor('endDate').option('value'); + const startDate = scheduler.appointmentForm.getEditor('startDateEditor').option('value'); + const endDate = scheduler.appointmentForm.getEditor('endDateEditor').option('value'); assert.equal(startDate.valueOf(), expectedStartDate.valueOf(), 'start date should be equal with date from grid - 5/22/2017 2:00 AM'); assert.equal(endDate.valueOf(), expectedEndDate.valueOf(), 'start date should be equal with date from grid - 5/22/2017 2:30 AM'); @@ -423,7 +299,7 @@ module('API', moduleConfig, () => { assert.ok(updateAppointment.calledOnce, 'Update method is called'); assert.deepEqual(updateAppointment.getCall(0).args[0], updatedItem, 'Target item is correct'); - assert.deepEqual(updateAppointment.getCall(0).args[1], updatedItem, 'New data is correct'); + assert.deepEqual(updateAppointment.getCall(0).args[1], { ...updatedItem, allDay: false, recurrenceRule: '' }, 'New data is correct'); } finally { updateAppointment.restore(); } @@ -1782,13 +1658,13 @@ module('Appointment popup', moduleConfig, () => { cases.forEach((testCase, index) => { test('StartDate and endDate should be valid', async function(assert) { - const scheduler = await createScheduler({ timeZone: timeZones.NewYork, editing: { legacyForm: true } }); // -4 offset + const scheduler = await createScheduler({ timeZone: timeZones.NewYork, }); // -4 offset scheduler.appointments.dblclick(index); const text = scheduler.appointments.getTitleText(index); - const startDate = scheduler.appointmentForm.getEditor('startDate').option('value'); - const endDate = scheduler.appointmentForm.getEditor('endDate').option('value'); + const startDate = scheduler.appointmentForm.getEditor('startDateEditor').option('value'); + const endDate = scheduler.appointmentForm.getEditor('endDateEditor').option('value'); assert.equal(startDate.valueOf(), testCase.startDate, `StartDate of '${text}' should be valid`); assert.equal(endDate.valueOf(), testCase.endDate, `EndDate of '${text}' should be valid`); @@ -1810,13 +1686,13 @@ module('Appointment popup', moduleConfig, () => { cases.forEach((testCase, index) => { test('StartDate and endDate should be valid', async function(assert) { - const scheduler = await createScheduler({ editing: { legacyForm: true } }); + const scheduler = await createScheduler({ }); scheduler.appointments.dblclick(index); const text = scheduler.appointments.getTitleText(index); - const startDate = scheduler.appointmentForm.getEditor('startDate').option('value'); - const endDate = scheduler.appointmentForm.getEditor('endDate').option('value'); + const startDate = scheduler.appointmentForm.getEditor('startDateEditor').option('value'); + const endDate = scheduler.appointmentForm.getEditor('endDateEditor').option('value'); assert.equal(startDate.valueOf(), testCase.startDate, `StartDate of '${text}' should be valid`); assert.equal(endDate.valueOf(), testCase.endDate, `EndDate of '${text}' should be valid`); @@ -1824,65 +1700,6 @@ module('Appointment popup', moduleConfig, () => { }); }); - ['Etc/GMT-5', 'Asia/Ashkhabad'].forEach(timeZone => { - test(`Appointment startDate and endDate should be correct in the details view, if custom timeZone='${timeZone}' is setting`, - async function(assert) { - const startDate = new Date(2015, 3, 11, 11); - const endDate = new Date(2015, 3, 11, 11, 30); - - const appointment = { - text: 'Task 1', - Start: startDate, - End: endDate - }; - - const scheduler = await createWrapper({ - timeZone, - dataSource: new DataSource({ - store: [appointment] - }), - editing: { - legacyForm: true, - }, - currentDate: new Date(2015, 3, 23), - startDateExpr: 'Start', - endDateExpr: 'End' - }); - - - scheduler.instance.showAppointmentPopup(appointment); - - const detailsForm = scheduler.instance.getAppointmentDetailsForm(); - const formData = detailsForm.option('formData'); - const deltaTz = getDeltaTz(5, startDate); - - assert.deepEqual(formData.Start, new Date(startDate.getTime() + deltaTz), 'start date is correct'); - assert.deepEqual(formData.End, new Date(endDate.getTime() + deltaTz), 'end date is correct'); - }); - }); - - test('Appointment startDate and endDate should be correct in the details view for new appointment, if custom timeZone was set, legacyForm', - async function(assert) { - const scheduler = await createWrapper({ - dataSource: new DataSource({ - store: [] - }), - currentDate: new Date(2015, 3, 23), - startDateExpr: 'Start', - endDateExpr: 'End', - timeZone: 'Asia/Calcutta', - editing: { legacyForm: true } - }); - - pointerMock(scheduler.getElement().find(CLASSES.dateTableCell).eq(22)).start().click().click(); - - const detailsForm = scheduler.instance.getAppointmentDetailsForm(); - const formData = detailsForm.option('formData'); - - assert.deepEqual(formData.Start, new Date(2015, 3, 23, 11), 'start date is correct'); - assert.deepEqual(formData.End, new Date(2015, 3, 23, 11, 30), 'end date is correct'); - }); - test('Appointment date correction should be rollback after closing popup, if custom timeZone was set as string', async function(assert) { const updatedItem = { text: 'Task 1', @@ -1909,7 +1726,7 @@ module('Appointment popup', moduleConfig, () => { assert.ok(updateAppointment.calledOnce, 'Update method is called'); assert.deepEqual(updateAppointment.getCall(0).args[0], updatedItem, 'Target item is correct'); - assert.deepEqual(updateAppointment.getCall(0).args[1], updatedItem, 'New data is correct'); + assert.deepEqual(updateAppointment.getCall(0).args[1], { ...updatedItem, allDay: false, recurrenceRule: '' }, 'New data is correct'); } finally { updateAppointment.restore(); } diff --git a/packages/testcafe-models/scheduler/appointment/legacyPopup.ts b/packages/testcafe-models/scheduler/appointment/legacyPopup.ts deleted file mode 100644 index af2bf9baa31e..000000000000 --- a/packages/testcafe-models/scheduler/appointment/legacyPopup.ts +++ /dev/null @@ -1,114 +0,0 @@ -import { Selector, ClientFunction } from 'testcafe'; - -export const CLASS = { - appointmentPopup: 'dx-scheduler-legacy-appointment-popup', - popup: 'dx-popup', - popupWrapper: 'dx-popup-wrapper', - popupContent: 'dx-overlay-content', - cancelButton: 'dx-popup-cancel.dx-button', - stateInvisible: 'dx-state-invisible', - recurrenceEditor: 'dx-recurrence-editor', - textEditorInput: 'dx-texteditor-input', - overlayWrapper: 'dx-overlay-wrapper', - fullScreen: 'dx-popup-fullscreen', - switch: 'dx-switch', - // e2e - form: 'e2e-dx-scheduler-form', - textEditor: 'e2e-dx-scheduler-form-text', - descriptionEditor: 'e2e-dx-scheduler-form-description', - startDateEditor: 'e2e-dx-scheduler-form-start-date', - endDateEditor: 'e2e-dx-scheduler-form-end-date', - startDateTimeZoneEditor: 'e2e-dx-scheduler-form-start-date-timezone', - endDateTimeZoneEditor: 'e2e-dx-scheduler-form-end-date-timezone', - allDaySwitch: 'e2e-dx-scheduler-form-all-day-switch', - recurrenceSwitch: 'e2e-dx-scheduler-form-recurrence-switch', - selectItem: 'dx-list-item', - radioButton: 'dx-radiobutton', -}; -export const SELECTORS = { - textInput: `.${CLASS.textEditor} .${CLASS.textEditorInput}`, - descriptionTextArea: `.${CLASS.descriptionEditor} .${CLASS.textEditorInput}`, - startDateInput: `.${CLASS.startDateEditor} .${CLASS.textEditorInput}`, - endDateInput: `.${CLASS.endDateEditor} .${CLASS.textEditorInput}`, - startDateTimeZoneInput: `.${CLASS.startDateTimeZoneEditor} .${CLASS.textEditorInput}`, - endDateTimeZoneInput: `.${CLASS.endDateTimeZoneEditor} .${CLASS.textEditorInput}`, - allDaySwitch: `.${CLASS.allDaySwitch} .${CLASS.switch}`, - recurrenceSwitch: `.${CLASS.recurrenceSwitch} .${CLASS.switch}`, - repeatUntilInput: '.dx-recurrence-datebox-until-date input[type="text"]', - repeatCountInput: '.dx-recurrence-numberbox-repeat-count input[type="text"]', -}; - -export default class LegacyAppointmentPopup { - element = this.scheduler.find(`.${CLASS.popup}.${CLASS.appointmentPopup}`); - - form = Selector(`.${CLASS.form}`); - - wrapper = Selector(`.${CLASS.popupWrapper}.${CLASS.appointmentPopup}`); - - content = Selector(`.${CLASS.popupWrapper}.${CLASS.appointmentPopup} .${CLASS.popupContent}`); - - subjectElement = this.wrapper.find(SELECTORS.textInput); - - descriptionElement = this.wrapper.find(SELECTORS.descriptionTextArea); - - startDateElement = this.wrapper.find(SELECTORS.startDateInput); - - endDateElement = this.wrapper.find(SELECTORS.endDateInput); - - startDateTimeZoneElement = this.wrapper.find(SELECTORS.startDateTimeZoneInput); - - endDateTimeZoneElement = this.wrapper.find(SELECTORS.endDateTimeZoneInput); - - doneButton = this.wrapper.find('.dx-popup-done.dx-button'); - - cancelButton = this.wrapper.find(`.${CLASS.cancelButton}`); - - allDayElement = this.wrapper.find(SELECTORS.allDaySwitch); - - recurrenceElement = this.wrapper.find(SELECTORS.recurrenceSwitch); - - freqElement = this.wrapper.find('.dx-recurrence-selectbox-freq .dx-selectbox'); - - recurrenceTypeElement = this.wrapper.find(`.${CLASS.recurrenceEditor} .${CLASS.textEditorInput}`).nth(0); - - endRepeatDateElement = this.wrapper.find(`.${CLASS.recurrenceEditor} .${CLASS.textEditorInput}`).nth(2); - - repeatEveryElement = this.wrapper.find(`.${CLASS.recurrenceEditor} .${CLASS.textEditorInput}`).nth(1); - - fullScreen = this.wrapper.find(`.${CLASS.overlayWrapper} .${CLASS.fullScreen}`).exists; - - repeatUntilElement = this.wrapper.find(SELECTORS.repeatUntilInput); - - repeatCountElement = this.wrapper.find(SELECTORS.repeatCountInput); - - constructor(private readonly scheduler: Selector) { - } - - isVisible(): Promise { - const { element } = this; - const invisibleStateClass = CLASS.stateInvisible; - - return ClientFunction(() => !(element() as any).classList.contains(invisibleStateClass), { - dependencies: { element, invisibleStateClass }, - })(); - } - - getAllDaySwitchValue(): Promise { - return this.allDayElement.find('input[type="hidden"]').value; - } - - getRecurrenceRuleSwitchValue(): Promise { - return this.recurrenceElement.find('input[type="hidden"]').value; - } - - getRecurrenceTypeSelectItem(nth = 0): Selector { - return Selector(`.${CLASS.overlayWrapper}`) - .nth(1) - .find(`.${CLASS.selectItem}`) - .nth(nth); - } - - getEndRepeatRadioButton(nth = 0): Selector { - return this.wrapper.find(`.${CLASS.radioButton}`).nth(nth); - } -} diff --git a/packages/testcafe-models/scheduler/index.ts b/packages/testcafe-models/scheduler/index.ts index a9bfb96effb4..3431f59ff607 100644 --- a/packages/testcafe-models/scheduler/index.ts +++ b/packages/testcafe-models/scheduler/index.ts @@ -1,6 +1,5 @@ import { ClientFunction } from 'testcafe'; import Widget from '../internal/widget'; -import LegacyAppointmentPopup from './appointment/legacyPopup'; import AppointmentPopup from './appointment/popup'; import AppointmentTooltip from './appointment/tooltip'; import AppointmentDialog from './appointment/dialog'; @@ -77,8 +76,6 @@ export default class Scheduler extends Widget { readonly workSpaceScroll: { left: Promise; top: Promise }; - readonly legacyAppointmentPopup: LegacyAppointmentPopup; - readonly appointmentPopup: AppointmentPopup; readonly appointmentTooltip: AppointmentTooltip; @@ -124,7 +121,6 @@ export default class Scheduler extends Widget { top: this.workspaceScrollable.scrollTop, }; - this.legacyAppointmentPopup = new LegacyAppointmentPopup(this.element); this.appointmentPopup = new AppointmentPopup(this.element); this.appointmentTooltip = new AppointmentTooltip(this.element); this.reducedIconTooltip = new ReducedIconTooltip();