Skip to content

Commit

Permalink
fix(datetime-picker): prevent view change when either from/to has bee…
Browse files Browse the repository at this point in the history
…n selected (#842)

* fix(datetime-picker): prevent view change when either from/to has been selected

* test(datetime-picker): add new test cases for duplex split mode
  • Loading branch information
wattachai-lseg authored Jul 20, 2023
1 parent 67061ea commit 2809df6
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@ import '@refinitiv-ui/elements/datetime-picker';
import '@refinitiv-ui/elemental-theme/light/ef-datetime-picker';
import { elementUpdated, expect, fixture, oneEvent } from '@refinitiv-ui/test-helpers';

import { addMonths, calendarClickNext, formatToView, typeText } from './utils';
import { addMonths, calendarClickNext, calendarClickPrevious, formatToView, typeText } from './utils';

const now = new Date();

describe('datetime-picker/View', () => {
describe('View Test', () => {
it('Check default view', async () => {
describe('datetime-picker/View', function () {
describe('View Test', function () {
it('Check default view', async function () {
const el = await fixture('<ef-datetime-picker lang="en-gb"></ef-datetime-picker>');
expect(el.view).to.be.equal(formatToView(now), 'Default view should be set to this month');
});
it('Check default view duplex', async () => {
it('Check default view duplex', async function () {
const el = await fixture('<ef-datetime-picker lang="en-gb" duplex></ef-datetime-picker>');
expect(el.views[0]).to.be.equal(
formatToView(now),
Expand All @@ -25,7 +25,7 @@ describe('datetime-picker/View', () => {
'Default view duplex to should be set to next month'
);
});
it('Check default view duplex=split', async () => {
it('Check default view duplex=split', async function () {
const el = await fixture('<ef-datetime-picker lang="en-gb" duplex="split"></ef-datetime-picker>');
expect(el.views[0]).to.be.equal(
formatToView(now),
Expand All @@ -36,55 +36,55 @@ describe('datetime-picker/View', () => {
'Default view duplex split to should be set to next month'
);
});
it('Check view when value set', async () => {
it('Check view when value set', async function () {
const el = await fixture('<ef-datetime-picker lang="en-gb" value="2020-04-21"></ef-datetime-picker>');
expect(el.view).to.be.equal('2020-04', 'View should be adjusted to value');
});
it('Check duplex view when values set', async () => {
it('Check duplex view when values set', async function () {
const el = await fixture(
'<ef-datetime-picker lang="en-gb" duplex values="2020-04-21,2020-06-21"></ef-datetime-picker>'
);
expect(el.views[0]).to.be.equal('2020-04', 'View from should be adjusted to from value');
expect(el.views[1]).to.be.equal('2020-05', 'View to should be followed by from value');
});
it('Check duplex="split" view when values set', async () => {
it('Check duplex="split" view when values set', async function () {
const el = await fixture(
'<ef-datetime-picker lang="en-gb" duplex="split" values="2020-04-21,2020-06-21"></ef-datetime-picker>'
);
expect(el.views[0]).to.be.equal('2020-04', 'View from should be adjusted to from value');
expect(el.views[1]).to.be.equal('2020-06', 'View to should be adjusted to to value');
});
it('View changes when typing the value', async () => {
it('View changes when typing the value', async function () {
const el = await fixture('<ef-datetime-picker lang="en-gb"></ef-datetime-picker>');
const input = el.inputEl;
typeText(input, '21-Apr-2020');
await elementUpdated(el);
expect(el.view).to.be.equal('2020-04', 'View did not change when typing text');
});
it('View reset to today when clearing the value', async () => {
it('View reset to today when clearing the value', async function () {
const el = await fixture('<ef-datetime-picker lang="en-gb" value="2020-04-21"></ef-datetime-picker>');
const input = el.inputEl;
typeText(input, '');
await elementUpdated(el);
expect(el.view).to.be.equal(formatToView(now), 'View should reset to now when value clears');
});
it('Duplex view changes when typing the value', async () => {
it('Duplex view changes when typing the value', async function () {
const el = await fixture('<ef-datetime-picker lang="en-gb" duplex></ef-datetime-picker>');
const input = el.inputEl;
typeText(input, '21-Apr-2020');
await elementUpdated(el);
expect(el.views[0]).to.be.equal('2020-04', 'Duplex: view from did not change when typing text');
expect(el.views[1]).to.be.equal('2020-05', 'Duplex: view to did not change when typing text');
});
it('Duplex split view changes when typing the value', async () => {
it('Duplex split view changes when typing the value', async function () {
const el = await fixture('<ef-datetime-picker lang="en-gb" duplex="split"></ef-datetime-picker>');
const input = el.inputEl;
typeText(input, '21-Apr-2020');
await elementUpdated(el);
expect(el.views[0]).to.be.equal('2020-04', 'Duplex split: view from did not change when typing text');
expect(el.views[1]).to.be.equal('2020-05', 'Duplex split: view to did not change when typing text');
});
it('Duplex split range view changes when typing the value', async () => {
it('Duplex split range view changes when typing the value', async function () {
const el = await fixture('<ef-datetime-picker lang="en-gb" duplex="split" range></ef-datetime-picker>');
const inputFrom = el.inputEl;
const inputTo = el.inputToEl;
Expand All @@ -100,13 +100,13 @@ describe('datetime-picker/View', () => {
'Duplex split range: view to did not change when typing text'
);
});
it('Setting invalid view should reset view and warn a user', async () => {
it('Setting invalid view should reset view and warn a user', async function () {
const el = await fixture('<ef-datetime-picker lang="en-gb" view="2020-04"></ef-datetime-picker>');
el.view = 'invalid view';
await elementUpdated(el);
expect(el.view).to.be.equal(formatToView(now), 'Invalid view should reset view');
});
it('Views are propagated to calendars', async () => {
it('Views are propagated to calendars', async function () {
const el = await fixture(
'<ef-datetime-picker lang="en-gb" range duplex="split" opened></ef-datetime-picker>'
);
Expand All @@ -117,7 +117,7 @@ describe('datetime-picker/View', () => {
expect(calendarFrom.view).to.be.equal('2020-01', 'From view is not propagated to calendar');
expect(calendarTo.view).to.be.equal('2020-04', 'To view is not propagated to calendar');
});
it('Passing empty string should reset views to default', async () => {
it('Passing empty string should reset views to default', async function () {
const el = await fixture(
'<ef-datetime-picker lang="en-gb" range duplex="split" views="2020-01,2020-04"></ef-datetime-picker>'
);
Expand All @@ -126,7 +126,7 @@ describe('datetime-picker/View', () => {
expect(el.views[0]).to.be.equal(formatToView(now), 'View from is not reset');
expect(el.views[1]).to.be.equal(formatToView(addMonths(now, 1)), 'View to is not reset');
});
it('Changing view in calendar should be reflected in datetime-picker and should fire view-changed event', async () => {
it('Changing view in calendar should be reflected in datetime-picker and should fire view-changed event', async function () {
const el = await fixture(
'<ef-datetime-picker lang="en-gb" view="2020-04" opened></ef-datetime-picker>'
);
Expand All @@ -138,7 +138,7 @@ describe('datetime-picker/View', () => {
expect(value).to.be.equal('2020-05', 'view-changed event does not contain valid value');
expect(el.view).to.be.equal('2020-05', 'View did not change on next click');
});
it('In duplex mode calendar view should be in sync', async () => {
it('In duplex mode calendar view should be in sync', async function () {
const el = await fixture(
'<ef-datetime-picker lang="en-gb" view="2020-04" duplex opened></ef-datetime-picker>'
);
Expand All @@ -163,7 +163,7 @@ describe('datetime-picker/View', () => {
'Clicking next on to calendar did not synchronise views'
);
});
it('In duplex="split" mode calendar view should be in sync', async () => {
it('In duplex="split" mode calendar view should be in sync', async function () {
const el = await fixture(
'<ef-datetime-picker lang="en-gb" duplex="split" opened></ef-datetime-picker>'
);
Expand Down Expand Up @@ -201,5 +201,42 @@ describe('datetime-picker/View', () => {
'Clicking next on to calendar did not synchronise views'
);
});

it('In range duplex="split" mode calendar view should be independent when at least one value is selected', async function () {
const el = await fixture(
'<ef-datetime-picker lang="en-gb" range duplex="split" opened></ef-datetime-picker>'
);
el.values = ['1997-04-01'];
const calendarFrom = el.calendarEl;
const calendarTo = el.calendarToEl;
await elementUpdated(el);
expect(calendarFrom.view).to.equal('1997-04', 'Calendar from view is not updated to the value');
expect(calendarTo.view).to.equal(
'1997-05',
'Calendar to view is not updated to next month of the value'
);
expect(String(el.views)).to.equal(
'1997-04,1997-05',
'Datepicker views are not updated according to the value'
);

calendarClickNext(calendarFrom);
await elementUpdated(el);
expect(calendarFrom.view).to.equal('1997-05', 'Calendar from view is not updated');
expect(calendarTo.view).to.equal('1997-05', 'Calendar to view is not updated');
expect(String(el.views)).to.equal('1997-05,1997-05', 'Datepicker views are not updated');

calendarClickNext(calendarFrom);
await elementUpdated(el);
expect(calendarFrom.view).to.equal('1997-06', 'Calendar from view is not updated');
expect(calendarTo.view).to.equal('1997-05', 'Calendar to view is not updated');
expect(String(el.views)).to.equal('1997-06,1997-05', 'Datepicker views are not updated');

calendarClickPrevious(calendarTo);
await elementUpdated(el);
expect(calendarFrom.view).to.equal('1997-06', 'CCalendar from view is not updated');
expect(calendarTo.view).to.equal('1997-04', 'Calendar to view is not updated');
expect(String(el.views)).to.equal('1997-06,1997-04', 'Datepicker views are not updated');
});
});
});
5 changes: 5 additions & 0 deletions packages/elements/src/datetime-picker/__test__/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ export const calendarClickNext = async (calendarEl) => {
await elementUpdated(calendarEl);
};

export const calendarClickPrevious = async (calendarEl) => {
calendarEl.shadowRoot.querySelector('[part=btn-prev]').click();
await elementUpdated(calendarEl);
};

export const snapshotIgnore = {
ignoreAttributes: ['style', 'class']
};
8 changes: 4 additions & 4 deletions packages/elements/src/datetime-picker/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -720,19 +720,19 @@ export class DatetimePicker extends ControlElement implements MultiValue {

// duplex split
if (index === 0) {
/* from. to must be after or the same */
// from. to must be after or the same when no value has been selected
let after = views[1] || addMonths(view, 1);
if (isBefore(after, view)) {
if (this.values.every((value) => !value) && isBefore(after, view)) {
after = view;
}

return [view, formatToView(after)];
}

if (index === 1) {
/* to. from must be before or the same */
// to. from must be before or the same when no value has been selected
let before = views[0] || subMonths(view, 1);
if (isAfter(before, view)) {
if (this.values.every((value) => !value) && isAfter(before, view)) {
before = view;
}

Expand Down

0 comments on commit 2809df6

Please sign in to comment.