Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import Scheduler from 'devextreme-testcafe-models/scheduler';
import { createWidget } from '../../../../helpers/createWidget';
import url from '../../../../helpers/getPageUrl';

fixture.disablePageReloads`Appointment Form: Recurrence Form`
.page(url(__dirname, '../../../container.html'));

const SCHEDULER_SELECTOR = '#container';

test('Subject text editor should have focus after returning from recurrence form', async (t) => {
const appointment = {
text: 'Appointment',
startDate: new Date('2021-04-26T16:30:00.000Z'),
endDate: new Date('2021-04-26T18:30:00.000Z'),
allDay: false,
recurrenceRule: 'FREQ=WEEKLY;BYDAY=MO,TH;COUNT=10',
};

const scheduler = new Scheduler(SCHEDULER_SELECTOR);
const appointmentPopup = await scheduler.openAppointmentPopup(t, appointment, true);

await appointmentPopup.openRecurrenceSettings(t);

await t.click(appointmentPopup.recurrence.backButton);

await t
.expect(appointmentPopup.textEditor.getInput().focused)
.ok();
}).before(async () => {
await createWidget('dxScheduler', {
dataSource: [],
views: ['week'],
currentView: 'week',
currentDate: new Date(2021, 2, 25),
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import { ClientFunction, Selector } from 'testcafe';
import Scheduler from 'devextreme-testcafe-models/scheduler';
import { SELECTORS } from 'devextreme-testcafe-models/scheduler/appointment/popup';
import SelectBox from 'devextreme-testcafe-models/selectBox';
import { createWidget } from '../../../../helpers/createWidget';
import url from '../../../../helpers/getPageUrl';

fixture.disablePageReloads`Appointment Form: Recurrence Form`
.page(url(__dirname, '../../../container.html'));

const SCHEDULER_SELECTOR = '#container';

test('Recurrence start date editor should have focus after opening recurrence settings', async (t) => {
const appointment = {
text: 'Appointment',
startDate: new Date('2021-04-26T16:30:00.000Z'),
endDate: new Date('2021-04-26T18:30:00.000Z'),
allDay: false,
recurrenceRule: 'FREQ=WEEKLY;BYDAY=MO,TH;COUNT=10',
};

const scheduler = new Scheduler(SCHEDULER_SELECTOR);
const appointmentPopup = await scheduler.openAppointmentPopup(t, appointment, true);

await appointmentPopup.openRecurrenceSettings(t);

await t
.expect(appointmentPopup.recurrence.startDateInput.focused)
.ok();
}).before(async () => {
await createWidget('dxScheduler', {
dataSource: [],
views: ['week'],
currentView: 'week',
currentDate: new Date(2021, 2, 25),
});
});

test('FrequencyEditor should not be focused when value is changed via API', async (t) => {
const appointment = {
text: 'Appointment',
startDate: new Date('2021-04-26T16:30:00.000Z'),
endDate: new Date('2021-04-26T18:30:00.000Z'),
allDay: false,
recurrenceRule: 'FREQ=WEEKLY;BYDAY=MO,TH;COUNT=10',
};

const scheduler = new Scheduler(SCHEDULER_SELECTOR);
const appointmentPopup = await scheduler.openAppointmentPopup(t, appointment, true);

await appointmentPopup.openRecurrenceSettings(t);

const frequencyEditor = new SelectBox(Selector(SELECTORS.recurrenceFrequencyEditor));
const { getInstance } = frequencyEditor;

const changeFrequencyValue = ClientFunction(
() => {
const instance = getInstance();
if (instance) {
(instance as any).option('value', 'yearly');
}
},
{ dependencies: { getInstance } },
);

await changeFrequencyValue();

await t
.expect(frequencyEditor.getInput().focused)
.notOk();
}).before(async () => {
await createWidget('dxScheduler', {
dataSource: [],
views: ['week'],
currentView: 'week',
currentDate: new Date(2021, 2, 25),
});
});

test('FrequencyEditor should be focused when value is changed via mouse', async (t) => {
const appointment = {
text: 'Appointment',
startDate: new Date('2021-04-26T16:30:00.000Z'),
endDate: new Date('2021-04-26T18:30:00.000Z'),
allDay: false,
recurrenceRule: 'FREQ=WEEKLY;BYDAY=MO,TH;COUNT=10',
};

const scheduler = new Scheduler(SCHEDULER_SELECTOR);
const appointmentPopup = await scheduler.openAppointmentPopup(t, appointment, true);

await appointmentPopup.openRecurrenceSettings(t);

const frequencyEditor = new SelectBox(Selector(SELECTORS.recurrenceFrequencyEditor));
await t.click(frequencyEditor.element);

const yearlyOption = Selector(SELECTORS.listOption).withText('Year(s)');
await t.click(yearlyOption);

await t
.expect(frequencyEditor.getInput().focused)
.ok();
}).before(async () => {
await createWidget('dxScheduler', {
dataSource: [],
views: ['week'],
currentView: 'week',
currentDate: new Date(2021, 2, 25),
});
});

test('FrequencyEditor should be focused when value is changed via keyboard', async (t) => {
const appointment = {
text: 'Appointment',
startDate: new Date('2021-04-26T16:30:00.000Z'),
endDate: new Date('2021-04-26T18:30:00.000Z'),
allDay: false,
recurrenceRule: 'FREQ=WEEKLY;BYDAY=MO,TH;COUNT=10',
};

const scheduler = new Scheduler(SCHEDULER_SELECTOR);
const appointmentPopup = await scheduler.openAppointmentPopup(t, appointment, true);

await appointmentPopup.openRecurrenceSettings(t);

const frequencyEditor = new SelectBox(Selector(SELECTORS.recurrenceFrequencyEditor));

await t.doubleClick(frequencyEditor.element);

await t.pressKey('down');

await t
.expect(frequencyEditor.getInput().focused)
.ok();
}).before(async () => {
await createWidget('dxScheduler', {
dataSource: [],
views: ['week'],
currentView: 'week',
currentDate: new Date(2021, 2, 25),
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -145,3 +145,45 @@ test.meta({ browserSize: [450, 1000] })('recurrence form on mobile screen', asyn
},
},
}));

test.meta({ browserSize: [1500, 1500] })('Recurrence settings button should have correct focus state', async (t) => {
const { takeScreenshot, compareResults } = createScreenshotsComparer(t);

const appointment = {
text: 'Appointment',
startDate: new Date('2021-04-26T16:30:00.000Z'),
endDate: new Date('2021-04-26T18:30:00.000Z'),
allDay: false,
recurrenceRule: 'FREQ=WEEKLY;BYDAY=MO,TH;COUNT=10',
};

const scheduler = new Scheduler(SCHEDULER_SELECTOR);
const appointmentPopup = await scheduler.openAppointmentPopup(t, appointment, true);

await testScreenshot(
t,
takeScreenshot,
'scheduler__appointment__recurrence-settings-button__not-focused.png',
{ element: appointmentPopup.contentElement },
);

await t.hover(appointmentPopup.recurrence.settingsButton);

await testScreenshot(
t,
takeScreenshot,
'scheduler__appointment__recurrence-settings-button__focus-state.png',
{ element: appointmentPopup.contentElement },
);

await t
.expect(compareResults.isValid())
.ok(compareResults.errorMessages());
}).before(async () => {
await createWidget('dxScheduler', {
dataSource: [],
views: ['week'],
currentView: 'week',
currentDate: new Date(2021, 2, 25),
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,11 @@ $fluent-scheduler-agenda-time-panel-cell-padding: 8px;

.dx-scheduler-form-repeat-editor .dx-scheduler-form-recurrence-settings-button {
height: auto;

&.dx-button-mode-text.dx-state-focused,
&.dx-button-mode-text.dx-state-hover {
background-color: rgba(0, 0, 0, .08);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1337,9 +1337,9 @@ describe('Appointment Form', () => {
scheduler.showAppointmentPopup();

expect(POM.popup.isMainGroupVisible()).toBe(true);
expect(POM.popup.mainGroup?.getAttribute('tabindex')).toBeNull();
expect(POM.popup.mainGroup?.getAttribute('inert')).toBeNull();
expect(POM.popup.isRecurrenceGroupVisible()).toBe(false);
expect(POM.popup.recurrenceGroup?.getAttribute('tabindex')).toBe('-1');
expect(POM.popup.recurrenceGroup?.getAttribute('inert')).toBe('true');

POM.popup.selectRepeatValue('weekly');
await new Promise(process.nextTick);
Expand All @@ -1349,17 +1349,17 @@ describe('Appointment Form', () => {
expect(typeof popupHeight).toBe('number');

expect(POM.popup.isMainGroupVisible()).toBe(false);
expect(POM.popup.mainGroup?.getAttribute('tabindex')).toBe('-1');
expect(POM.popup.mainGroup?.getAttribute('inert')).toBe('true');
expect(POM.popup.isRecurrenceGroupVisible()).toBe(true);
expect(POM.popup.recurrenceGroup?.getAttribute('tabindex')).toBeNull();
expect(POM.popup.recurrenceGroup?.getAttribute('inert')).toBeNull();

POM.popup.getBackButton().click();

expect(POM.popup.component.option('height')).toBe('auto');
expect(POM.popup.isMainGroupVisible()).toBe(true);
expect(POM.popup.mainGroup?.getAttribute('tabindex')).toBeNull();
expect(POM.popup.mainGroup?.getAttribute('inert')).toBeNull();
expect(POM.popup.isRecurrenceGroupVisible()).toBe(false);
expect(POM.popup.recurrenceGroup?.getAttribute('tabindex')).toBe('-1');
expect(POM.popup.recurrenceGroup?.getAttribute('inert')).toBe('true');
});

it('should open main form when opening recurring appointment', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const CLASSES = {
form: 'dx-scheduler-form',
icon: 'dx-icon',
hidden: 'dx-hidden',
fieldItemContent: 'dx-field-item-content',

groupWithIcon: 'dx-scheduler-form-group-with-icon',
formIcon: 'dx-scheduler-form-icon',
Expand Down Expand Up @@ -858,6 +859,8 @@ export class AppointmentForm {
}

showMainGroup(): void {
this._popup.updateToolbarForMainGroup();

const currentHeight = this.dxPopup.option('height') as string | number | undefined;
const editingConfig = this.scheduler.getEditingConfig();
const configuredHeight = editingConfig?.popup?.height ?? 'auto';
Expand All @@ -866,28 +869,40 @@ export class AppointmentForm {
this.dxPopup.option('height', configuredHeight);
}

this._$mainGroup?.removeClass(CLASSES.mainHidden);
this._$mainGroup?.removeAttr('tabindex');
this._$recurrenceGroup?.addClass(CLASSES.recurrenceHidden);
this._$recurrenceGroup?.attr('tabindex', '-1');
if (this._$mainGroup) {
this._$mainGroup.removeClass(CLASSES.mainHidden);
this._$mainGroup.removeAttr('inert');

this._popup.updateToolbarForMainGroup();
this.focusFirstFocusableInGroup(this._$mainGroup);
}

if (this._$recurrenceGroup) {
this._$recurrenceGroup.addClass(CLASSES.recurrenceHidden);
this._$recurrenceGroup.attr('inert', true);
}
}

showRecurrenceGroup(): void {
this._popup.updateToolbarForRecurrenceGroup();

const currentHeight = this.dxPopup.option('height') as string | number | undefined;

if (currentHeight === 'auto' || currentHeight === undefined) {
const overlayHeight = this.dxPopup.$overlayContent().get(0).clientHeight;
this.dxPopup.option('height', overlayHeight);
}

this._$mainGroup?.addClass(CLASSES.mainHidden);
this._$mainGroup?.attr('tabindex', '-1');
this._$recurrenceGroup?.removeClass(CLASSES.recurrenceHidden);
this._$recurrenceGroup?.removeAttr('tabindex');
if (this._$mainGroup) {
this._$mainGroup.addClass(CLASSES.mainHidden);
this._$mainGroup.attr('inert', true);
}

if (this._$recurrenceGroup) {
this._$recurrenceGroup.removeClass(CLASSES.recurrenceHidden);
this._$recurrenceGroup.removeAttr('inert');

this._popup.updateToolbarForRecurrenceGroup();
this.focusFirstFocusableInGroup(this._$recurrenceGroup);
}
}

saveRecurrenceValue(): void {
Expand Down Expand Up @@ -1006,4 +1021,9 @@ export class AppointmentForm {
this.dxForm.itemOption(endTimeItemName, 'visible', visible);
this.dxForm.endUpdate();
}

private focusFirstFocusableInGroup($group: dxElementWrapper): void {
const focusTarget = $group.find(`.${CLASSES.fieldItemContent} [tabindex]`).first().get(0) as HTMLElement;
focusTarget?.focus({ preventScroll: true });
}
}
Loading
Loading