Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ONL-6340: datepicker fixes #1105

Merged
merged 5 commits into from
Mar 16, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Original file line number Diff line number Diff line change
Expand Up @@ -1111,7 +1111,7 @@ exports[`Datepicker :props should render as disabled 1`] = `
class="ec-input-field__input ec-input-field__input--has-icon flatpickr-input"
data-test="ec-datepicker ec-input-field__input"
disabled="disabled"
id="datepicker-1"
id="ec-datepicker-1"
type="text"
/>

Expand Down Expand Up @@ -1695,7 +1695,7 @@ exports[`Datepicker :props should render with a bottom note 1`] = `
autocomplete="off"
class="ec-input-field__input ec-input-field__input--has-icon flatpickr-input"
data-test="ec-datepicker ec-input-field__input"
id="datepicker-1"
id="ec-datepicker-1"
type="text"
/>

Expand Down Expand Up @@ -1735,7 +1735,7 @@ exports[`Datepicker :props should render with a bottom note in a warning state 1
autocomplete="off"
class="ec-input-field__input ec-input-field__input--has-icon flatpickr-input"
data-test="ec-datepicker ec-input-field__input"
id="datepicker-1"
id="ec-datepicker-1"
type="text"
/>

Expand Down Expand Up @@ -1772,7 +1772,7 @@ exports[`Datepicker :props should render with a label 1`] = `
<label
class="ec-input-field__label"
data-test="ec-input-field__label"
for="datepicker-1"
for="ec-datepicker-1"
>
<span
class="ec-input-field__label-text"
Expand All @@ -1789,7 +1789,7 @@ exports[`Datepicker :props should render with a label 1`] = `
autocomplete="off"
class="ec-input-field__input ec-input-field__input--has-icon flatpickr-input"
data-test="ec-datepicker ec-input-field__input"
id="datepicker-1"
id="ec-datepicker-1"
type="text"
/>

Expand Down Expand Up @@ -1821,7 +1821,7 @@ exports[`Datepicker :props should render with a note 1`] = `
<label
class="ec-input-field__label"
data-test="ec-input-field__label"
for="datepicker-1"
for="ec-datepicker-1"
>
<!---->

Expand All @@ -1837,7 +1837,7 @@ exports[`Datepicker :props should render with a note 1`] = `
autocomplete="off"
class="ec-input-field__input ec-input-field__input--has-icon flatpickr-input"
data-test="ec-datepicker ec-input-field__input"
id="datepicker-1"
id="ec-datepicker-1"
type="text"
/>

Expand Down Expand Up @@ -1872,7 +1872,7 @@ exports[`Datepicker :props should render with a placeholder 1`] = `
autocomplete="off"
class="ec-input-field__input ec-input-field__input--has-icon flatpickr-input"
data-test="ec-datepicker ec-input-field__input"
id="datepicker-1"
id="ec-datepicker-1"
placeholder="Datepicker placeholder"
type="text"
/>
Expand Down Expand Up @@ -1909,7 +1909,7 @@ exports[`Datepicker :props should render with an error message 1`] = `
autocomplete="off"
class="ec-input-field__input ec-input-field__input--has-error ec-input-field__input--has-icon flatpickr-input"
data-test="ec-datepicker ec-input-field__input"
id="datepicker-1"
id="ec-datepicker-1"
type="text"
/>

Expand Down Expand Up @@ -5793,7 +5793,7 @@ exports[`Datepicker should render properly 1`] = `
autocomplete="off"
class="ec-input-field__input ec-input-field__input--has-icon flatpickr-input"
data-test="ec-datepicker ec-input-field__input"
id="datepicker-1"
id="ec-datepicker-1"
type="text"
/>

Expand Down
60 changes: 52 additions & 8 deletions src/components/ec-datepicker/ec-datepicker.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ describe('Datepicker', () => {
},
);

expect(inputWrapper.findByDataTest('ec-input-field__input').element.value).toBe('22/02/2022');
expect(inputWrapper.findByDataTest('ec-datepicker').element.value).toBe('22/02/2022');
});
});

Expand Down Expand Up @@ -325,13 +325,13 @@ describe('Datepicker', () => {
.findByDataTest('ec-datepicker__calendar-day--2022-02-24')
.trigger('click');

expect(inputWrapper.findByDataTest('ec-input-field__input').element.value).toBe('2022-02-24');
expect(inputWrapper.findByDataTest('ec-datepicker').element.value).toBe('2022-02-24');

await inputWrapper.setProps({
dateFormat: 'd/m/Y',
});

expect(inputWrapper.findByDataTest('ec-input-field__input').element.value).toBe('24/02/2022');
expect(inputWrapper.findByDataTest('ec-datepicker').element.value).toBe('24/02/2022');
});

it('should update the locale', async () => {
Expand Down Expand Up @@ -362,6 +362,7 @@ describe('Datepicker', () => {
);

expect(inputWrapper.vm.model.getTime()).toBe(new Date('2022-02-22').getTime());
expect(inputWrapper.findByDataTest('ec-datepicker').element.value).toBe('2022-02-22');
});

it('should update the value of the calendar when I type a value', async () => {
Expand All @@ -377,15 +378,51 @@ describe('Datepicker', () => {
},
);

await inputWrapper.findByDataTest('ec-input-field__input').setValue('2022-02-23');
// When allowInput is true, flatpickr is listening to blur event
// https://github.com/flatpickr/flatpickr/blob/master/src/index.ts#L493
await inputWrapper.findByDataTest('ec-input-field__input').trigger('blur');
await setDatepickerInputValue(inputWrapper, '2022-02-23');

expect(inputWrapper.findByDataTest('ec-input-field__input').element.value).toBe('2022-02-23');
expect(inputWrapper.findByDataTest('ec-datepicker').element.value).toBe('2022-02-23');
expect(inputWrapper.vm.model.getTime()).toBe(new Date(2022, 1, 23).getTime());
});

it('should clear the value in the input when a null gets passed to the model', async () => {
const { inputWrapper } = mountDatepickerAsTemplate(
'<ec-datepicker v-model="model" />',
{},
{
data() {
return {
model: new Date('2022-02-23'),
};
},
},
);

await inputWrapper.setData({
model: null,
});

expect(inputWrapper.findByDataTest('ec-datepicker').element.value).toBe('');
});

it('should clear the model value when the input value gets deleted', async () => {
const { inputWrapper } = mountDatepickerAsTemplate(
'<ec-datepicker v-model="model" />',
{},
{
data() {
return {
model: new Date('2022-02-23'),
};
},
},
);

await setDatepickerInputValue(inputWrapper, '');

expect(inputWrapper.findByDataTest('ec-datepicker').element.value).toBe('');
expect(inputWrapper.vm.model).toBe(null);
});

it('should update the value of the calendar when I select a value from the datepicker', async () => {
const { inputWrapper, calendarWrapper } = mountDatepickerAsTemplate(
'<ec-datepicker v-model="model" />',
Expand Down Expand Up @@ -465,3 +502,10 @@ describe('Datepicker', () => {
});
});
});

async function setDatepickerInputValue(inputWrapper, value) {
inputWrapper.findByDataTest('ec-datepicker').setValue(value);
// When allowInput is true, flatpickr is listening to blur event
// https://github.com/flatpickr/flatpickr/blob/master/src/index.ts#L493
await inputWrapper.findByDataTest('ec-datepicker').trigger('blur');
}
27 changes: 21 additions & 6 deletions src/components/ec-datepicker/ec-datepicker.vue
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,12 @@ export default {
data() {
return {
uid: getUid(),
formattedValue: null,
formattedValue: '',
};
},
computed: {
id() {
return `datepicker-${this.uid}`;
return `ec-datepicker-${this.uid}`;
},
},
watch: {
Expand All @@ -115,6 +115,10 @@ export default {
if (newValue && newValue !== oldValue && !this.datesAreEqual(newValue, oldValue)) {
this.flatpickrInstance.setDate(newValue, true);
}

if (!newValue) {
this.flatpickrInstance.clear();
}
},
dateFormat(newValue) {
/* istanbul ignore next */
Expand Down Expand Up @@ -149,6 +153,19 @@ export default {
},
mounted() {
this.flatpickrInstance = flatpickr(this.$refs.input.getInputRef(), this.mergeWithDefaultOptions(this.options));

/* istanbul ignore next */
if (this.flatpickrInstance.input) {
// sync the value to the formattedValue after the flatpickr is initialized.
//
// if the 'value' prop contains any initial value, that value got passed to the flatpickr via defaultValue option
// and a formatted value may be visible in the input now. we need to get that value from input to our
// formattedValue in order to keep it in sync.
// if we don't do that, an empty formattedValue can be passed to the ec-input-field via Vue props
// in the nextTick, and that would reset the value in the input and in the flatpickr.
this.formattedValue = this.flatpickrInstance.input.value;
}

/* istanbul ignore next */
if (this.flatpickrInstance.calendarContainer) {
this.flatpickrInstance.calendarContainer.dataset.test = 'ec-datepicker__calendar';
Expand Down Expand Up @@ -191,11 +208,9 @@ export default {
onReady: [...(this.options.onReady ?? []), () => {
this.$emit('ready');
}],
// eslint-disable-next-line no-unused-vars
onChange: (selectedDates, dateStr, instance) => {
const d = selectedDates[0];
onChange: (selectedDates, dateStr) => {
this.formattedValue = dateStr;
this.$emit('value-change', d);
this.$emit('value-change', selectedDates[0] ?? null);
},
onOpen: [...(this.options.onOpen ?? []), () => {
this.$emit('open');
Expand Down