diff --git a/src/docs/partials/functions/dates.html b/src/docs/partials/functions/dates.html index a56056fe5..77f13cfae 100644 --- a/src/docs/partials/functions/dates.html +++ b/src/docs/partials/functions/dates.html @@ -101,16 +101,29 @@

add(DateTime)
-

setValue(value: DateTime, index?: number) +

setValue(value: DateTime, index?: number, proposedRangeValid?: boolean)

Sets the select date index (or the first, if not provided) to the provided DateTime object. + For dateRange pickers, please use setRangeValues instead. The + proposedRangeValid parameter is intended for internal use.

+
+

setRangeValues(startTarget?: DateTime, endTarget?: DateTime): void + + +

+

+ Sets the range dates to the provided DateTime objects. This should only be used for + dateRange pickers. +

+
+

formatInput(value: DateTime): string { + document.body.innerHTML = `
+
+
+ +
+ + + + +
+
+
+
+`; +}); + +describe('TD date range', () => { + let element, input, td; + + beforeEach(() => { + element = document.getElementById('datetimepicker1'); + input = document.getElementById('datetimepicker1Input'); + td = new TempusDominus(document.getElementById('datetimepicker1'), { + dateRange: true, + display: { + components: { + clock: false, + }, + }, + localization: { + format: 'M/d/yyyy', + }, + }); + }); + + describe('manually inputting from the text input', () => { + const updateInput = (value) => { + input.value = value; + input.dispatchEvent(new Event('change', { bubbles: true })); + }; + + test('keeps invalid input but preserves the selected dates', () => { + updateInput('foobar'); + expect(input.value).toBe('foobar'); + expect(td.dates.picked).toEqual([ + new Date(2025, 6, 8, 0, 0, 0), + new Date(2025, 6, 12, 0, 0, 0), + ]); + }); + + test('can be a single date before the current range', () => { + updateInput('7/1/2025'); + expect(input.value).toBe('7/1/2025; 7/12/2025'); + expect(td.dates.picked).toEqual([ + new Date(2025, 6, 1, 0, 0, 0), + new Date(2025, 6, 12, 0, 0, 0), + ]); + }); + + test('can be a single date in between the current range', () => { + updateInput('7/9/2025'); + expect(input.value).toBe('7/9/2025; 7/12/2025'); + expect(td.dates.picked).toEqual([ + new Date(2025, 6, 9, 0, 0, 0), + new Date(2025, 6, 12, 0, 0, 0), + ]); + }); + + // NOTE: This behavior seems like it might be wrong, but I want to preserve + // current behavior for now + test('can be a single date after the current range', () => { + updateInput('7/19/2025'); + expect(input.value).toBe('7/19/2025; 7/12/2025'); + expect(td.dates.picked).toEqual([ + new Date(2025, 6, 19, 0, 0, 0), + new Date(2025, 6, 12, 0, 0, 0), + ]); + }); + + test('can be before the current range', () => { + updateInput('06/07/2025; 06/11/2025'); + expect(td.dates.picked).toEqual([ + new Date(2025, 5, 7, 0, 0, 0), + new Date(2025, 5, 11, 0, 0, 0), + ]); + }); + + test('can be after the current range', () => { + updateInput('08/07/2025; 08/11/2025'); + expect(td.dates.picked).toEqual([ + new Date(2025, 7, 7, 0, 0, 0), + new Date(2025, 7, 11, 0, 0, 0), + ]); + }); + }); + + describe('selecting the range from the calendar UI', () => { + beforeEach(() => { + // Using the calendar UI ends up using matchMedia, which is not available in jsdom + vi.spyOn(window, 'matchMedia').mockImplementation(() => ({ + matches: false, + addEventListener: vi.fn(), + removeEventListener: vi.fn(), + })); + }); + + test('can be before the current range', () => { + document.querySelector('[data-td-toggle="datetimepicker"] i').click(); + document + .querySelector('[data-action="selectDay"][data-value="2025-06-02"]') + .click(); + document + .querySelector('[data-action="selectDay"][data-value="2025-06-06"]') + .click(); + expect(td.dates.picked).toEqual([ + new Date(2025, 6, 2, 0, 0, 0), + new Date(2025, 6, 6, 0, 0, 0), + ]); + }); + + test('can be after the current range', () => { + document.querySelector('[data-td-toggle="datetimepicker"] i').click(); + document + .querySelector('[data-action="selectDay"][data-value="2025-06-15"]') + .click(); + document + .querySelector('[data-action="selectDay"][data-value="2025-06-19"]') + .click(); + expect(td.dates.picked).toEqual([ + new Date(2025, 6, 15, 0, 0, 0), + new Date(2025, 6, 19, 0, 0, 0), + ]); + }); + }); + + describe('selecting the range programmatically', () => { + test('can be before the current range', () => { + const startDate = td.dates.parseInput('6/7/2025'); + const endDate = td.dates.parseInput('6/11/2025'); + td.dates.setRangeValues(startDate, endDate); + expect(input.value).toBe('6/7/2025; 6/11/2025'); + expect(td.dates.picked).toEqual([ + new Date(2025, 5, 7, 0, 0, 0), + new Date(2025, 5, 11, 0, 0, 0), + ]); + }); + + test('can be in the middle of the current range', () => { + const startDate = td.dates.parseInput('7/9/2025'); + const endDate = td.dates.parseInput('7/11/2025'); + td.dates.setRangeValues(startDate, endDate); + expect(input.value).toBe('7/9/2025; 7/11/2025'); + expect(td.dates.picked).toEqual([ + new Date(2025, 6, 9, 0, 0, 0), + new Date(2025, 6, 11, 0, 0, 0), + ]); + }); + + test('can be after the current range', () => { + const startDate = td.dates.parseInput('8/9/2025'); + const endDate = td.dates.parseInput('8/11/2025'); + td.dates.setRangeValues(startDate, endDate); + expect(input.value).toBe('8/9/2025; 8/11/2025'); + expect(td.dates.picked).toEqual([ + new Date(2025, 7, 9, 0, 0, 0), + new Date(2025, 7, 11, 0, 0, 0), + ]); + }); + }); +});