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 c1abb2a372d9..6f5313ff9856 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 @@ -14,6 +14,7 @@ import { AppointmentDataAccessor, } from '../../utils/data_accessor/appointment_data_accessor'; import type { IFieldExpr } from '../../utils/data_accessor/types'; +import type { ResourceConfig } from '../../utils/loader/types'; import { ResourceManager, } from '../../utils/resource_manager/resource_manager'; @@ -64,6 +65,7 @@ interface CreateAppointmentPopupOptions { firstDayOfWeek?: number; startDayHour?: number; timeZone?: string; + resources?: ResourceConfig[]; onAppointmentFormOpening?: (...args: unknown[]) => void; onSave?: jest.Mock<(appointment: Record) => PromiseLike>; title?: string; @@ -106,10 +108,16 @@ export const createAppointmentPopup = async ( document.body.appendChild(container); const dataAccessors = new AppointmentDataAccessor(DEFAULT_FIELDS, false); - const resourceManager = new ResourceManager([]); + const resourceManager = new ResourceManager(options.resources ?? []); const timeZoneCalculator = createTimeZoneCalculator(options.timeZone ?? NO_TIMEZONE); const editing = { ...DEFAULT_EDITING, ...options.editing }; + if (options.resources?.length) { + await Promise.all( + resourceManager.resources.map((r) => r.load()), + ); + } + const addAppointment = options.addAppointment ?? jest.fn(resolvedDeferred); const updateAppointment = options.updateAppointment @@ -187,6 +195,7 @@ export const createAppointmentPopup = async ( const dispose = (): void => { popup.dispose(); + resourceManager.dispose(); container.remove(); }; diff --git a/packages/devextreme/js/__internal/scheduler/appointment_popup/appointment_popup.integration.test.ts b/packages/devextreme/js/__internal/scheduler/appointment_popup/appointment_popup.integration.test.ts index d2b7fb7f3bd6..8529696b0cfd 100644 --- a/packages/devextreme/js/__internal/scheduler/appointment_popup/appointment_popup.integration.test.ts +++ b/packages/devextreme/js/__internal/scheduler/appointment_popup/appointment_popup.integration.test.ts @@ -4,7 +4,6 @@ import { import dateLocalization from '@js/common/core/localization/date'; import { CustomStore } from '@js/common/data/custom_store'; import $ from '@js/core/renderer'; -import type { GroupItem } from '@js/ui/form'; import type { ToolbarItem } from '@js/ui/popup'; import { toMilliseconds } from '@ts/utils/toMilliseconds'; @@ -73,151 +72,6 @@ describe('Appointment Form', () => { }); describe('Changes saving/canceling', () => { - it('should update appointment on save button click', async () => { - const { scheduler, POM } = await createScheduler({ - ...getDefaultConfig(), - dataSource: [{ ...commonAppointment }], - }); - const dataSource = (scheduler as any).getDataSource(); - const item = dataSource.items()[0]; - - scheduler.showAppointmentPopup(item); - POM.popup.setInputValue('subjectEditor', 'New Subject'); - POM.popup.saveButton.click(); - await Promise.resolve(); - - expect(dataSource.items()[0]).toMatchObject({ - ...commonAppointment, - text: 'New Subject', - }); - }); - - it('should not update appointment on cancel button click', async () => { - const { scheduler, POM } = await createScheduler({ - ...getDefaultConfig(), - dataSource: [{ ...commonAppointment }], - }); - const dataSource = (scheduler as any).getDataSource(); - const item = dataSource.items()[0]; - - scheduler.showAppointmentPopup(item); - POM.popup.setInputValue('subjectEditor', 'New Subject'); - POM.popup.cancelButton.click(); - - expect(dataSource.items()[0]).toMatchObject(commonAppointment); - }); - - it('should update recurring appointment on save button click in recurrence form', async () => { - const { scheduler, POM } = await createScheduler({ - ...getDefaultConfig(), - dataSource: [{ ...recurringAppointment }], - }); - const dataSource = (scheduler as any).getDataSource(); - const item = dataSource.items()[0]; - - scheduler.showAppointmentPopup(item); - - POM.popup.editSeriesButton.click(); - POM.popup.setInputValue('subjectEditor', 'New Subject'); - POM.popup.recurrenceSettingsButton.click(); - POM.popup.saveButton.click(); - await Promise.resolve(); - - expect(dataSource.items()[0]).toMatchObject({ - ...recurringAppointment, - text: 'New Subject', - }); - }); - - it('should not update recurring appointment on cancel button click in recurrence form', async () => { - const { scheduler, POM } = await createScheduler({ - ...getDefaultConfig(), - dataSource: [{ ...recurringAppointment }], - }); - const dataSource = (scheduler as any).getDataSource(); - const item = dataSource.items()[0]; - - scheduler.showAppointmentPopup(item); - POM.popup.editSeriesButton.click(); - POM.popup.setInputValue('subjectEditor', 'New Subject'); - POM.popup.recurrenceSettingsButton.click(); - POM.popup.cancelButton.click(); - - expect(dataSource.items()[0]).toMatchObject(recurringAppointment); - }); - - it('should update appointment recurrence rule changes on save button click', async () => { - const { scheduler, POM } = await createScheduler({ - ...getDefaultConfig(), - dataSource: [{ ...commonAppointment }], - }); - const dataSource = (scheduler as any).getDataSource(); - const item = dataSource.items()[0]; - - scheduler.showAppointmentPopup(item); - POM.popup.selectRepeatValue('daily'); - POM.popup.saveButton.click(); - await Promise.resolve(); - - expect(dataSource.items()[0]).toMatchObject({ - ...commonAppointment, - recurrenceRule: 'FREQ=DAILY', - }); - }); - - it('should not update appointment recurrence rule changes on cancel button click', async () => { - const { scheduler, POM } = await createScheduler({ - ...getDefaultConfig(), - dataSource: [{ ...commonAppointment }], - }); - const dataSource = (scheduler as any).getDataSource(); - const item = dataSource.items()[0]; - - scheduler.showAppointmentPopup(item); - POM.popup.selectRepeatValue('daily'); - POM.popup.cancelButton.click(); - - expect(dataSource.items()[0]).toMatchObject(commonAppointment); - }); - - it('should not update recurrence rule on save button click if recurrence rule was not changed', async () => { - const { scheduler, POM } = await createScheduler({ - ...getDefaultConfig(), - dataSource: [{ ...recurringAppointment }], - }); - - const dataSource = (scheduler as any).getDataSource(); - const item = dataSource.items()[0]; - - scheduler.showAppointmentPopup(item); - POM.popup.editSeriesButton.click(); - POM.popup.saveButton.click(); - await Promise.resolve(); - - expect(dataSource.items()[0]).toMatchObject(recurringAppointment); - }); - - it('should update recurrence rule on save button click if repeat editor value was set to never', async () => { - const { scheduler, POM } = await createScheduler({ - ...getDefaultConfig(), - dataSource: [{ ...recurringAppointment }], - }); - - const dataSource = (scheduler as any).getDataSource(); - const item = dataSource.items()[0]; - - scheduler.showAppointmentPopup(item); - POM.popup.editSeriesButton.click(); - POM.popup.selectRepeatValue('never'); - POM.popup.saveButton.click(); - await Promise.resolve(); - - expect(dataSource.items()[0]).toMatchObject({ - ...recurringAppointment, - recurrenceRule: '', - }); - }); - it('should update appointment when data source is a custom store', async () => { const appointment = { ...commonAppointment, id: 0 }; @@ -727,190 +581,6 @@ describe('Appointment Form', () => { jest.useRealTimers(); }); - it('should have correct resource editor value', async () => { - const { scheduler, POM } = await createScheduler({ - ...getDefaultConfig(), - dataSource: [{ - text: 'Resource test app', - startDate: new Date(2017, 4, 9, 9, 30), - endDate: new Date(2017, 4, 9, 11), - roomId: 2, - }], - resources: [{ - fieldExpr: 'roomId', - dataSource: [ - { text: 'Room 1', id: 1, color: '#00af2c' }, - { text: 'Room 2', id: 2, color: '#56ca85' }, - { text: 'Room 3', id: 3, color: '#8ecd3c' }, - ], - }], - }); - const dataSource = (scheduler as any).getDataSource(); - const item = dataSource.items()[0]; - - scheduler.showAppointmentPopup(item); - expect(POM.popup.getInputValue('roomId')).toBe('Room 2'); - }); - - it('should create resourceEditorsGroup when resources have no custom icons', async () => { - const { scheduler, POM } = await createScheduler({ - ...getDefaultConfig(), - resources: [ - { fieldExpr: 'roomId' }, - { fieldExpr: 'ownerId' }, - ], - }); - - scheduler.showAppointmentPopup(); - - const resourcesGroup = POM.popup.dxForm.itemOption('mainGroup.resourcesGroup') as GroupItem; - - expect(resourcesGroup).toBeDefined(); - expect(resourcesGroup?.items?.length).toBe(2); - - expect(resourcesGroup?.items).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - name: 'resourcesGroupIcon', - }), - expect.objectContaining({ - name: 'resourceEditorsGroup', - itemType: 'group', - items: expect.arrayContaining([ - expect.objectContaining({ - name: 'roomIdEditor', - }), - expect.objectContaining({ - name: 'ownerIdEditor', - }), - ]), - }), - ]), - ); - }); - - it('should create individual resource groups when resources have custom icons', async () => { - const { scheduler, POM } = await createScheduler({ - ...getDefaultConfig(), - resources: [ - { fieldExpr: 'roomId', icon: 'home' }, - { fieldExpr: 'ownerId', icon: 'user' }, - ], - }); - - scheduler.showAppointmentPopup(); - - const resourcesGroup = POM.popup.dxForm.itemOption('mainGroup.resourcesGroup') as GroupItem; - - expect(resourcesGroup).toBeDefined(); - expect(resourcesGroup?.items?.length).toBe(2); - - expect(resourcesGroup?.items).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - name: 'roomIdGroup', - itemType: 'group', - items: expect.arrayContaining([ - expect.objectContaining({ - name: 'roomIdIcon', - }), - expect.objectContaining({ - name: 'roomIdEditor', - }), - ]), - }), - expect.objectContaining({ - name: 'ownerIdGroup', - itemType: 'group', - items: expect.arrayContaining([ - expect.objectContaining({ - name: 'ownerIdIcon', - }), - expect.objectContaining({ - name: 'ownerIdEditor', - }), - ]), - }), - ]), - ); - }); - - it('should render FontAwesome icon with correct CSS classes (T1322161)', async () => { - const { scheduler, POM } = await createScheduler({ - ...getDefaultConfig(), - dataSource: [{ - text: 'Resource test app', - startDate: new Date(2017, 4, 9, 9, 30), - endDate: new Date(2017, 4, 9, 11), - roomId: 1, - }], - resources: [{ - fieldExpr: 'roomId', - icon: 'fas fa-home', - dataSource: [{ text: 'Room 1', id: 1 }, { text: 'Room 2', id: 2 }], - }], - }); - const dataSource = (scheduler as any).getDataSource(); - const appointment = dataSource.items()[0]; - - scheduler.showAppointmentPopup(appointment); - - const { resourceIcon } = POM.popup; - - expect(resourceIcon.classList.contains('fas')).toBe(true); - expect(resourceIcon.classList.contains('fa-home')).toBe(true); - }); - - it('should create dxTagBox for resource with multiple selection', async () => { - const { scheduler, POM } = await createScheduler({ - ...getDefaultConfig(), - dataSource: [{ - text: 'Resource test app', - startDate: new Date(2017, 4, 9, 9, 30), - endDate: new Date(2017, 4, 9, 11), - ownerId: [1, 2], - }], - resources: [{ - fieldExpr: 'ownerId', - allowMultiple: true, - dataSource: [{ text: 'Owner 1', id: 1 }, { text: 'Owner 2', id: 2 }, { text: 'Owner 3', id: 3 }], - }], - }); - const dataSource = (scheduler as any).getDataSource(); - const appointment = dataSource.items()[0]; - - scheduler.showAppointmentPopup(appointment); - - const resourceEditor = POM.popup.dxForm.getEditor('ownerId') as any; - expect(resourceEditor.NAME).toBe('dxTagBox'); - expect(resourceEditor.option('value')).toEqual([1, 2]); - }); - - it('should create dxSelectBox for resource with single selection', async () => { - const { scheduler, POM } = await createScheduler({ - ...getDefaultConfig(), - dataSource: [{ - text: 'Resource test app', - startDate: new Date(2017, 4, 9, 9, 30), - endDate: new Date(2017, 4, 9, 11), - ownerId: 2, - }], - resources: [{ - fieldExpr: 'ownerId', - allowMultiple: false, - dataSource: [{ text: 'Owner 1', id: 1 }, { text: 'Owner 2', id: 2 }, { text: 'Owner 3', id: 3 }], - }], - }); - const dataSource = (scheduler as any).getDataSource(); - const appointment = dataSource.items()[0]; - - scheduler.showAppointmentPopup(appointment); - - const resourceEditor = POM.popup.dxForm.getEditor('ownerId') as any; - expect(resourceEditor.NAME).toBe('dxSelectBox'); - expect(resourceEditor.option('value')).toEqual(2); - }); - it('should load resource dataSource only once', async () => { const resourceDataSource = new CustomStore({ load: () => [ @@ -1029,15 +699,6 @@ describe('Appointment Form', () => { describe('Icons', () => { describe('Subject icon', () => { - it('has default color when appointment has no resources', async () => { - const { scheduler, POM } = await createScheduler(getDefaultConfig()); - - scheduler.showAppointmentPopup(commonAppointment); - - const $icon = $(POM.popup.subjectIcon); - expect($icon.css('color')).toBe(''); - }); - it('has default color when showAppointmentPopup is called without data', async () => { const { scheduler, POM } = await createScheduler(getDefaultConfig()); @@ -1046,35 +707,6 @@ describe('Appointment Form', () => { const $icon = $(POM.popup.subjectIcon); expect($icon.css('color')).toBe(''); }); - - it('has resource color when appointment has resource', async () => { - const resourceColor1 = 'rgb(255, 0, 0)'; - const resourceColor2 = 'rgb(0, 0, 255)'; - const { scheduler, POM } = await createScheduler({ - ...getDefaultConfig(), - resources: [{ - fieldExpr: 'roomId', - dataSource: [ - { id: 1, text: 'Room 1', color: resourceColor1 }, - { id: 2, text: 'Room 2', color: resourceColor2 }, - ], - }], - }); - - scheduler.showAppointmentPopup({ - ...commonAppointment, - roomId: 1, - }); - await new Promise(process.nextTick); - - const $icon = $(POM.popup.subjectIcon); - expect($icon.css('color')).toBe(resourceColor1); - - POM.popup.setInputValue('roomId', 2); - await new Promise(process.nextTick); - - expect($icon.css('color')).toBe(resourceColor2); - }); }); describe('Resource icons', () => { diff --git a/packages/devextreme/js/__internal/scheduler/appointment_popup/appointment_popup.test.ts b/packages/devextreme/js/__internal/scheduler/appointment_popup/appointment_popup.test.ts index 4d93cde96b41..0e720c33c8a8 100644 --- a/packages/devextreme/js/__internal/scheduler/appointment_popup/appointment_popup.test.ts +++ b/packages/devextreme/js/__internal/scheduler/appointment_popup/appointment_popup.test.ts @@ -938,4 +938,349 @@ describe('Isolated AppointmentPopup environment', () => { expect(POM.isRecurrenceGroupVisible()).toBe(true); }); }); + + describe('Resources', () => { + it('should create resourceEditorsGroup when resources have no custom icons', async () => { + const { POM } = await createAppointmentPopup({ + resources: [ + { fieldExpr: 'roomId' }, + { fieldExpr: 'ownerId' }, + ], + }); + + const resourcesGroup = POM.dxForm.itemOption('mainGroup.resourcesGroup') as GroupItem; + + expect(resourcesGroup).toBeDefined(); + expect(resourcesGroup?.items?.length).toBe(2); + expect(resourcesGroup?.items).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + name: 'resourcesGroupIcon', + }), + expect.objectContaining({ + name: 'resourceEditorsGroup', + itemType: 'group', + items: expect.arrayContaining([ + expect.objectContaining({ name: 'roomIdEditor' }), + expect.objectContaining({ name: 'ownerIdEditor' }), + ]), + }), + ]), + ); + }); + + it('should create individual resource groups when resources have custom icons', async () => { + const { POM } = await createAppointmentPopup({ + resources: [ + { fieldExpr: 'roomId', icon: 'home' }, + { fieldExpr: 'ownerId', icon: 'user' }, + ], + }); + + const resourcesGroup = POM.dxForm.itemOption('mainGroup.resourcesGroup') as GroupItem; + + expect(resourcesGroup).toBeDefined(); + expect(resourcesGroup?.items?.length).toBe(2); + expect(resourcesGroup?.items).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + name: 'roomIdGroup', + itemType: 'group', + items: expect.arrayContaining([ + expect.objectContaining({ name: 'roomIdIcon' }), + expect.objectContaining({ name: 'roomIdEditor' }), + ]), + }), + expect.objectContaining({ + name: 'ownerIdGroup', + itemType: 'group', + items: expect.arrayContaining([ + expect.objectContaining({ name: 'ownerIdIcon' }), + expect.objectContaining({ name: 'ownerIdEditor' }), + ]), + }), + ]), + ); + }); + + it('should render FontAwesome icon with correct CSS classes (T1322161)', async () => { + const { POM } = await createAppointmentPopup({ + appointmentData: { + text: 'Resource test app', + startDate: new Date(2017, 4, 9, 9, 30), + endDate: new Date(2017, 4, 9, 11), + roomId: 1, + }, + resources: [{ + fieldExpr: 'roomId', + icon: 'fas fa-home', + dataSource: [{ text: 'Room 1', id: 1 }, { text: 'Room 2', id: 2 }], + }], + }); + + const { resourceIcon } = POM; + + expect(resourceIcon.classList.contains('fas')).toBe(true); + expect(resourceIcon.classList.contains('fa-home')).toBe(true); + }); + + it('should create dxTagBox for resource with multiple selection', async () => { + const { POM } = await createAppointmentPopup({ + appointmentData: { + text: 'Resource test app', + startDate: new Date(2017, 4, 9, 9, 30), + endDate: new Date(2017, 4, 9, 11), + ownerId: [1, 2], + }, + resources: [{ + fieldExpr: 'ownerId', + allowMultiple: true, + dataSource: [ + { text: 'Owner 1', id: 1 }, + { text: 'Owner 2', id: 2 }, + { text: 'Owner 3', id: 3 }, + ], + }], + }); + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const resourceEditor = POM.dxForm.getEditor('ownerId') as any; + expect(resourceEditor.NAME).toBe('dxTagBox'); + expect(resourceEditor.option('value')).toEqual([1, 2]); + }); + + it('should create dxSelectBox for resource with single selection', async () => { + const { POM } = await createAppointmentPopup({ + appointmentData: { + text: 'Resource test app', + startDate: new Date(2017, 4, 9, 9, 30), + endDate: new Date(2017, 4, 9, 11), + ownerId: 2, + }, + resources: [{ + fieldExpr: 'ownerId', + allowMultiple: false, + dataSource: [ + { text: 'Owner 1', id: 1 }, + { text: 'Owner 2', id: 2 }, + { text: 'Owner 3', id: 3 }, + ], + }], + }); + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const resourceEditor = POM.dxForm.getEditor('ownerId') as any; + expect(resourceEditor.NAME).toBe('dxSelectBox'); + expect(resourceEditor.option('value')).toEqual(2); + }); + }); + + describe('Icons', () => { + describe('Subject icon', () => { + it('has default color when appointment has no resources', async () => { + const { POM } = await createAppointmentPopup({ + appointmentData: { + text: 'common-app', + startDate: new Date(2017, 4, 9, 9, 30), + endDate: new Date(2017, 4, 9, 11), + }, + }); + + expect(POM.subjectIcon.style.color).toBe(''); + }); + + it('has resource color when appointment has resource', async () => { + const resourceColor1 = 'rgb(255, 0, 0)'; + const resourceColor2 = 'rgb(0, 0, 255)'; + + const { POM } = await createAppointmentPopup({ + appointmentData: { + text: 'common-app', + startDate: new Date(2017, 4, 9, 9, 30), + endDate: new Date(2017, 4, 9, 11), + roomId: 1, + }, + resources: [{ + fieldExpr: 'roomId', + dataSource: [ + { id: 1, text: 'Room 1', color: resourceColor1 }, + { id: 2, text: 'Room 2', color: resourceColor2 }, + ], + }], + }); + await new Promise(process.nextTick); + + expect(POM.subjectIcon.style.color).toBe(resourceColor1); + + POM.setInputValue('roomId', 2); + await new Promise(process.nextTick); + + expect(POM.subjectIcon.style.color).toBe(resourceColor2); + }); + }); + }); + + describe('Changes saving/canceling', () => { + const commonAppointment = { + text: 'common-app', + startDate: new Date(2017, 4, 9, 9, 30), + endDate: new Date(2017, 4, 9, 11), + }; + const recurringAppointment = { + text: 'recurring-app', + startDate: new Date(2017, 4, 1, 9, 30), + endDate: new Date(2017, 4, 1, 11), + recurrenceRule: 'FREQ=DAILY;COUNT=5', + }; + + it('should pass updated text to onSave on save button click', async () => { + const { POM, callbacks } = await createAppointmentPopup({ + appointmentData: { ...commonAppointment }, + }); + + POM.setInputValue('subjectEditor', 'New Subject'); + POM.saveButton.click(); + await new Promise(process.nextTick); + + expect(callbacks.onSave).toHaveBeenCalledTimes(1); + expect(callbacks.onSave).toHaveBeenCalledWith( + expect.objectContaining({ ...commonAppointment, text: 'New Subject' }), + ); + }); + + it('should not call onSave on cancel button click', async () => { + const { POM, callbacks } = await createAppointmentPopup({ + appointmentData: { ...commonAppointment }, + }); + + POM.setInputValue('subjectEditor', 'New Subject'); + POM.cancelButton.click(); + + expect(callbacks.onSave).not.toHaveBeenCalled(); + }); + + it('should pass updated text to onSave from recurrence form', async () => { + const { POM, callbacks } = await createAppointmentPopup({ + appointmentData: { ...recurringAppointment }, + }); + + POM.setInputValue('subjectEditor', 'New Subject'); + POM.recurrenceSettingsButton.click(); + POM.saveButton.click(); + await new Promise(process.nextTick); + + expect(callbacks.onSave).toHaveBeenCalledTimes(1); + expect(callbacks.onSave).toHaveBeenCalledWith( + expect.objectContaining({ ...recurringAppointment, text: 'New Subject' }), + ); + }); + + it('should not call onSave on cancel from recurrence form', async () => { + const { POM, callbacks } = await createAppointmentPopup({ + appointmentData: { ...recurringAppointment }, + }); + + POM.setInputValue('subjectEditor', 'New Subject'); + POM.recurrenceSettingsButton.click(); + POM.cancelButton.click(); + + expect(callbacks.onSave).not.toHaveBeenCalled(); + }); + + it('should pass recurrence rule changes to onSave on save button click', async () => { + const { POM, callbacks } = await createAppointmentPopup({ + appointmentData: { ...commonAppointment }, + }); + + POM.selectRepeatValue('daily'); + POM.saveButton.click(); + await new Promise(process.nextTick); + + expect(callbacks.onSave).toHaveBeenCalledWith( + expect.objectContaining({ ...commonAppointment, recurrenceRule: 'FREQ=DAILY' }), + ); + }); + + it('should not modify recurrence rule on save if it was not changed', async () => { + const { POM, callbacks } = await createAppointmentPopup({ + appointmentData: { ...recurringAppointment }, + }); + + POM.saveButton.click(); + await new Promise(process.nextTick); + + expect(callbacks.onSave).toHaveBeenCalledWith( + expect.objectContaining({ recurrenceRule: recurringAppointment.recurrenceRule }), + ); + }); + + it('should clear recurrence rule on save when repeat is set to never', async () => { + const { POM, callbacks } = await createAppointmentPopup({ + appointmentData: { ...recurringAppointment }, + }); + + POM.selectRepeatValue('never'); + POM.saveButton.click(); + await new Promise(process.nextTick); + + expect(callbacks.onSave).toHaveBeenCalledWith( + expect.objectContaining({ recurrenceRule: '' }), + ); + }); + + it('should pass updated resource value to onSave on save button click', async () => { + const { POM, callbacks } = await createAppointmentPopup({ + appointmentData: { + text: 'Resource test app', + startDate: new Date(2017, 4, 9, 9, 30), + endDate: new Date(2017, 4, 9, 11), + roomId: 1, + }, + resources: [{ + fieldExpr: 'roomId', + dataSource: [ + { text: 'Room 1', id: 1, color: '#00af2c' }, + { text: 'Room 2', id: 2, color: '#56ca85' }, + { text: 'Room 3', id: 3, color: '#8ecd3c' }, + ], + }], + }); + + POM.setInputValue('roomId', 2); + POM.saveButton.click(); + await new Promise(process.nextTick); + + expect(callbacks.onSave).toHaveBeenCalledWith( + expect.objectContaining({ roomId: 2 }), + ); + }); + + it('should pass all form fields to onSave including description and dates', async () => { + const { POM, callbacks } = await createAppointmentPopup({ + appointmentData: { + text: '', + startDate: new Date(2017, 4, 25, 9, 0), + endDate: new Date(2017, 4, 25, 10, 0), + }, + }); + + POM.setInputValue('subjectEditor', 'New subject'); + POM.setInputValue('descriptionEditor', 'New appointment description'); + POM.setInputValue('startDateEditor', new Date(2017, 4, 26, 9, 0)); + POM.setInputValue('startTimeEditor', new Date(2017, 4, 26, 9, 0)); + POM.setInputValue('endDateEditor', new Date(2017, 4, 26, 10, 0)); + POM.setInputValue('endTimeEditor', new Date(2017, 4, 26, 10, 0)); + POM.saveButton.click(); + await new Promise(process.nextTick); + + expect(callbacks.onSave).toHaveBeenCalledWith( + expect.objectContaining({ + text: 'New subject', + startDate: new Date(2017, 4, 26, 9, 0), + endDate: new Date(2017, 4, 26, 10, 0), + description: 'New appointment description', + }), + ); + }); + }); });