diff --git a/frontend/src/components/form/base/EDatePicker.vue b/frontend/src/components/form/base/EDatePicker.vue index aeeb0e9f4bd..fcae6341377 100644 --- a/frontend/src/components/form/base/EDatePicker.vue +++ b/frontend/src/components/form/base/EDatePicker.vue @@ -28,6 +28,7 @@ Displays a field as a date picker (can be used with v-model) no-title scrollable show-adjacent-months + :picker-date.sync="pickerMonth" @input="picker.onInput" > @@ -64,6 +65,37 @@ export default { min: { type: String, default: null }, max: { type: String, default: null }, }, + data: () => ({ + pickerMonth: undefined, + }), + watch: { + min: { + handler(newMin) { + if (this.value) return + if (!newMin) return + const currentPickerMonth = this.$date(this.pickerMonth) + const newMinPickerMonth = this.$date(newMin) + if (currentPickerMonth.unix() < newMinPickerMonth.unix()) { + // Update the month displayed in the picker + this.pickerMonth = newMinPickerMonth.format('YYYY-MM') + } + }, + immediate: true, + }, + max: { + handler(newMax) { + if (this.value) return + if (!newMax) return + const currentPickerMonth = this.$date(this.pickerMonth) + const newMaxPickerMonth = this.$date(newMax) + if (currentPickerMonth.unix() > newMaxPickerMonth.unix()) { + // Update the month displayed in the picker + this.pickerMonth = newMaxPickerMonth.format('YYYY-MM') + } + }, + immediate: true, + }, + }, methods: { /** * override date but keep time diff --git a/frontend/src/components/form/base/__tests__/EColorPicker.spec.js b/frontend/src/components/form/base/__tests__/EColorPicker.spec.js index 1785b3ca2d0..c7f08f178df 100644 --- a/frontend/src/components/form/base/__tests__/EColorPicker.spec.js +++ b/frontend/src/components/form/base/__tests__/EColorPicker.spec.js @@ -149,7 +149,7 @@ describe('An EColorPicker', () => { // then // close button should stay visible - return expect( + await expect( waitFor(() => { expect(screen.queryByText('Schliessen')).not.toBeVisible() }) @@ -178,7 +178,7 @@ describe('An EColorPicker', () => { // Our entered time should be visible... screen.getByDisplayValue(COLOR2) // ...and stay visible - return expect( + await expect( waitFor(() => { expect(screen.getByDisplayValue(COLOR2)).not.toBeVisible() }) @@ -212,7 +212,7 @@ describe('An EColorPicker', () => { // Our entered time should be visible... screen.getByDisplayValue(COLOR3) // ...and stay visible - return expect( + await expect( waitFor(() => { expect(screen.getByDisplayValue(COLOR3)).not.toBeVisible() }) diff --git a/frontend/src/components/form/base/__tests__/EDatePicker.spec.js b/frontend/src/components/form/base/__tests__/EDatePicker.spec.js index aa562b920bc..f9498bf9b6a 100644 --- a/frontend/src/components/form/base/__tests__/EDatePicker.spec.js +++ b/frontend/src/components/form/base/__tests__/EDatePicker.spec.js @@ -15,6 +15,8 @@ describe('An EDatePicker', () => { dateInWrongLocale: '03/19/2020', labelText: 'Dialog öffnen um ein Datum für test zu wählen', date1Heading: 'März 2020', + date3Heading: 'Januar 2111', + date4Heading: 'Januar 1999', closeButton: 'Schliessen', validationMessage: 'Ungültiges Format, bitte gib das Datum im Format DD.MM.YYYY ein', @@ -26,6 +28,8 @@ describe('An EDatePicker', () => { dateInWrongLocale: '19.03.2020', labelText: 'Open dialog to select a date for test', date1Heading: 'March 2020', + date3Heading: 'January 2111', + date4Heading: 'January 1999', closeButton: 'Close', validationMessage: 'Invalid format, please enter the date in the format MM/DD/YYYY', }, @@ -212,7 +216,7 @@ describe('An EDatePicker', () => { // Our entered date should be visible... screen.getByDisplayValue(data.date2) // ...and stay visible - return expect( + await expect( waitFor(() => { expect(screen.getByDisplayValue(data.date2)).not.toBeVisible() }) @@ -243,7 +247,7 @@ describe('An EDatePicker', () => { // Our selected date should be visible... screen.getByDisplayValue(data.date2) // ...and stay visible - return expect( + await expect( waitFor(() => { expect(screen.getByDisplayValue(data.date2)).not.toBeVisible() }) @@ -279,9 +283,99 @@ describe('An EDatePicker', () => { // then expect(screen.queryByText(data.validationMessage)).not.toBeInTheDocument() // validation message should not appear - return expect(screen.findByText(data.validationMessage)).rejects.toThrow( + await expect(screen.findByText(data.validationMessage)).rejects.toThrow( /Unable to find an element with the text/ ) }) + + it('autoscrolls forward to the earliest allowable month based on min', async () => { + // given + render(EDatePicker, { + props: { value: '', name: 'test', min: '2111-01-01' }, + }) + + // when + await user.click(screen.getByLabelText(data.labelText)) + + // then + await waitFor(async () => { + expect(await screen.findByText(data.date3Heading)).toBeVisible() + }) + }) + + it('does not autoscroll forward if given a value', async () => { + // given + render(EDatePicker, { + props: { value: DATE1_ISO, name: 'test', min: '2111-01-01' }, + }) + + // when + await user.click(screen.getByLabelText(data.labelText)) + + // then + await expect(async () => { + await screen.findByText(data.date3Heading) + }).rejects.toThrow(/Unable to find an element with the text/) + }) + + it('does not autoscroll backward based on min', async () => { + // given + render(EDatePicker, { + props: { value: '', name: 'test', min: '1999-01-01' }, + }) + + // when + await user.click(screen.getByLabelText(data.labelText)) + + // then + await expect(async () => { + await screen.findByText(data.date4Heading) + }).rejects.toThrow(/Unable to find an element with the text/) + }) + + it('autoscrolls back to the latest allowable month based on max', async () => { + // given + render(EDatePicker, { + props: { value: '', name: 'test', max: '1999-01-01' }, + }) + + // when + await user.click(screen.getByLabelText(data.labelText)) + + // then + await waitFor(async () => { + expect(await screen.findByText(data.date4Heading)).toBeVisible() + }) + }) + + it('does not autoscroll forward based on max', async () => { + // given + render(EDatePicker, { + props: { value: '', name: 'test', max: '2111-01-01' }, + }) + + // when + await user.click(screen.getByLabelText(data.labelText)) + + // then + await expect(async () => { + await screen.findByText(data.date3Heading) + }).rejects.toThrow(/Unable to find an element with the text/) + }) + + it('does not autoscroll backward if given a value', async () => { + // given + render(EDatePicker, { + props: { value: DATE1_ISO, name: 'test', max: '1999-01-01' }, + }) + + // when + await user.click(screen.getByLabelText(data.labelText)) + + // then + await expect(async () => { + await screen.findByText(data.date4Heading) + }).rejects.toThrow(/Unable to find an element with the text/) + }) }) }) diff --git a/frontend/src/components/form/base/__tests__/ETimePicker.spec.js b/frontend/src/components/form/base/__tests__/ETimePicker.spec.js index ba53c6f9201..2a61ad0bedf 100644 --- a/frontend/src/components/form/base/__tests__/ETimePicker.spec.js +++ b/frontend/src/components/form/base/__tests__/ETimePicker.spec.js @@ -184,7 +184,7 @@ describe('An ETimePicker', () => { // then // close button should stay visible - return expect( + await expect( waitFor(() => { expect(screen.queryByText(data.closeButton)).not.toBeVisible() }) @@ -213,7 +213,7 @@ describe('An ETimePicker', () => { // Our entered time should be visible... screen.getByDisplayValue(data.time2) // ...and stay visible - return expect( + await expect( waitFor(() => { expect(screen.getByDisplayValue(data.time2)).not.toBeVisible() }) @@ -251,7 +251,7 @@ describe('An ETimePicker', () => { // Our entered time should be visible... screen.getByDisplayValue(data.time3) // ...and stay visible - return expect( + await expect( waitFor(() => { expect(screen.getByDisplayValue(data.time3)).not.toBeVisible() })