From fecd7d188f543e4542917f63a6012b0a8c2fa6c0 Mon Sep 17 00:00:00 2001 From: Georgi Damyanov Date: Fri, 21 Nov 2025 15:31:05 +0200 Subject: [PATCH 01/10] feat: make calendar header btns focusable --- packages/main/src/Calendar.ts | 10 ++++++++++ packages/main/src/CalendarHeaderTemplate.tsx | 6 ++++++ packages/main/src/CalendarTemplate.tsx | 7 +++---- packages/main/src/i18n/messagebundle.properties | 12 ++++++++++++ packages/main/src/themes/Calendar.css | 2 +- packages/main/src/themes/CalendarHeader.css | 2 +- 6 files changed, 33 insertions(+), 6 deletions(-) diff --git a/packages/main/src/Calendar.ts b/packages/main/src/Calendar.ts index ba14a1a2db4c..b4fb2822e4b1 100644 --- a/packages/main/src/Calendar.ts +++ b/packages/main/src/Calendar.ts @@ -53,6 +53,10 @@ import { CALENDAR_HEADER_YEAR_BUTTON_SHORTCUT, CALENDAR_HEADER_YEAR_RANGE_BUTTON, CALENDAR_HEADER_YEAR_RANGE_BUTTON_SHORTCUT, + CALENDAR_HEADER_MONTH_NEXT_BUTTON_TITLE, + CALENDAR_HEADER_MONTH_NEXT_BUTTON_SHORTCUT, + CALENDAR_HEADER_MONTH_PREVIOUS_BUTTON_TITLE, + CALENDAR_HEADER_MONTH_PREVIOUS_BUTTON_SHORTCUT, } from "./generated/i18n/i18n-defaults.js"; import type { YearRangePickerChangeEventDetail } from "./YearRangePicker.js"; @@ -802,11 +806,15 @@ class Calendar extends CalendarPart { const monthLabel = Calendar.i18nBundle?.getText(CALENDAR_HEADER_MONTH_BUTTON, headerMonthButtonText); const yearLabel = Calendar.i18nBundle?.getText(CALENDAR_HEADER_YEAR_BUTTON, this._headerYearButtonText as string); const yearRangeLabel = Calendar.i18nBundle?.getText(CALENDAR_HEADER_YEAR_RANGE_BUTTON, rangeStartText, rangeEndText); + const nextBtnLabel = Calendar.i18nBundle?.getText(CALENDAR_HEADER_MONTH_NEXT_BUTTON_TITLE); + const prevBtnLabel = Calendar.i18nBundle?.getText(CALENDAR_HEADER_MONTH_PREVIOUS_BUTTON_TITLE); // Get shortcuts const monthShortcut = Calendar.i18nBundle?.getText(CALENDAR_HEADER_MONTH_BUTTON_SHORTCUT); const yearShortcut = Calendar.i18nBundle?.getText(CALENDAR_HEADER_YEAR_BUTTON_SHORTCUT); const yearRangeShortcut = Calendar.i18nBundle?.getText(CALENDAR_HEADER_YEAR_RANGE_BUTTON_SHORTCUT); + const nextBtnShortcut = Calendar.i18nBundle?.getText(CALENDAR_HEADER_MONTH_NEXT_BUTTON_SHORTCUT); + const prevBtnShortcut = Calendar.i18nBundle?.getText(CALENDAR_HEADER_MONTH_PREVIOUS_BUTTON_SHORTCUT); return { ariaLabelMonthButton: monthLabel, @@ -822,6 +830,8 @@ class Calendar extends CalendarPart { tooltipMonthButton: `${monthLabel} (${monthShortcut})`, tooltipYearButton: `${yearLabel} (${yearShortcut})`, tooltipYearRangeButton: `${yearRangeLabel} (${yearRangeShortcut})`, + tooltipNextButton: `${nextBtnLabel} (${nextBtnShortcut})`, + tooltipPrevButton: `${prevBtnLabel} (${prevBtnShortcut})`, }; } diff --git a/packages/main/src/CalendarHeaderTemplate.tsx b/packages/main/src/CalendarHeaderTemplate.tsx index c3193e95c41d..96ad04cc287b 100644 --- a/packages/main/src/CalendarHeaderTemplate.tsx +++ b/packages/main/src/CalendarHeaderTemplate.tsx @@ -7,6 +7,7 @@ import slimArowRight from "@ui5/webcomponents-icons/dist/slim-arrow-right.js"; export default function CalendarTemplate(this: Calendar) { return (
+
@@ -35,6 +38,7 @@ export default function CalendarTemplate(this: Calendar) { onClick={this.onHeaderMonthButtonPress} onKeyDown={this.onMonthButtonKeyDown} onKeyUp={this.onMonthButtonKeyUp} + > {this._headerMonthButtonText} {this.hasSecondaryCalendarType && @@ -93,6 +97,8 @@ export default function CalendarTemplate(this: Calendar) { part="calendar-header-arrow-button" role="button" onMouseDown={this.onNextButtonClick} + tabindex={this._nextButtonDisabled ? -1 : 0} + title={this.accInfo.tooltipNextButton} >
diff --git a/packages/main/src/CalendarTemplate.tsx b/packages/main/src/CalendarTemplate.tsx index dc96a6eccb24..d610645f9ea0 100644 --- a/packages/main/src/CalendarTemplate.tsx +++ b/packages/main/src/CalendarTemplate.tsx @@ -13,6 +13,9 @@ export default function CalendarTemplate(this: Calendar) { class="ui5-cal-root" onKeyDown={this._onkeydown} > +
+ { CalendarHeaderTemplate.call(this) } +
- -
- { CalendarHeaderTemplate.call(this) } -
Date: Mon, 24 Nov 2025 17:33:00 +0200 Subject: [PATCH 02/10] feat: apply styles --- packages/main/src/themes/CalendarHeader.css | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/main/src/themes/CalendarHeader.css b/packages/main/src/themes/CalendarHeader.css index 34d39e8686d3..93c495d28370 100644 --- a/packages/main/src/themes/CalendarHeader.css +++ b/packages/main/src/themes/CalendarHeader.css @@ -24,6 +24,8 @@ padding: 0; font-size: var(--sapFontSize); user-select: none; + position: relative; + box-sizing: border-box; } .ui5-calheader-arrowbtn.ui5-calheader-arrowbtn-disabled:hover, @@ -41,10 +43,6 @@ display: none; } -.ui5-calheader-arrowbtn:focus { - outline: none; -} - .ui5-calheader-arrowbtn:hover { background-color: var(--sapButton_Hover_Background); color: var(--sapButton_Lite_TextColor); @@ -111,13 +109,13 @@ background: var(--_ui5_calendar_header_middle_button_focus_background); } -.ui5-calheader-middlebtn:focus:active { +.ui5-calheader-middlebtn:focus:active, .ui5-calheader-arrowbtn:focus:active { outline: var(--_ui5_calendar_header_middle_button_focus_active_outline); outline-offset: -0.0625rem; background: var(--_ui5_calendar_header_middle_button_focus_active_background) } -.ui5-calheader-middlebtn:focus::after { +.ui5-calheader-middlebtn:focus::after, .ui5-calheader-arrowbtn:focus::after { content: ""; display: var(--_ui5_calendar_header_middle_button_focus_after_display); width: var(--_ui5_calendar_header_middle_button_focus_after_width); @@ -128,6 +126,6 @@ left: var(--_ui5_calendar_header_middle_button_focus_after_left_offset); } -.ui5-calheader-middlebtn:focus:active::after { +.ui5-calheader-middlebtn:focus:active::after, .ui5-calheader-arrowbtn:focus:active::after { border-color: var(--sapContent_ContrastFocusColor); } From c14faf6c680629a37695433d335b329c6596cdba Mon Sep 17 00:00:00 2001 From: Georgi Damyanov Date: Mon, 24 Nov 2025 17:38:43 +0200 Subject: [PATCH 03/10] fix: lint errors --- packages/main/src/CalendarHeaderTemplate.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/main/src/CalendarHeaderTemplate.tsx b/packages/main/src/CalendarHeaderTemplate.tsx index 96ad04cc287b..10bc4b6d14ab 100644 --- a/packages/main/src/CalendarHeaderTemplate.tsx +++ b/packages/main/src/CalendarHeaderTemplate.tsx @@ -7,7 +7,6 @@ import slimArowRight from "@ui5/webcomponents-icons/dist/slim-arrow-right.js"; export default function CalendarTemplate(this: Calendar) { return (
-
{this._headerMonthButtonText} {this.hasSecondaryCalendarType && From 3986aa6a4b802bbfe30f52d8b2bbd1365cf58f7c Mon Sep 17 00:00:00 2001 From: Georgi Damyanov Date: Mon, 24 Nov 2025 21:08:19 +0200 Subject: [PATCH 04/10] test: start to adapt tests --- packages/main/cypress/specs/Calendar.cy.tsx | 2827 ++++++++++--------- 1 file changed, 1425 insertions(+), 1402 deletions(-) diff --git a/packages/main/cypress/specs/Calendar.cy.tsx b/packages/main/cypress/specs/Calendar.cy.tsx index 47141ef325ef..e2a0106bf3db 100644 --- a/packages/main/cypress/specs/Calendar.cy.tsx +++ b/packages/main/cypress/specs/Calendar.cy.tsx @@ -38,1438 +38,1461 @@ const getCalendarsWithWeekNumbers = () => (<> ); describe("Calendar general interaction", () => { - it("Focus goes into the current day item of the day picker", () => { + it("Focus goes into the header items and then to the current day item of the day picker", () => { const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); cy.mount(getDefaultCalendar(date)); - cy.ui5CalendarGetDay("#calendar1", "974851200") - .as("selectedDay"); - - cy.get("@selectedDay") - .realClick(); - - cy.get("@selectedDay") - .should("have.focus") - .realPress("Tab"); - - cy.get("#calendar1") - .shadow() - .find(".ui5-calheader") - .as("calheader"); - - cy.get("@calheader") - .find("[data-ui5-cal-header-btn-month]") - .as("monthBtn"); - - cy.get("@monthBtn") - .should("have.focus") - .realPress("Tab"); - - cy.get("@calheader") - .find("[data-ui5-cal-header-btn-year]") - .as("yearBtn"); - - cy.get("@yearBtn") - .should("have.focus") - .realPress(["Shift", "Tab"]); - - cy.get("@monthBtn") - .should("have.focus") - .realPress(["Shift", "Tab"]); - - cy.get("@selectedDay") - .should("have.focus"); - }); - - it("Calendar focuses the selected year when yearpicker is opened", () => { - const YEAR = 1997; - const date = Date.UTC(YEAR); - cy.mount(getDefaultCalendar(new Date(date))); - - cy.get("#calendar1") - .shadow() - .find(".ui5-calheader") - .find("[data-ui5-cal-header-btn-year]") - .realClick(); - - cy.get("#calendar1") - .shadow() - .find("[ui5-yearpicker]") - .shadow() - .find("[tabindex='0']") - .invoke("attr", "data-sap-timestamp") - .then(_timestamp => { - const focusedYear = new Date(parseInt(_timestamp!) * 1000).getUTCFullYear(); - expect(focusedYear).to.equal(1997); - }); - }); - - it("Calendar focuses the selected month when monthpicker is opened with space", () => { - const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); - cy.mount(getDefaultCalendar(date)); - - cy.ui5CalendarGetDay("#calendar1", "974851200") - .realClick(); - - cy.focused().realPress("Tab"); - cy.focused().realPress("Space"); - - cy.get("#calendar1") - .shadow() - .find("[ui5-monthpicker]") - .should("not.have.attr", "hidden"); - - cy.get("#calendar1") - .shadow() - .find("[ui5-monthpicker]") - .shadow() - .find("[tabindex='0']") - .invoke("attr", "data-sap-timestamp") - .then(_timestamp => { - const focusedMonth = new Date(parseInt(_timestamp!) * 1000).getUTCMonth(); - expect(focusedMonth).to.equal(10); - }); - }); - - it("Calendar focuses the selected year when yearpicker is opened with space", () => { - const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); - cy.mount(getDefaultCalendar(date)); - - cy.ui5CalendarGetDay("#calendar1", "974851200") - .realClick(); - - cy.focused().realPress("Tab"); - cy.focused().realPress("Tab"); - cy.focused().realPress("Space"); - - cy.get("#calendar1") - .shadow() - .find("[ui5-yearpicker]") - .should("not.have.attr", "hidden"); - - cy.get("#calendar1") - .shadow() - .find("[ui5-yearpicker]") - .shadow() - .find("[tabindex='0']") - .invoke("attr", "data-sap-timestamp") - .then(_timestamp => { - const focusedYear = new Date(parseInt(_timestamp!) * 1000).getUTCFullYear(); - expect(focusedYear).to.equal(2000); - }); - }); - - it("Should focus the selected range when YearRange Picker is opened", () => { - const YEAR = 1997; - const date = Date.UTC(YEAR); - const expectedRangeStart = 1988; - const expectedRangeEnd = 2007; - cy.mount(getDefaultCalendar(new Date(date))); - - cy.get("[ui5-calendar]") - .as("calendar"); - - cy.get("@calendar") - .ui5CalendarShowYearRangePicker(); - - cy.get("@calendar") - .shadow() - .find("[ui5-yearrangepicker]") - .as("yearRangePicker"); - - cy.get("@yearRangePicker") - .shadow() - .find("[tabindex='0']") - .as("focusedYearRange"); - - cy.get("@focusedYearRange") - .invoke("attr", "data-sap-timestamp") - .then(_timestamp => { - const focusedYear = new Date(parseInt(_timestamp!) * 1000).getUTCFullYear(); - expect(focusedYear).to.equal(expectedRangeStart); - }); - - cy.get("@focusedYearRange") - .find("span") - .first() - .should("have.text", `${expectedRangeStart} - ${expectedRangeEnd}`); - }); - - it("Calendar doesn't mark year as selected when there are no selected dates", () => { - const todayDate = new Date(); - const todayTimestamp = Date.UTC(todayDate.getFullYear(), todayDate.getMonth(), todayDate.getDate(), 0, 0, 0, 0) / 1000; - - cy.mount(); - - cy.get("#calendar2") - .shadow() - .find(".ui5-calheader") - .find("[data-ui5-cal-header-btn-year]") - .realClick(); - - cy.get("#calendar2") - .shadow() - .find("[ui5-yearpicker]") - .shadow() - .find(`[data-sap-timestamp=${todayTimestamp}]`) - .should("have.focus") - .should("not.have.class", "ui5-yp-item--selected"); - }); - - it("Calendar doesn't mark month as selected when there are no selected dates", () => { - const todayDate = new Date(); - const todayTimestamp = Date.UTC(todayDate.getFullYear(), todayDate.getMonth(), todayDate.getDate(), 0, 0, 0, 0) / 1000; - - cy.mount(); - - cy.get("#calendar2") - .shadow() - .find(".ui5-calheader") - .find("[data-ui5-cal-header-btn-month]") - .realClick(); - - cy.ui5CalendarGetMonth("#calendar2", todayTimestamp.toString()) - .should("have.focus") - .should("not.have.class", "ui5-mp-item--selected"); - }); - - it("Should navigate to Year Picker when selecting a range in Year Range Picker", () => { - const YEAR = 1997; - const date = Date.UTC(YEAR); - const expectedRangeStart = 1948; - const expectedRangeEnd = 1967; - cy.mount(getDefaultCalendar(new Date(date))); - - cy.get("[ui5-calendar]") - .as("calendar"); - - cy.get("@calendar") - .ui5CalendarShowYearRangePicker(); - - cy.get("@calendar") - .shadow() - .find("[ui5-yearrangepicker]") - .as("yearRangePicker"); - - cy.get("@yearRangePicker") - .shadow() - .find(".ui5-yrp-item") - .first() // 1948 - 1967 - .as("yearRangePickerItem"); - - cy.get("@yearRangePickerItem") - .find("span") - .first() - .should("have.text", `${expectedRangeStart} - ${expectedRangeEnd}`); - - cy.get("@yearRangePickerItem") - .realClick({position: "center"}); - - cy.get("@calendar") - .shadow() - .find("[ui5-yearpicker]") - .as("yearPicker"); - - cy.get("@yearPicker") - .should("be.visible"); - - cy.get("@yearPicker") - .shadow() - .find(".ui5-yp-item") - .first() - .as("yearPickerItem"); - - cy.get("@yearPickerItem") - .invoke("attr", "data-sap-timestamp") - .then(_timestamp => { - const year = new Date(parseInt(_timestamp!) * 1000).getUTCFullYear(); - expect(year).to.equal(expectedRangeStart); - }); - - }); - - it("Page up/down increments/decrements the month value", () => { - const date = new Date(Date.UTC(2000, 10, 1, 0, 0, 0)); - cy.mount(getDefaultCalendar(date)); - - cy.get("#calendar1") - .shadow() - .find("[ui5-daypicker]") - .shadow() - .find("[tabindex='0']") - .realClick(); - - cy.focused().realPress("PageUp"); - - cy.get("#calendar1") - .invoke("prop", "timestamp") - .then(_timestamp => { - expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(2000, 9, 1, 0, 0, 0))); - }); - - cy.focused().realPress("PageDown"); - - cy.get("#calendar1") - .invoke("prop", "timestamp") - .then(_timestamp => { - expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(2000, 10, 1, 0, 0, 0))); - }); - }); - - it("Shift + Page up/down increments/decrements the year value by one", () => { - const date = new Date(Date.UTC(2000, 10, 1, 0, 0, 0)); - cy.mount(getDefaultCalendar(date)); - - cy.get("#calendar1") - .shadow() - .find("[ui5-daypicker]") - .shadow() - .find("[tabindex='0']") - .realClick(); - - cy.focused().realPress(["Shift", "PageUp"]); - - cy.get("#calendar1") - .invoke("prop", "timestamp") - .then(_timestamp => { - expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(1999, 10, 1, 0, 0, 0))); - }); - - cy.focused().realPress(["Shift", "PageDown"]); - - cy.get("#calendar1") - .invoke("prop", "timestamp") - .then(_timestamp => { - expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(2000, 10, 1, 0, 0, 0))); - }); - }); - - it("Ctrl + Shift + Page up/down increments/decrements the year value by ten", () => { - const date = new Date(Date.UTC(2000, 10, 1, 0, 0, 0)); - cy.mount(getDefaultCalendar(date)); - - cy.get("#calendar1") - .shadow() - .find("[ui5-daypicker]") - .shadow() - .find("[tabindex='0']") - .realClick(); - - cy.focused().realPress(["Control", "Shift", "PageUp"]); - - cy.get("#calendar1") - .invoke("prop", "timestamp") - .then(_timestamp => { - expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(1990, 10, 1, 0, 0, 0))); - }); - - cy.focused().realPress(["Control", "Shift", "PageDown"]); - - cy.get("#calendar1") - .invoke("prop", "timestamp") - .then(_timestamp => { - expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(2000, 10, 1, 0, 0, 0))); - }); - }); - - it("Page up/down increments/decrements the year value in the month picker", () => { - const date = new Date(Date.UTC(2000, 9, 1, 0, 0, 0)); - cy.mount(getDefaultCalendar(date)); - - cy.get("#calendar1") - .shadow() - .find("[ui5-daypicker]") - .shadow() - .find("[tabindex='0']") - .realClick(); - - cy.focused().realPress("F4"); - cy.focused().realPress("PageUp"); - - cy.get("#calendar1") - .invoke("prop", "timestamp") - .then(_timestamp => { - expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(1999, 9, 1, 0, 0, 0))); - }); - - cy.focused().realPress("PageDown"); - - cy.get("#calendar1") - .invoke("prop", "timestamp") - .then(_timestamp => { - expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(2000, 9, 1, 0, 0, 0))); - }); - }); - - it("Page up/down increments/decrements the year range in the year picker", () => { - const date = new Date(Date.UTC(2000, 9, 1, 0, 0, 0)); - cy.mount(getDefaultCalendar(date)); - - cy.get("#calendar1") - .shadow() - .find("[ui5-daypicker]") - .shadow() - .find("[tabindex='0']") - .realClick() - .should("have.focus"); - - cy.focused().realPress(["Shift", "F4"]); - - // Wait for focus to settle before proceeding - cy.get("#calendar1") - .shadow() - .find("[ui5-yearpicker]") - .shadow() - .find("[tabindex='0']") - .should("have.focus"); - - cy.focused().realPress("PageUp"); - - cy.get("#calendar1") - .invoke("prop", "timestamp") - .then(_timestamp => { - expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(1980, 9, 1, 0, 0, 0))); - }); - - // Wait for focus to settle before proceeding - cy.get("#calendar1") - .shadow() - .find("[ui5-yearpicker]") - .shadow() - .find("[tabindex='0']") - .should("have.focus"); - - cy.focused().realPress("PageDown"); - - cy.get("#calendar1") - .invoke("prop", "timestamp") - .then(_timestamp => { - expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(2000, 9, 1, 0, 0, 0))); - }); - }); - - it("Navigation with Page down decrements the year ranges in the year range picker", () => { - const date = new Date(Date.UTC(1998, 9, 16, 0, 0, 0)); - cy.mount(getDefaultCalendar(date)); - - cy.get("#calendar1") - .ui5CalendarShowYearRangePicker(); - - cy.get("#calendar1") - .invoke("prop", "timestamp") - .then(_timestamp => { - expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(1998, 9, 16, 0, 0, 0))); - }); - - // Wait for focus to settle before proceeding - cy.get("#calendar1") - .shadow() - .find("[ui5-yearrangepicker]") - .shadow() - .find("[tabindex='0']") - .should("have.focus"); - - cy.focused().realPress("PageUp"); - - cy.get("#calendar1") - .invoke("prop", "timestamp") - .then(_timestamp => { - expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(1838, 9, 16, 0, 0, 0))); - }); - }); - - it("Navigation with Page up increments the year ranges in the year range picker", () => { - const date = new Date(Date.UTC(1998, 9, 16, 0, 0, 0)); - cy.mount(getDefaultCalendar(date)); - - cy.get("#calendar1") - .ui5CalendarShowYearRangePicker(); - - cy.get("#calendar1") - .invoke("prop", "timestamp") - .then(_timestamp => { - expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(1998, 9, 16, 0, 0, 0))); - }); - - // Wait for focus to settle before proceeding - cy.get("#calendar1") - .shadow() - .find("[ui5-yearrangepicker]") - .shadow() - .find("[tabindex='0']") - .should("have.focus"); - - cy.focused().realPress("PageDown"); - - cy.get("#calendar1") - .invoke("prop", "timestamp") - .then(_timestamp => { - expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(2158, 9, 16, 0, 0, 0))); - }); - }); - - it("Calendar with 'Multiple' selection type", () => { - cy.mount(); - const timestamp = new Date(Date.UTC(2000, 9, 10, 0, 0, 0)).valueOf() / 1000; - - cy.get("#calendar1").invoke("prop", "timestamp", timestamp); - - const timestamps = [971136000, 971222400, 971308800]; - - timestamps.forEach(_timestamp => { - cy.ui5CalendarGetDay("#calendar1", _timestamp.toString()) - .as("date"); - - cy.get("@date").realClick(); - cy.get("@date").should("have.class", "ui5-dp-item--selected"); - }); - - cy.get("#calendar1") - .invoke("prop", "selectedDates") - .then(selectedDates => { - expect(selectedDates.sort()).to.deep.equal(timestamps.sort()); - }); - }); - - it("Keyboard navigation works properly, when calendar selection type is set to 'Multiple'", () => { - cy.mount(); - - const timestamp = new Date(Date.UTC(2000, 9, 10, 0, 0, 0)).valueOf() / 1000; - - cy.get("#calendar1").invoke("prop", "timestamp", timestamp); - - cy.ui5CalendarGetDay("#calendar1", timestamp.toString()) - .focus() - .should("have.focus"); - - // Select the focused date - cy.focused().realPress("Space"); - - // Deselect the focused date - cy.focused().realPress("Space"); - cy.focused().realPress("ArrowRight"); - - cy.ui5CalendarGetDay("#calendar1", "971222400") - .should("have.focus"); - }); - - it("Calendar with 'Range' selection type", () => { - cy.mount(); - const timestamp = new Date(Date.UTC(2000, 9, 10, 0, 0, 0)).valueOf() / 1000; - - cy.get("#calendar1").invoke("prop", "timestamp", timestamp); - - const timestamps = [971740800, 971827200, 971913600]; - - cy.ui5CalendarGetDay("#calendar1", timestamps[0].toString()) - .realClick(); - - cy.ui5CalendarGetDay("#calendar1", timestamps[2].toString()) - .realClick(); - - cy.ui5CalendarGetDay("#calendar1", timestamps[0].toString()) - .should("have.class", "ui5-dp-item--selected"); - - cy.ui5CalendarGetDay("#calendar1", timestamps[1].toString()) - .should("have.class", "ui5-dp-item--selected-between"); - - cy.ui5CalendarGetDay("#calendar1", timestamps[2].toString()) - .should("have.class", "ui5-dp-item--selected"); - - cy.get("#calendar1") - .invoke("prop", "selectedDates") - .then(selectedDates => { - expect(selectedDates.sort()).to.deep.equal([timestamps[0], timestamps[2]].sort()); - }); - }); - - it("Previous and next buttons are disabled when necessary", () => { - cy.mount(<> - - - - ); - const timestamp = 1594166400; - - cy.get("#calendar1").invoke("prop", "timestamp", timestamp); - - cy.get("#calendar1") - .shadow() - .find(".ui5-calheader") - .find("[data-ui5-cal-header-btn-prev]") - .should("have.class", "ui5-calheader-arrowbtn-disabled"); - - cy.get("#calendar1") - .shadow() - .find(".ui5-calheader") - .find("[data-ui5-cal-header-btn-next]") - .should("not.have.class", "ui5-calheader-arrowbtn-disabled") - .realClick(); - - cy.get("#calendar1") - .shadow() - .find(".ui5-calheader") - .find("[data-ui5-cal-header-btn-prev]") - .should("not.have.class", "ui5-calheader-arrowbtn-disabled"); - - cy.get("#calendar1") - .shadow() - .find(".ui5-calheader") - .find("[data-ui5-cal-header-btn-next]") - .should("not.have.class", "ui5-calheader-arrowbtn-disabled"); - - cy.get("#calendar1") - .shadow() - .find(".ui5-calheader") - .find("[data-ui5-cal-header-btn-next]") - .realClick(); - - cy.get("#calendar1") - .shadow() - .find(".ui5-calheader") - .find("[data-ui5-cal-header-btn-next]") - .realClick(); - - cy.get("#calendar1") - .shadow() - .find(".ui5-calheader") - .find("[data-ui5-cal-header-btn-prev]") - .should("not.have.class", "ui5-calheader-arrowbtn-disabled"); - - cy.get("#calendar1") - .shadow() - .find(".ui5-calheader") - .find("[data-ui5-cal-header-btn-next]") - .should("have.class", "ui5-calheader-arrowbtn-disabled"); - }); - - it("Second month and year are rendered in the header", () => { - cy.mount(); - const timestamp = new Date(Date.UTC(2000, 9, 10, 0, 0, 0)).valueOf() / 1000; - - cy.get("#calendar1").invoke("prop", "timestamp", timestamp); - - cy.get("#calendar1") - .shadow() - .find(".ui5-calheader") - .find("[data-ui5-cal-header-btn-month] > span") - .should("have.length", 2); - - cy.get("#calendar1") - .shadow() - .find(".ui5-calheader") - .find("[data-ui5-cal-header-btn-year] > span") - .should("have.length", 2); - }); - - it("Buttons for month and year in header are rendered with correct value", () => { - cy.mount(); - const timestamp = new Date(Date.UTC(2000, 9, 10, 0, 0, 0)).valueOf() / 1000; - - cy.get("#calendar1").invoke("prop", "timestamp", timestamp); - - cy.get("#calendar1") - .shadow() - .find(".ui5-calheader") - .find("[data-ui5-cal-header-btn-month]") - .find("span") - .should(spans => { - expect(spans[0].textContent).to.equal("Rajab"); - expect(spans[1].textContent).to.equal("Sep – Oct"); - }); - - cy.get("#calendar1") - .shadow() - .find(".ui5-calheader") - .find("[data-ui5-cal-header-btn-year]") - .find("span") - .then(spans => { - expect(spans[0].textContent).to.equal("1421 AH"); - expect(spans[1].textContent).to.equal("2000"); - }); - }); - - it("Calendar render two type for Month when MonthPicker is opened", () => { - cy.mount(); - const timestamp = new Date(Date.UTC(2000, 0, 1, 0, 0, 0)).valueOf() / 1000; - - cy.get("#calendar1").invoke("prop", "timestamp", timestamp); - - cy.get("#calendar1") - .shadow() - .find(".ui5-calheader") - .find("[data-ui5-cal-header-btn-month]") - .realClick(); - - cy.get("#calendar1") - .shadow() - .find("[ui5-monthpicker]") - .shadow() - .find(".ui5-mp-item") - .first() - .find("span") - .should("have.length", 2) - .then(spans => { - expect(spans[0]).to.have.text("Muharram"); - expect(spans[1]).to.have.text("Apr – May"); - }); - }); - - it("Calendar renders secondary type for Year when Year Picker is opened", () => { - cy.mount( - - - ); - - - cy.get("[ui5-calendar]") - .as("calendar"); - - cy.get("@calendar") - .shadow() - .find(".ui5-calheader") - .find("[data-ui5-cal-header-btn-year]") - .realClick(); - - cy.get("@calendar") - .shadow() - .find("[ui5-yearpicker]") - .as("yearPicker"); - - cy.get("@yearPicker") - .shadow() - .find(".ui5-yp-item") - .should("have.length", 8) - .first() - .as("yearPickerItem"); - - cy.get("@yearPickerItem") - .find("span") - .should("have.length", 2) - .then(spans => { - expect(spans[0]).to.have.text("1414 AH"); - expect(spans[1]).to.have.text("1993 - 1994"); - }); - }); - - it("Calendar renders secondary type for Year Range Picker", () => { - cy.mount( - - - - ); - - cy.get("[ui5-calendar]") - .as("calendar"); - - cy.get("@calendar") - .ui5CalendarShowYearRangePicker(); - - cy.get("@calendar") - .shadow() - .find("[ui5-yearrangepicker]") - .as("yearRangePicker"); - - cy.get("@yearRangePicker") - .shadow() - .find(".ui5-yrp-item") - .should("have.length", 8) - .first() - .as("yearRangePickerItem"); - - cy.get("@yearRangePickerItem") - .find("span") - .should("have.length", 2) - .then(spans => { - expect(spans[0]).to.have.text("1398 AH - 1405 AH"); - expect(spans[1]).to.have.text("1977 - 1984"); - }); - }); - - it("Min and max dates are set without format-pattern by using ISO (yyyy-MM-dd) format", () => { - const maxDate = new Date(Date.UTC(2024, 9, 4, 0, 0, 0)).toISOString().split("T")[0]; - cy.mount(); - - cy.get("#calendar1") - .shadow() - .find(".ui5-calheader") - .find("[data-ui5-cal-header-btn-year]") - .realClick(); - - cy.get("#calendar1") - .shadow() - .find("[ui5-yearpicker]") - .shadow() - .find(".ui5-yp-root .ui5-yp-item") - .eq(11) // year 2025 - .should("have.class", "ui5-yp-item--disabled"); - }); - - it("Min and max dates are NOT set without format-pattern, because are not in ISO format (yyyy-MM-dd)", () => { - const maxDate = new Date(Date.UTC(2024, 9, 4, 0, 0, 0)).toString(); - cy.mount(); - - cy.get("#calendar1") - .shadow() - .find(".ui5-calheader") - .find("[data-ui5-cal-header-btn-year]") - .realClick(); - - cy.get("#calendar1") - .shadow() - .find("[ui5-yearpicker]") - .shadow() - .find(".ui5-yp-root .ui5-yp-item") - .eq(3) // year 2016 - .should("not.have.class", "ui5-yp-item--disabled"); - - cy.get("#calendar1") - .shadow() - .find("[ui5-yearpicker]") - .shadow() - .find(".ui5-yp-root .ui5-yp-item") - .eq(10) // year 2024 - .should("not.have.class", "ui5-yp-item--disabled"); - }); - - it("Year Ranges outside of the min and max dates are disabled", () => { - cy.mount( - - - - ); - - cy.get("[ui5-calendar]") - .as("calendar"); - - cy.get("@calendar") - .ui5CalendarShowYearRangePicker(); - - cy.get("@calendar") - .shadow() - .find("[ui5-yearrangepicker]") - .as("yearRangePicker"); - - cy.get("@yearRangePicker") - .shadow() - .find(".ui5-yrp-item") - .as("yearRangePickerItems"); - - cy.get("@yearRangePickerItems") - .should("have.length", 8); - - // Only the first 2 items are enabled (1998-2017 and 2018-2037) - cy.get("@yearRangePickerItems") - .first() // 1998-2017 - .as("firstItem"); - - cy.get("@firstItem") - .should("not.have.class", "ui5-yrp-item--disabled"); - - cy.get("@yearRangePickerItems") - .first() // 2018-2037 - .as("firstItem"); - - cy.get("@firstItem") - .should("not.have.class", "ui5-yrp-item--disabled"); - - cy.get("@yearRangePickerItems") - .eq(1) // 2038-2057 - .as("secondItem"); - - cy.get("@secondItem") - .should("not.have.class", "ui5-yrp-item--disabled"); - - cy.get("@yearRangePickerItems") - .eq(2) // 2003 - 2022 - .as("thirdItem"); - - cy.get("@thirdItem") - .should("have.class", "ui5-yrp-item--disabled"); - }); - - it("Focus goes into first selected day of the range selection", () => { - cy.mount( - - - ); - - const timestamp = new Date(Date.UTC(2021, 0, 20, 0, 0, 0)).valueOf() / 1000; // 1611100800 - - cy.get("#calendar1") - .shadow() - .find(".ui5-calheader") - .find("[data-ui5-cal-header-btn-month]") - .realClick(); - - cy.ui5CalendarGetMonth("#calendar1", timestamp.toString()) - .realClick(); - - cy.ui5CalendarGetDay("#calendar1", timestamp.toString()) - .should("have.focus"); - }); - - it("Special date respects format-pattern given to the calendar", () => { - cy.mount( - - - ); - - cy.get("#calendar1") - .shadow() - .find("[ui5-daypicker]") - .shadow() - .find(".ui5-dp-root") - .find("div[data-ui5-special-day]") - .should("have.length", 1); - }); - - it("Check calendar week numbers with specific CalendarWeekNumbering configuration", () => { - cy.mount(getCalendarsWithWeekNumbers()); - - // Check first week number in ISO_8601 calendar - cy.get("#calendar1") - .shadow() - .find("[ui5-daypicker]") - .shadow() - .find(".ui5-dp-weekname") - .first() - .should("have.text", "52"); - - // Check first week number in MiddleEastern calendar - cy.get("#calendar2") - .shadow() - .find("[ui5-daypicker]") - .shadow() - .find(".ui5-dp-weekname") - .first() - .should("have.text", "1"); - - // Check first week number in WesternTraditional calendar - cy.get("#calendar3") - .shadow() - .find("[ui5-daypicker]") - .shadow() - .find(".ui5-dp-weekname") - .first() - .should("have.text", "1"); - }); - - it("Check calendar week day names with specific CalendarWeekNumbering configuration", () => { - cy.mount(getCalendarsWithWeekNumbers()); - cy.get("#calendar1") - .shadow() - .find("[ui5-daypicker]") - .shadow() - .find(".ui5-dp-firstday") - .first() - .should("have.text", "Mon"); - - cy.get("#calendar2") - .shadow() - .find("[ui5-daypicker]") - .shadow() - .find(".ui5-dp-firstday") - .first() - .should("have.text", "Sat"); - - cy.get("#calendar3") - .shadow() - .find("[ui5-daypicker]") - .shadow() - .find(".ui5-dp-firstday") - .first() - .should("have.text", "Sun"); - }); -}); - -describe("Calendar accessibility", () => { - it("Should have proper aria-label attributes on header buttons", () => { - const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); - cy.mount(getDefaultCalendar(date)); - - cy.get("#calendar1") - .shadow() - .find(".ui5-calheader") - .as("calheader"); - - // Check month button aria-label - cy.get("@calheader") - .find("[data-ui5-cal-header-btn-month]") - .should("have.attr", "aria-label") - .and("contain", "Month November"); - - // Check year button aria-label - cy.get("@calheader") - .find("[data-ui5-cal-header-btn-year]") - .should("have.attr", "aria-label") - .and("contain", "Year 2000"); - }); - - it("Should have proper aria-description attributes on header buttons", () => { - const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); - cy.mount(getDefaultCalendar(date)); - - cy.get("#calendar1") - .shadow() - .find(".ui5-calheader") - .as("calheader"); - - // Check month button aria-description - cy.get("@calheader") - .find("[data-ui5-cal-header-btn-month]") - .should("have.attr", "aria-description") - .and("contain", "Month November"); - - // Check year button aria-description - cy.get("@calheader") - .find("[data-ui5-cal-header-btn-year]") - .should("have.attr", "aria-description") - .and("contain", "Year 2000"); - }); - - it("Should have proper title (tooltip) attributes on header buttons", () => { - const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); - cy.mount(getDefaultCalendar(date)); - - cy.get("#calendar1") - .shadow() - .find(".ui5-calheader") - .as("calheader"); - - // Check month button title includes both label and shortcut - cy.get("@calheader") - .find("[data-ui5-cal-header-btn-month]") - .should("have.attr", "title") - .and("contain", "Month November") - .and("contain", "(F4)"); - - // Check year button title includes both label and shortcut - cy.get("@calheader") - .find("[data-ui5-cal-header-btn-year]") - .should("have.attr", "title") - .and("contain", "Year 2000") - .and("contain", "(Shift + F4)"); - }); - - it("Should have proper aria-keyshortcuts attributes on header buttons", () => { - const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); - cy.mount(getDefaultCalendar(date)); - - cy.get("#calendar1") - .shadow() - .find(".ui5-calheader") - .as("calheader"); - - // Check month button keyboard shortcut - cy.get("@calheader") - .find("[data-ui5-cal-header-btn-month]") - .should("have.attr", "aria-keyshortcuts", "F4"); - - // Check year button keyboard shortcut - cy.get("@calheader") - .find("[data-ui5-cal-header-btn-year]") - .should("have.attr", "aria-keyshortcuts", "Shift + F4"); - }); - - it("Should have proper accessibility attributes on year range button when visible", () => { - const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); - cy.mount(getDefaultCalendar(date)); - - // Navigate to year picker first to make year range button visible - cy.get("#calendar1") - .shadow() - .find("[data-ui5-cal-header-btn-year]") - .realClick(); - - // Now check year range button accessibility attributes - cy.get("#calendar1") - .shadow() - .find(".ui5-calheader") - .find("[data-ui5-cal-header-btn-year-range]") - .as("yearRangeBtn"); - - // Check aria-label for year range - cy.get("@yearRangeBtn") - .should("have.attr", "aria-label") - .and("contain", "Year range from") - .and("contain", "1991") - .and("contain", "to") - .and("contain", "2010"); - - // Check aria-description for year range - cy.get("@yearRangeBtn") - .should("have.attr", "aria-description") - .and("contain", "Year range from") - .and("contain", "1991") - .and("contain", "to") - .and("contain", "2010"); - - // Check title includes both label and shortcut - cy.get("@yearRangeBtn") - .should("have.attr", "title") - .and("contain", "Year range from") - .and("contain", "1991") - .and("contain", "to") - .and("contain", "2010") - .and("contain", "(Shift + F4)"); - - // Check keyboard shortcut - cy.get("@yearRangeBtn") - .should("have.attr", "aria-keyshortcuts", "Shift + F4"); - }); - - it("Should update accessibility attributes when navigating between different months", () => { - const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); // November 2000 - cy.mount(getDefaultCalendar(date)); - cy.get("#calendar1") .shadow() .find(".ui5-calheader") .as("calheader"); - // Initial check - November 2000 cy.get("@calheader") - .find("[data-ui5-cal-header-btn-month]") - .should("have.attr", "aria-label") - .and("contain", "Month November"); + .should("exist"); - // Navigate to next month - cy.get("@calheader") - .find("[data-ui5-cal-header-btn-next]") - .realClick(); + cy.ui5CalendarGetDay("#calendar1", "974851200") + .as("selectedDay"); - // Check updated aria-label - December 2000 - cy.get("@calheader") - .find("[data-ui5-cal-header-btn-month]") - .should("have.attr", "aria-label") - .and("contain", "Month December"); + cy.realPress("Tab"); - // Navigate to previous month twice cy.get("@calheader") .find("[data-ui5-cal-header-btn-prev]") - .realClick() - .realClick(); - - // Check updated aria-label - October 2000 - cy.get("@calheader") - .find("[data-ui5-cal-header-btn-month]") - .should("have.attr", "aria-label") - .and("contain", "Month October"); - }); - - it("Should update accessibility attributes when navigating between different years", () => { - const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); // November 2000 - cy.mount(getDefaultCalendar(date)); - - cy.get("#calendar1") - .shadow() - .find(".ui5-calheader") - .as("calheader"); + .as("prevBtn"); - // Initial check - Year 2000 - cy.get("@calheader") - .find("[data-ui5-cal-header-btn-year]") - .should("have.attr", "aria-label") - .and("contain", "Year 2000"); - - // Navigate to day picker and use keyboard shortcuts to change year - cy.get("#calendar1") - .shadow() - .find("[ui5-daypicker]") - .shadow() - .find("[tabindex='0']") - .realClick() - .realPress(["Shift", "PageDown"]); // Next year - - // Check updated aria-label - Year 2001 - cy.get("@calheader") - .find("[data-ui5-cal-header-btn-year]") - .should("have.attr", "aria-label") - .and("contain", "Year 2001"); - - // Navigate back one year - cy.focused() - .realPress(["Shift", "PageUp"]); // Previous year - - // Check updated aria-label - Year 2000 - cy.get("@calheader") - .find("[data-ui5-cal-header-btn-year]") - .should("have.attr", "aria-label") - .and("contain", "Year 2000"); - }); - - it("Should maintain accessibility attributes consistency between primary and secondary calendar types", () => { - const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); - cy.mount( - - - - ); - - cy.get("#calendar1") - .shadow() - .find(".ui5-calheader") - .as("calheader"); + cy.get("@prevBtn") + .should("have.focus") + .realPress("Tab"); - // Check that month button still has proper aria-label with dual calendar cy.get("@calheader") .find("[data-ui5-cal-header-btn-month]") - .should("have.attr", "aria-label") - .and("contain", "Month"); - - // Check that year button still has proper aria-label with dual calendar - cy.get("@calheader") - .find("[data-ui5-cal-header-btn-year]") - .should("have.attr", "aria-label") - .and("contain", "Year"); + .should("have.focus") + .realPress("Tab"); - // Verify tooltips still contain shortcuts - cy.get("@calheader") - .find("[data-ui5-cal-header-btn-month]") - .should("have.attr", "title") - .and("contain", "(F4)"); + // cy.get("@calheader") + // .find("[data-ui5-cal-header-btn-year]") + // .should("have.focus") + // .realPress("Tab"); + + // cy.get("@calheader") + // .find("[data-ui5-cal-header-btn-next]") + // .should("have.focus") + // .realPress("Tab"); + + // cy.get("@selectedDay") + // .should("have.focus"); + // cy.get("@calheader") + // .find("[data-ui5-cal-header-btn-month]") + // .as("monthBtn"); + + // cy.get("@monthBtn") + // .should("have.focus") + // .realPress("Tab"); - cy.get("@calheader") - .find("[data-ui5-cal-header-btn-year]") - .should("have.attr", "title") - .and("contain", "(Shift + F4)"); - }); + // cy.get("@calheader") + // .find("[data-ui5-cal-header-btn-year]") + // .as("yearBtn"); + + // cy.get("@yearBtn") + // .should("have.focus") + // .realPress(["Shift", "Tab"]); - it("Should have proper aria-labels for range selection dates (First, Between, Last)", () => { - // Mount calendar with predefined range selection (Jan 20-22, 2021) similar to Calendar.html - cy.mount( - - - - ); + // cy.get("@monthBtn") + // .should("have.focus") + // .realPress(["Shift", "Tab"]); - // Find all selected day cells using the part attribute - cy.get("#calendar1") - .shadow() - .find("[ui5-daypicker]") - .shadow() - .find("[part*='day-cell-selected']") - .as("selectedDays"); + // cy.get("@selectedDay") + // .should("have.focus"); + }); - // Should have exactly 3 selected days (Jan 20, 21, 22) - cy.get("@selectedDays") - .should("have.length", 3); +// it("Calendar focuses the selected year when yearpicker is opened", () => { +// const YEAR = 1997; +// const date = Date.UTC(YEAR); +// cy.mount(getDefaultCalendar(new Date(date))); + +// cy.get("#calendar1") +// .shadow() +// .find(".ui5-calheader") +// .find("[data-ui5-cal-header-btn-year]") +// .realClick(); + +// cy.get("#calendar1") +// .shadow() +// .find("[ui5-yearpicker]") +// .shadow() +// .find("[tabindex='0']") +// .invoke("attr", "data-sap-timestamp") +// .then(_timestamp => { +// const focusedYear = new Date(parseInt(_timestamp!) * 1000).getUTCFullYear(); +// expect(focusedYear).to.equal(1997); +// }); +// }); + +// it("Calendar focuses the selected month when monthpicker is opened with space", () => { +// const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); +// cy.mount(getDefaultCalendar(date)); + +// cy.ui5CalendarGetDay("#calendar1", "974851200") +// .realClick(); + +// cy.focused().realPress("Tab"); +// cy.focused().realPress("Space"); + +// cy.get("#calendar1") +// .shadow() +// .find("[ui5-monthpicker]") +// .should("not.have.attr", "hidden"); + +// cy.get("#calendar1") +// .shadow() +// .find("[ui5-monthpicker]") +// .shadow() +// .find("[tabindex='0']") +// .invoke("attr", "data-sap-timestamp") +// .then(_timestamp => { +// const focusedMonth = new Date(parseInt(_timestamp!) * 1000).getUTCMonth(); +// expect(focusedMonth).to.equal(10); +// }); +// }); + +// it("Calendar focuses the selected year when yearpicker is opened with space", () => { +// const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); +// cy.mount(getDefaultCalendar(date)); + +// cy.ui5CalendarGetDay("#calendar1", "974851200") +// .realClick(); + +// cy.focused().realPress("Tab"); +// cy.focused().realPress("Tab"); +// cy.focused().realPress("Space"); + +// cy.get("#calendar1") +// .shadow() +// .find("[ui5-yearpicker]") +// .should("not.have.attr", "hidden"); + +// cy.get("#calendar1") +// .shadow() +// .find("[ui5-yearpicker]") +// .shadow() +// .find("[tabindex='0']") +// .invoke("attr", "data-sap-timestamp") +// .then(_timestamp => { +// const focusedYear = new Date(parseInt(_timestamp!) * 1000).getUTCFullYear(); +// expect(focusedYear).to.equal(2000); +// }); +// }); + +// it("Should focus the selected range when YearRange Picker is opened", () => { +// const YEAR = 1997; +// const date = Date.UTC(YEAR); +// const expectedRangeStart = 1988; +// const expectedRangeEnd = 2007; +// cy.mount(getDefaultCalendar(new Date(date))); + +// cy.get("[ui5-calendar]") +// .as("calendar"); + +// cy.get("@calendar") +// .ui5CalendarShowYearRangePicker(); + +// cy.get("@calendar") +// .shadow() +// .find("[ui5-yearrangepicker]") +// .as("yearRangePicker"); + +// cy.get("@yearRangePicker") +// .shadow() +// .find("[tabindex='0']") +// .as("focusedYearRange"); + +// cy.get("@focusedYearRange") +// .invoke("attr", "data-sap-timestamp") +// .then(_timestamp => { +// const focusedYear = new Date(parseInt(_timestamp!) * 1000).getUTCFullYear(); +// expect(focusedYear).to.equal(expectedRangeStart); +// }); + +// cy.get("@focusedYearRange") +// .find("span") +// .first() +// .should("have.text", `${expectedRangeStart} - ${expectedRangeEnd}`); +// }); + +// it("Calendar doesn't mark year as selected when there are no selected dates", () => { +// const todayDate = new Date(); +// const todayTimestamp = Date.UTC(todayDate.getFullYear(), todayDate.getMonth(), todayDate.getDate(), 0, 0, 0, 0) / 1000; + +// cy.mount(); + +// cy.get("#calendar2") +// .shadow() +// .find(".ui5-calheader") +// .find("[data-ui5-cal-header-btn-year]") +// .realClick(); + +// cy.get("#calendar2") +// .shadow() +// .find("[ui5-yearpicker]") +// .shadow() +// .find(`[data-sap-timestamp=${todayTimestamp}]`) +// .should("have.focus") +// .should("not.have.class", "ui5-yp-item--selected"); +// }); + +// it("Calendar doesn't mark month as selected when there are no selected dates", () => { +// const todayDate = new Date(); +// const todayTimestamp = Date.UTC(todayDate.getFullYear(), todayDate.getMonth(), todayDate.getDate(), 0, 0, 0, 0) / 1000; + +// cy.mount(); + +// cy.get("#calendar2") +// .shadow() +// .find(".ui5-calheader") +// .find("[data-ui5-cal-header-btn-month]") +// .realClick(); + +// cy.ui5CalendarGetMonth("#calendar2", todayTimestamp.toString()) +// .should("have.focus") +// .should("not.have.class", "ui5-mp-item--selected"); +// }); + +// it("Should navigate to Year Picker when selecting a range in Year Range Picker", () => { +// const YEAR = 1997; +// const date = Date.UTC(YEAR); +// const expectedRangeStart = 1948; +// const expectedRangeEnd = 1967; +// cy.mount(getDefaultCalendar(new Date(date))); + +// cy.get("[ui5-calendar]") +// .as("calendar"); + +// cy.get("@calendar") +// .ui5CalendarShowYearRangePicker(); + +// cy.get("@calendar") +// .shadow() +// .find("[ui5-yearrangepicker]") +// .as("yearRangePicker"); + +// cy.get("@yearRangePicker") +// .shadow() +// .find(".ui5-yrp-item") +// .first() // 1948 - 1967 +// .as("yearRangePickerItem"); + +// cy.get("@yearRangePickerItem") +// .find("span") +// .first() +// .should("have.text", `${expectedRangeStart} - ${expectedRangeEnd}`); + +// cy.get("@yearRangePickerItem") +// .realClick({position: "center"}); + +// cy.get("@calendar") +// .shadow() +// .find("[ui5-yearpicker]") +// .as("yearPicker"); + +// cy.get("@yearPicker") +// .should("be.visible"); + +// cy.get("@yearPicker") +// .shadow() +// .find(".ui5-yp-item") +// .first() +// .as("yearPickerItem"); + +// cy.get("@yearPickerItem") +// .invoke("attr", "data-sap-timestamp") +// .then(_timestamp => { +// const year = new Date(parseInt(_timestamp!) * 1000).getUTCFullYear(); +// expect(year).to.equal(expectedRangeStart); +// }); + +// }); + +// it("Page up/down increments/decrements the month value", () => { +// const date = new Date(Date.UTC(2000, 10, 1, 0, 0, 0)); +// cy.mount(getDefaultCalendar(date)); + +// cy.get("#calendar1") +// .shadow() +// .find("[ui5-daypicker]") +// .shadow() +// .find("[tabindex='0']") +// .realClick(); + +// cy.focused().realPress("PageUp"); + +// cy.get("#calendar1") +// .invoke("prop", "timestamp") +// .then(_timestamp => { +// expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(2000, 9, 1, 0, 0, 0))); +// }); + +// cy.focused().realPress("PageDown"); + +// cy.get("#calendar1") +// .invoke("prop", "timestamp") +// .then(_timestamp => { +// expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(2000, 10, 1, 0, 0, 0))); +// }); +// }); + +// it("Shift + Page up/down increments/decrements the year value by one", () => { +// const date = new Date(Date.UTC(2000, 10, 1, 0, 0, 0)); +// cy.mount(getDefaultCalendar(date)); + +// cy.get("#calendar1") +// .shadow() +// .find("[ui5-daypicker]") +// .shadow() +// .find("[tabindex='0']") +// .realClick(); + +// cy.focused().realPress(["Shift", "PageUp"]); + +// cy.get("#calendar1") +// .invoke("prop", "timestamp") +// .then(_timestamp => { +// expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(1999, 10, 1, 0, 0, 0))); +// }); + +// cy.focused().realPress(["Shift", "PageDown"]); + +// cy.get("#calendar1") +// .invoke("prop", "timestamp") +// .then(_timestamp => { +// expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(2000, 10, 1, 0, 0, 0))); +// }); +// }); + +// it("Ctrl + Shift + Page up/down increments/decrements the year value by ten", () => { +// const date = new Date(Date.UTC(2000, 10, 1, 0, 0, 0)); +// cy.mount(getDefaultCalendar(date)); + +// cy.get("#calendar1") +// .shadow() +// .find("[ui5-daypicker]") +// .shadow() +// .find("[tabindex='0']") +// .realClick(); + +// cy.focused().realPress(["Control", "Shift", "PageUp"]); + +// cy.get("#calendar1") +// .invoke("prop", "timestamp") +// .then(_timestamp => { +// expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(1990, 10, 1, 0, 0, 0))); +// }); + +// cy.focused().realPress(["Control", "Shift", "PageDown"]); + +// cy.get("#calendar1") +// .invoke("prop", "timestamp") +// .then(_timestamp => { +// expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(2000, 10, 1, 0, 0, 0))); +// }); +// }); + +// it("Page up/down increments/decrements the year value in the month picker", () => { +// const date = new Date(Date.UTC(2000, 9, 1, 0, 0, 0)); +// cy.mount(getDefaultCalendar(date)); + +// cy.get("#calendar1") +// .shadow() +// .find("[ui5-daypicker]") +// .shadow() +// .find("[tabindex='0']") +// .realClick(); + +// cy.focused().realPress("F4"); +// cy.focused().realPress("PageUp"); + +// cy.get("#calendar1") +// .invoke("prop", "timestamp") +// .then(_timestamp => { +// expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(1999, 9, 1, 0, 0, 0))); +// }); + +// cy.focused().realPress("PageDown"); + +// cy.get("#calendar1") +// .invoke("prop", "timestamp") +// .then(_timestamp => { +// expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(2000, 9, 1, 0, 0, 0))); +// }); +// }); + +// it("Page up/down increments/decrements the year range in the year picker", () => { +// const date = new Date(Date.UTC(2000, 9, 1, 0, 0, 0)); +// cy.mount(getDefaultCalendar(date)); + +// cy.get("#calendar1") +// .shadow() +// .find("[ui5-daypicker]") +// .shadow() +// .find("[tabindex='0']") +// .realClick() +// .should("have.focus"); + +// cy.focused().realPress(["Shift", "F4"]); + +// // Wait for focus to settle before proceeding +// cy.get("#calendar1") +// .shadow() +// .find("[ui5-yearpicker]") +// .shadow() +// .find("[tabindex='0']") +// .should("have.focus"); + +// cy.focused().realPress("PageUp"); + +// cy.get("#calendar1") +// .invoke("prop", "timestamp") +// .then(_timestamp => { +// expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(1980, 9, 1, 0, 0, 0))); +// }); + +// // Wait for focus to settle before proceeding +// cy.get("#calendar1") +// .shadow() +// .find("[ui5-yearpicker]") +// .shadow() +// .find("[tabindex='0']") +// .should("have.focus"); + +// cy.focused().realPress("PageDown"); + +// cy.get("#calendar1") +// .invoke("prop", "timestamp") +// .then(_timestamp => { +// expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(2000, 9, 1, 0, 0, 0))); +// }); +// }); + +// it("Navigation with Page down decrements the year ranges in the year range picker", () => { +// const date = new Date(Date.UTC(1998, 9, 16, 0, 0, 0)); +// cy.mount(getDefaultCalendar(date)); + +// cy.get("#calendar1") +// .ui5CalendarShowYearRangePicker(); + +// cy.get("#calendar1") +// .invoke("prop", "timestamp") +// .then(_timestamp => { +// expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(1998, 9, 16, 0, 0, 0))); +// }); + +// // Wait for focus to settle before proceeding +// cy.get("#calendar1") +// .shadow() +// .find("[ui5-yearrangepicker]") +// .shadow() +// .find("[tabindex='0']") +// .should("have.focus"); + +// cy.focused().realPress("PageUp"); + +// cy.get("#calendar1") +// .invoke("prop", "timestamp") +// .then(_timestamp => { +// expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(1838, 9, 16, 0, 0, 0))); +// }); +// }); - // Get the selected days and verify their aria-labels - cy.get("@selectedDays").each(($day, index) => { - cy.wrap($day).should("have.attr", "aria-label"); +// it("Navigation with Page up increments the year ranges in the year range picker", () => { +// const date = new Date(Date.UTC(1998, 9, 16, 0, 0, 0)); +// cy.mount(getDefaultCalendar(date)); + +// cy.get("#calendar1") +// .ui5CalendarShowYearRangePicker(); + +// cy.get("#calendar1") +// .invoke("prop", "timestamp") +// .then(_timestamp => { +// expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(1998, 9, 16, 0, 0, 0))); +// }); + +// // Wait for focus to settle before proceeding +// cy.get("#calendar1") +// .shadow() +// .find("[ui5-yearrangepicker]") +// .shadow() +// .find("[tabindex='0']") +// .should("have.focus"); + +// cy.focused().realPress("PageDown"); + +// cy.get("#calendar1") +// .invoke("prop", "timestamp") +// .then(_timestamp => { +// expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(2158, 9, 16, 0, 0, 0))); +// }); +// }); + +// it("Calendar with 'Multiple' selection type", () => { +// cy.mount(); +// const timestamp = new Date(Date.UTC(2000, 9, 10, 0, 0, 0)).valueOf() / 1000; + +// cy.get("#calendar1").invoke("prop", "timestamp", timestamp); + +// const timestamps = [971136000, 971222400, 971308800]; + +// timestamps.forEach(_timestamp => { +// cy.ui5CalendarGetDay("#calendar1", _timestamp.toString()) +// .as("date"); + +// cy.get("@date").realClick(); +// cy.get("@date").should("have.class", "ui5-dp-item--selected"); +// }); + +// cy.get("#calendar1") +// .invoke("prop", "selectedDates") +// .then(selectedDates => { +// expect(selectedDates.sort()).to.deep.equal(timestamps.sort()); +// }); +// }); + +// it("Keyboard navigation works properly, when calendar selection type is set to 'Multiple'", () => { +// cy.mount(); + +// const timestamp = new Date(Date.UTC(2000, 9, 10, 0, 0, 0)).valueOf() / 1000; + +// cy.get("#calendar1").invoke("prop", "timestamp", timestamp); + +// cy.ui5CalendarGetDay("#calendar1", timestamp.toString()) +// .focus() +// .should("have.focus"); + +// // Select the focused date +// cy.focused().realPress("Space"); + +// // Deselect the focused date +// cy.focused().realPress("Space"); +// cy.focused().realPress("ArrowRight"); + +// cy.ui5CalendarGetDay("#calendar1", "971222400") +// .should("have.focus"); +// }); + +// it("Calendar with 'Range' selection type", () => { +// cy.mount(); +// const timestamp = new Date(Date.UTC(2000, 9, 10, 0, 0, 0)).valueOf() / 1000; + +// cy.get("#calendar1").invoke("prop", "timestamp", timestamp); + +// const timestamps = [971740800, 971827200, 971913600]; + +// cy.ui5CalendarGetDay("#calendar1", timestamps[0].toString()) +// .realClick(); + +// cy.ui5CalendarGetDay("#calendar1", timestamps[2].toString()) +// .realClick(); + +// cy.ui5CalendarGetDay("#calendar1", timestamps[0].toString()) +// .should("have.class", "ui5-dp-item--selected"); + +// cy.ui5CalendarGetDay("#calendar1", timestamps[1].toString()) +// .should("have.class", "ui5-dp-item--selected-between"); + +// cy.ui5CalendarGetDay("#calendar1", timestamps[2].toString()) +// .should("have.class", "ui5-dp-item--selected"); + +// cy.get("#calendar1") +// .invoke("prop", "selectedDates") +// .then(selectedDates => { +// expect(selectedDates.sort()).to.deep.equal([timestamps[0], timestamps[2]].sort()); +// }); +// }); + +// it("Previous and next buttons are disabled when necessary", () => { +// cy.mount(<> +// +// +// +// ); +// const timestamp = 1594166400; + +// cy.get("#calendar1").invoke("prop", "timestamp", timestamp); + +// cy.get("#calendar1") +// .shadow() +// .find(".ui5-calheader") +// .find("[data-ui5-cal-header-btn-prev]") +// .should("have.class", "ui5-calheader-arrowbtn-disabled"); + +// cy.get("#calendar1") +// .shadow() +// .find(".ui5-calheader") +// .find("[data-ui5-cal-header-btn-next]") +// .should("not.have.class", "ui5-calheader-arrowbtn-disabled") +// .realClick(); + +// cy.get("#calendar1") +// .shadow() +// .find(".ui5-calheader") +// .find("[data-ui5-cal-header-btn-prev]") +// .should("not.have.class", "ui5-calheader-arrowbtn-disabled"); + +// cy.get("#calendar1") +// .shadow() +// .find(".ui5-calheader") +// .find("[data-ui5-cal-header-btn-next]") +// .should("not.have.class", "ui5-calheader-arrowbtn-disabled"); + +// cy.get("#calendar1") +// .shadow() +// .find(".ui5-calheader") +// .find("[data-ui5-cal-header-btn-next]") +// .realClick(); + +// cy.get("#calendar1") +// .shadow() +// .find(".ui5-calheader") +// .find("[data-ui5-cal-header-btn-next]") +// .realClick(); + +// cy.get("#calendar1") +// .shadow() +// .find(".ui5-calheader") +// .find("[data-ui5-cal-header-btn-prev]") +// .should("not.have.class", "ui5-calheader-arrowbtn-disabled"); + +// cy.get("#calendar1") +// .shadow() +// .find(".ui5-calheader") +// .find("[data-ui5-cal-header-btn-next]") +// .should("have.class", "ui5-calheader-arrowbtn-disabled"); +// }); + +// it("Second month and year are rendered in the header", () => { +// cy.mount(); +// const timestamp = new Date(Date.UTC(2000, 9, 10, 0, 0, 0)).valueOf() / 1000; + +// cy.get("#calendar1").invoke("prop", "timestamp", timestamp); + +// cy.get("#calendar1") +// .shadow() +// .find(".ui5-calheader") +// .find("[data-ui5-cal-header-btn-month] > span") +// .should("have.length", 2); + +// cy.get("#calendar1") +// .shadow() +// .find(".ui5-calheader") +// .find("[data-ui5-cal-header-btn-year] > span") +// .should("have.length", 2); +// }); + +// it("Buttons for month and year in header are rendered with correct value", () => { +// cy.mount(); +// const timestamp = new Date(Date.UTC(2000, 9, 10, 0, 0, 0)).valueOf() / 1000; + +// cy.get("#calendar1").invoke("prop", "timestamp", timestamp); + +// cy.get("#calendar1") +// .shadow() +// .find(".ui5-calheader") +// .find("[data-ui5-cal-header-btn-month]") +// .find("span") +// .should(spans => { +// expect(spans[0].textContent).to.equal("Rajab"); +// expect(spans[1].textContent).to.equal("Sep – Oct"); +// }); + +// cy.get("#calendar1") +// .shadow() +// .find(".ui5-calheader") +// .find("[data-ui5-cal-header-btn-year]") +// .find("span") +// .then(spans => { +// expect(spans[0].textContent).to.equal("1421 AH"); +// expect(spans[1].textContent).to.equal("2000"); +// }); +// }); + +// it("Calendar render two type for Month when MonthPicker is opened", () => { +// cy.mount(); +// const timestamp = new Date(Date.UTC(2000, 0, 1, 0, 0, 0)).valueOf() / 1000; + +// cy.get("#calendar1").invoke("prop", "timestamp", timestamp); + +// cy.get("#calendar1") +// .shadow() +// .find(".ui5-calheader") +// .find("[data-ui5-cal-header-btn-month]") +// .realClick(); + +// cy.get("#calendar1") +// .shadow() +// .find("[ui5-monthpicker]") +// .shadow() +// .find(".ui5-mp-item") +// .first() +// .find("span") +// .should("have.length", 2) +// .then(spans => { +// expect(spans[0]).to.have.text("Muharram"); +// expect(spans[1]).to.have.text("Apr – May"); +// }); +// }); + +// it("Calendar renders secondary type for Year when Year Picker is opened", () => { +// cy.mount( +// +// +// ); + + +// cy.get("[ui5-calendar]") +// .as("calendar"); + +// cy.get("@calendar") +// .shadow() +// .find(".ui5-calheader") +// .find("[data-ui5-cal-header-btn-year]") +// .realClick(); + +// cy.get("@calendar") +// .shadow() +// .find("[ui5-yearpicker]") +// .as("yearPicker"); + +// cy.get("@yearPicker") +// .shadow() +// .find(".ui5-yp-item") +// .should("have.length", 8) +// .first() +// .as("yearPickerItem"); + +// cy.get("@yearPickerItem") +// .find("span") +// .should("have.length", 2) +// .then(spans => { +// expect(spans[0]).to.have.text("1414 AH"); +// expect(spans[1]).to.have.text("1993 - 1994"); +// }); +// }); + +// it("Calendar renders secondary type for Year Range Picker", () => { +// cy.mount( +// +// +// +// ); + +// cy.get("[ui5-calendar]") +// .as("calendar"); + +// cy.get("@calendar") +// .ui5CalendarShowYearRangePicker(); + +// cy.get("@calendar") +// .shadow() +// .find("[ui5-yearrangepicker]") +// .as("yearRangePicker"); + +// cy.get("@yearRangePicker") +// .shadow() +// .find(".ui5-yrp-item") +// .should("have.length", 8) +// .first() +// .as("yearRangePickerItem"); + +// cy.get("@yearRangePickerItem") +// .find("span") +// .should("have.length", 2) +// .then(spans => { +// expect(spans[0]).to.have.text("1398 AH - 1405 AH"); +// expect(spans[1]).to.have.text("1977 - 1984"); +// }); +// }); + +// it("Min and max dates are set without format-pattern by using ISO (yyyy-MM-dd) format", () => { +// const maxDate = new Date(Date.UTC(2024, 9, 4, 0, 0, 0)).toISOString().split("T")[0]; +// cy.mount(); + +// cy.get("#calendar1") +// .shadow() +// .find(".ui5-calheader") +// .find("[data-ui5-cal-header-btn-year]") +// .realClick(); + +// cy.get("#calendar1") +// .shadow() +// .find("[ui5-yearpicker]") +// .shadow() +// .find(".ui5-yp-root .ui5-yp-item") +// .eq(11) // year 2025 +// .should("have.class", "ui5-yp-item--disabled"); +// }); + +// it("Min and max dates are NOT set without format-pattern, because are not in ISO format (yyyy-MM-dd)", () => { +// const maxDate = new Date(Date.UTC(2024, 9, 4, 0, 0, 0)).toString(); +// cy.mount(); + +// cy.get("#calendar1") +// .shadow() +// .find(".ui5-calheader") +// .find("[data-ui5-cal-header-btn-year]") +// .realClick(); + +// cy.get("#calendar1") +// .shadow() +// .find("[ui5-yearpicker]") +// .shadow() +// .find(".ui5-yp-root .ui5-yp-item") +// .eq(3) // year 2016 +// .should("not.have.class", "ui5-yp-item--disabled"); + +// cy.get("#calendar1") +// .shadow() +// .find("[ui5-yearpicker]") +// .shadow() +// .find(".ui5-yp-root .ui5-yp-item") +// .eq(10) // year 2024 +// .should("not.have.class", "ui5-yp-item--disabled"); +// }); + +// it("Year Ranges outside of the min and max dates are disabled", () => { +// cy.mount( +// +// +// +// ); + +// cy.get("[ui5-calendar]") +// .as("calendar"); + +// cy.get("@calendar") +// .ui5CalendarShowYearRangePicker(); + +// cy.get("@calendar") +// .shadow() +// .find("[ui5-yearrangepicker]") +// .as("yearRangePicker"); + +// cy.get("@yearRangePicker") +// .shadow() +// .find(".ui5-yrp-item") +// .as("yearRangePickerItems"); + +// cy.get("@yearRangePickerItems") +// .should("have.length", 8); + +// // Only the first 2 items are enabled (1998-2017 and 2018-2037) +// cy.get("@yearRangePickerItems") +// .first() // 1998-2017 +// .as("firstItem"); + +// cy.get("@firstItem") +// .should("not.have.class", "ui5-yrp-item--disabled"); + +// cy.get("@yearRangePickerItems") +// .first() // 2018-2037 +// .as("firstItem"); + +// cy.get("@firstItem") +// .should("not.have.class", "ui5-yrp-item--disabled"); + +// cy.get("@yearRangePickerItems") +// .eq(1) // 2038-2057 +// .as("secondItem"); + +// cy.get("@secondItem") +// .should("not.have.class", "ui5-yrp-item--disabled"); + +// cy.get("@yearRangePickerItems") +// .eq(2) // 2003 - 2022 +// .as("thirdItem"); + +// cy.get("@thirdItem") +// .should("have.class", "ui5-yrp-item--disabled"); +// }); + +// it("Focus goes into first selected day of the range selection", () => { +// cy.mount( +// +// +// ); + +// const timestamp = new Date(Date.UTC(2021, 0, 20, 0, 0, 0)).valueOf() / 1000; // 1611100800 + +// cy.get("#calendar1") +// .shadow() +// .find(".ui5-calheader") +// .find("[data-ui5-cal-header-btn-month]") +// .realClick(); + +// cy.ui5CalendarGetMonth("#calendar1", timestamp.toString()) +// .realClick(); + +// cy.ui5CalendarGetDay("#calendar1", timestamp.toString()) +// .should("have.focus"); +// }); + +// it("Special date respects format-pattern given to the calendar", () => { +// cy.mount( +// +// +// ); + +// cy.get("#calendar1") +// .shadow() +// .find("[ui5-daypicker]") +// .shadow() +// .find(".ui5-dp-root") +// .find("div[data-ui5-special-day]") +// .should("have.length", 1); +// }); + +// it("Check calendar week numbers with specific CalendarWeekNumbering configuration", () => { +// cy.mount(getCalendarsWithWeekNumbers()); + +// // Check first week number in ISO_8601 calendar +// cy.get("#calendar1") +// .shadow() +// .find("[ui5-daypicker]") +// .shadow() +// .find(".ui5-dp-weekname") +// .first() +// .should("have.text", "52"); + +// // Check first week number in MiddleEastern calendar +// cy.get("#calendar2") +// .shadow() +// .find("[ui5-daypicker]") +// .shadow() +// .find(".ui5-dp-weekname") +// .first() +// .should("have.text", "1"); + +// // Check first week number in WesternTraditional calendar +// cy.get("#calendar3") +// .shadow() +// .find("[ui5-daypicker]") +// .shadow() +// .find(".ui5-dp-weekname") +// .first() +// .should("have.text", "1"); +// }); + +// it("Check calendar week day names with specific CalendarWeekNumbering configuration", () => { +// cy.mount(getCalendarsWithWeekNumbers()); +// cy.get("#calendar1") +// .shadow() +// .find("[ui5-daypicker]") +// .shadow() +// .find(".ui5-dp-firstday") +// .first() +// .should("have.text", "Mon"); + +// cy.get("#calendar2") +// .shadow() +// .find("[ui5-daypicker]") +// .shadow() +// .find(".ui5-dp-firstday") +// .first() +// .should("have.text", "Sat"); + +// cy.get("#calendar3") +// .shadow() +// .find("[ui5-daypicker]") +// .shadow() +// .find(".ui5-dp-firstday") +// .first() +// .should("have.text", "Sun"); +// }); +// }); + +// describe("Calendar accessibility", () => { +// it("Should have proper aria-label attributes on header buttons", () => { +// const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); +// cy.mount(getDefaultCalendar(date)); + +// cy.get("#calendar1") +// .shadow() +// .find(".ui5-calheader") +// .as("calheader"); + +// // Check month button aria-label +// cy.get("@calheader") +// .find("[data-ui5-cal-header-btn-month]") +// .should("have.attr", "aria-label") +// .and("contain", "Month November"); + +// // Check year button aria-label +// cy.get("@calheader") +// .find("[data-ui5-cal-header-btn-year]") +// .should("have.attr", "aria-label") +// .and("contain", "Year 2000"); +// }); + +// it("Should have proper aria-description attributes on header buttons", () => { +// const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); +// cy.mount(getDefaultCalendar(date)); + +// cy.get("#calendar1") +// .shadow() +// .find(".ui5-calheader") +// .as("calheader"); + +// // Check month button aria-description +// cy.get("@calheader") +// .find("[data-ui5-cal-header-btn-month]") +// .should("have.attr", "aria-description") +// .and("contain", "Month November"); + +// // Check year button aria-description +// cy.get("@calheader") +// .find("[data-ui5-cal-header-btn-year]") +// .should("have.attr", "aria-description") +// .and("contain", "Year 2000"); +// }); + +// it("Should have proper title (tooltip) attributes on header buttons", () => { +// const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); +// cy.mount(getDefaultCalendar(date)); + +// cy.get("#calendar1") +// .shadow() +// .find(".ui5-calheader") +// .as("calheader"); + +// // Check month button title includes both label and shortcut +// cy.get("@calheader") +// .find("[data-ui5-cal-header-btn-month]") +// .should("have.attr", "title") +// .and("contain", "Month November") +// .and("contain", "(F4)"); + +// // Check year button title includes both label and shortcut +// cy.get("@calheader") +// .find("[data-ui5-cal-header-btn-year]") +// .should("have.attr", "title") +// .and("contain", "Year 2000") +// .and("contain", "(Shift + F4)"); +// }); + +// it("Should have proper aria-keyshortcuts attributes on header buttons", () => { +// const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); +// cy.mount(getDefaultCalendar(date)); + +// cy.get("#calendar1") +// .shadow() +// .find(".ui5-calheader") +// .as("calheader"); + +// // Check month button keyboard shortcut +// cy.get("@calheader") +// .find("[data-ui5-cal-header-btn-month]") +// .should("have.attr", "aria-keyshortcuts", "F4"); + +// // Check year button keyboard shortcut +// cy.get("@calheader") +// .find("[data-ui5-cal-header-btn-year]") +// .should("have.attr", "aria-keyshortcuts", "Shift + F4"); +// }); + +// it("Should have proper accessibility attributes on year range button when visible", () => { +// const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); +// cy.mount(getDefaultCalendar(date)); + +// // Navigate to year picker first to make year range button visible +// cy.get("#calendar1") +// .shadow() +// .find("[data-ui5-cal-header-btn-year]") +// .realClick(); + +// // Now check year range button accessibility attributes +// cy.get("#calendar1") +// .shadow() +// .find(".ui5-calheader") +// .find("[data-ui5-cal-header-btn-year-range]") +// .as("yearRangeBtn"); + +// // Check aria-label for year range +// cy.get("@yearRangeBtn") +// .should("have.attr", "aria-label") +// .and("contain", "Year range from") +// .and("contain", "1991") +// .and("contain", "to") +// .and("contain", "2010"); + +// // Check aria-description for year range +// cy.get("@yearRangeBtn") +// .should("have.attr", "aria-description") +// .and("contain", "Year range from") +// .and("contain", "1991") +// .and("contain", "to") +// .and("contain", "2010"); + +// // Check title includes both label and shortcut +// cy.get("@yearRangeBtn") +// .should("have.attr", "title") +// .and("contain", "Year range from") +// .and("contain", "1991") +// .and("contain", "to") +// .and("contain", "2010") +// .and("contain", "(Shift + F4)"); + +// // Check keyboard shortcut +// cy.get("@yearRangeBtn") +// .should("have.attr", "aria-keyshortcuts", "Shift + F4"); +// }); + +// it("Should update accessibility attributes when navigating between different months", () => { +// const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); // November 2000 +// cy.mount(getDefaultCalendar(date)); + +// cy.get("#calendar1") +// .shadow() +// .find(".ui5-calheader") +// .as("calheader"); + +// // Initial check - November 2000 +// cy.get("@calheader") +// .find("[data-ui5-cal-header-btn-month]") +// .should("have.attr", "aria-label") +// .and("contain", "Month November"); + +// // Navigate to next month +// cy.get("@calheader") +// .find("[data-ui5-cal-header-btn-next]") +// .realClick(); + +// // Check updated aria-label - December 2000 +// cy.get("@calheader") +// .find("[data-ui5-cal-header-btn-month]") +// .should("have.attr", "aria-label") +// .and("contain", "Month December"); + +// // Navigate to previous month twice +// cy.get("@calheader") +// .find("[data-ui5-cal-header-btn-prev]") +// .realClick() +// .realClick(); + +// // Check updated aria-label - October 2000 +// cy.get("@calheader") +// .find("[data-ui5-cal-header-btn-month]") +// .should("have.attr", "aria-label") +// .and("contain", "Month October"); +// }); + +// it("Should update accessibility attributes when navigating between different years", () => { +// const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); // November 2000 +// cy.mount(getDefaultCalendar(date)); + +// cy.get("#calendar1") +// .shadow() +// .find(".ui5-calheader") +// .as("calheader"); + +// // Initial check - Year 2000 +// cy.get("@calheader") +// .find("[data-ui5-cal-header-btn-year]") +// .should("have.attr", "aria-label") +// .and("contain", "Year 2000"); + +// // Navigate to day picker and use keyboard shortcuts to change year +// cy.get("#calendar1") +// .shadow() +// .find("[ui5-daypicker]") +// .shadow() +// .find("[tabindex='0']") +// .realClick() +// .realPress(["Shift", "PageDown"]); // Next year + +// // Check updated aria-label - Year 2001 +// cy.get("@calheader") +// .find("[data-ui5-cal-header-btn-year]") +// .should("have.attr", "aria-label") +// .and("contain", "Year 2001"); + +// // Navigate back one year +// cy.focused() +// .realPress(["Shift", "PageUp"]); // Previous year + +// // Check updated aria-label - Year 2000 +// cy.get("@calheader") +// .find("[data-ui5-cal-header-btn-year]") +// .should("have.attr", "aria-label") +// .and("contain", "Year 2000"); +// }); + +// it("Should maintain accessibility attributes consistency between primary and secondary calendar types", () => { +// const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); +// cy.mount( +// +// +// +// ); + +// cy.get("#calendar1") +// .shadow() +// .find(".ui5-calheader") +// .as("calheader"); + +// // Check that month button still has proper aria-label with dual calendar +// cy.get("@calheader") +// .find("[data-ui5-cal-header-btn-month]") +// .should("have.attr", "aria-label") +// .and("contain", "Month"); + +// // Check that year button still has proper aria-label with dual calendar +// cy.get("@calheader") +// .find("[data-ui5-cal-header-btn-year]") +// .should("have.attr", "aria-label") +// .and("contain", "Year"); + +// // Verify tooltips still contain shortcuts +// cy.get("@calheader") +// .find("[data-ui5-cal-header-btn-month]") +// .should("have.attr", "title") +// .and("contain", "(F4)"); + +// cy.get("@calheader") +// .find("[data-ui5-cal-header-btn-year]") +// .should("have.attr", "title") +// .and("contain", "(Shift + F4)"); +// }); + +// it("Should have proper aria-labels for range selection dates (First, Between, Last)", () => { +// // Mount calendar with predefined range selection (Jan 20-22, 2021) similar to Calendar.html +// cy.mount( +// +// +// +// ); + +// // Find all selected day cells using the part attribute +// cy.get("#calendar1") +// .shadow() +// .find("[ui5-daypicker]") +// .shadow() +// .find("[part*='day-cell-selected']") +// .as("selectedDays"); + +// // Should have exactly 3 selected days (Jan 20, 21, 22) +// cy.get("@selectedDays") +// .should("have.length", 3); + +// // Get the selected days and verify their aria-labels +// cy.get("@selectedDays").each(($day, index) => { +// cy.wrap($day).should("have.attr", "aria-label"); - if (index === 0) { - // First day should contain "First date of range" - cy.wrap($day) - .should("have.attr", "aria-label") - .and("contain", "First date of range"); - } else if (index === 1) { - // Middle day should contain "in a selected range" - cy.wrap($day) - .should("have.attr", "aria-label") - .and("contain", "in a selected range"); - } else if (index === 2) { - // Last day should contain "Last date of range" - cy.wrap($day) - .should("have.attr", "aria-label") - .and("contain", "Last date of range"); - } - }); - }); -}); - -describe("Day Picker Tests", () => { - it.skip("Select day with Space", () => { - cy.mount(); +// if (index === 0) { +// // First day should contain "First date of range" +// cy.wrap($day) +// .should("have.attr", "aria-label") +// .and("contain", "First date of range"); +// } else if (index === 1) { +// // Middle day should contain "in a selected range" +// cy.wrap($day) +// .should("have.attr", "aria-label") +// .and("contain", "in a selected range"); +// } else if (index === 2) { +// // Last day should contain "Last date of range" +// cy.wrap($day) +// .should("have.attr", "aria-label") +// .and("contain", "Last date of range"); +// } +// }); +// }); +// }); + +// describe("Day Picker Tests", () => { +// it.skip("Select day with Space", () => { +// cy.mount(); - cy.get("#calendar1") - .shadow() - .find("[ui5-daypicker]") - .shadow() - .find(".ui5-dp-item--now") - .as("today"); +// cy.get("#calendar1") +// .shadow() +// .find("[ui5-daypicker]") +// .shadow() +// .find(".ui5-dp-item--now") +// .as("today"); - cy.get("@today") - .realClick() - .should("be.focused") - .realPress("ArrowRight") - .realPress("Space"); +// cy.get("@today") +// .realClick() +// .should("be.focused") +// .realPress("ArrowRight") +// .realPress("Space"); - cy.focused() - .invoke("attr", "data-sap-timestamp") - .then(timestampAttr => { - const timestamp = parseInt(timestampAttr!); - const selectedDate = new Date(timestamp * 1000).getDate(); - const expectedDate = new Date(Date.now() + 24 * 3600 * 1000).getDate(); - expect(selectedDate).to.eq(expectedDate); - }); +// cy.focused() +// .invoke("attr", "data-sap-timestamp") +// .then(timestampAttr => { +// const timestamp = parseInt(timestampAttr!); +// const selectedDate = new Date(timestamp * 1000).getDate(); +// const expectedDate = new Date(Date.now() + 24 * 3600 * 1000).getDate(); +// expect(selectedDate).to.eq(expectedDate); +// }); - cy.get("#calendar1") - .should(($calendar) => { - const selectedDates = $calendar.prop("selectedDates"); - expect(selectedDates).to.have.length.greaterThan(0); - }); - }); - - it("Select day with Enter", () => { - const today = new Date(); - const tomorrow = Math.floor(Date.UTC(today.getFullYear(), today.getMonth(), today.getDate() + 1, 0, 0, 0, 0) / 1000); - - cy.mount(); +// cy.get("#calendar1") +// .should(($calendar) => { +// const selectedDates = $calendar.prop("selectedDates"); +// expect(selectedDates).to.have.length.greaterThan(0); +// }); +// }); + +// it("Select day with Enter", () => { +// const today = new Date(); +// const tomorrow = Math.floor(Date.UTC(today.getFullYear(), today.getMonth(), today.getDate() + 1, 0, 0, 0, 0) / 1000); + +// cy.mount(); - cy.get("#calendar1") - .shadow() - .find("[ui5-daypicker]") - .shadow() - .find(".ui5-dp-item--now") - .realClick(); - - // Wait for focus to settle before proceeding - cy.get("#calendar1") - .shadow() - .find("[ui5-daypicker]") - .shadow() - .find("[tabindex='0']") - .should("have.focus"); - - cy.get("#calendar1") - .realPress("ArrowRight"); - - cy.get("#calendar1") - .shadow() - .find("[ui5-daypicker]") - .shadow() - .find(`[data-sap-timestamp='${tomorrow}']`) - .should("have.focus"); - - cy.get("#calendar1") - .realPress("Enter"); - - // assert the date after today is selected - cy.get("#calendar1") - .should(($calendar) => { - const selectedDates = $calendar.prop("selectedDates"); - expect(selectedDates).to.include(tomorrow); - }); - }); - - it("Day names are correctly displayed", () => { - cy.mount(); +// cy.get("#calendar1") +// .shadow() +// .find("[ui5-daypicker]") +// .shadow() +// .find(".ui5-dp-item--now") +// .realClick(); + +// // Wait for focus to settle before proceeding +// cy.get("#calendar1") +// .shadow() +// .find("[ui5-daypicker]") +// .shadow() +// .find("[tabindex='0']") +// .should("have.focus"); + +// cy.get("#calendar1") +// .realPress("ArrowRight"); + +// cy.get("#calendar1") +// .shadow() +// .find("[ui5-daypicker]") +// .shadow() +// .find(`[data-sap-timestamp='${tomorrow}']`) +// .should("have.focus"); + +// cy.get("#calendar1") +// .realPress("Enter"); + +// // assert the date after today is selected +// cy.get("#calendar1") +// .should(($calendar) => { +// const selectedDates = $calendar.prop("selectedDates"); +// expect(selectedDates).to.include(tomorrow); +// }); +// }); + +// it("Day names are correctly displayed", () => { +// cy.mount(); - cy.get("#calendar1") - .shadow() - .find("[ui5-daypicker]") - .shadow() - .find(".ui5-dp-firstday") - .first() - .should("have.text", "Sun"); // English default - }); - - it("Day names container has proper structure", () => { - cy.mount(); - - cy.get("#calendar1") - .shadow() - .find("[ui5-daypicker]") - .shadow() - .find(".ui5-dp-days-names-container") - .should("exist") - .find("[role='columnheader']") - .should("have.length", 8); - }); - - it("Arrow navigation works in day picker", () => { - const date = new Date(Date.UTC(2000, 10, 15, 0, 0, 0)); - cy.mount(getDefaultCalendar(date)); - - const timestamp = new Date(Date.UTC(2000, 10, 15, 0, 0, 0)).valueOf() / 1000; - const nextDayTimestamp = new Date(Date.UTC(2000, 10, 16, 0, 0, 0)).valueOf() / 1000; - - cy.ui5CalendarGetDay("#calendar1", timestamp.toString()) - .realClick() - .should("have.focus"); - - cy.focused().realPress("ArrowRight"); - - cy.ui5CalendarGetDay("#calendar1", nextDayTimestamp.toString()) - .should("have.focus"); - - cy.focused().realPress("ArrowLeft"); - - cy.ui5CalendarGetDay("#calendar1", timestamp.toString()) - .should("have.focus"); - }); - - it("Today's date is highlighted correctly", () => { - cy.mount(); - - cy.get("#calendar1") - .shadow() - .find("[ui5-daypicker]") - .shadow() - .find(".ui5-dp-item--now") - .should("exist") - .and("be.visible") - .invoke("attr", "data-sap-timestamp") - .then(timestampAttr => { - const timestamp = parseInt(timestampAttr!); - const todayFromTimestamp = new Date(timestamp * 1000); - const actualToday = new Date(); +// cy.get("#calendar1") +// .shadow() +// .find("[ui5-daypicker]") +// .shadow() +// .find(".ui5-dp-firstday") +// .first() +// .should("have.text", "Sun"); // English default +// }); + +// it("Day names container has proper structure", () => { +// cy.mount(); + +// cy.get("#calendar1") +// .shadow() +// .find("[ui5-daypicker]") +// .shadow() +// .find(".ui5-dp-days-names-container") +// .should("exist") +// .find("[role='columnheader']") +// .should("have.length", 8); +// }); + +// it("Arrow navigation works in day picker", () => { +// const date = new Date(Date.UTC(2000, 10, 15, 0, 0, 0)); +// cy.mount(getDefaultCalendar(date)); + +// const timestamp = new Date(Date.UTC(2000, 10, 15, 0, 0, 0)).valueOf() / 1000; +// const nextDayTimestamp = new Date(Date.UTC(2000, 10, 16, 0, 0, 0)).valueOf() / 1000; + +// cy.ui5CalendarGetDay("#calendar1", timestamp.toString()) +// .realClick() +// .should("have.focus"); + +// cy.focused().realPress("ArrowRight"); + +// cy.ui5CalendarGetDay("#calendar1", nextDayTimestamp.toString()) +// .should("have.focus"); + +// cy.focused().realPress("ArrowLeft"); + +// cy.ui5CalendarGetDay("#calendar1", timestamp.toString()) +// .should("have.focus"); +// }); + +// it("Today's date is highlighted correctly", () => { +// cy.mount(); + +// cy.get("#calendar1") +// .shadow() +// .find("[ui5-daypicker]") +// .shadow() +// .find(".ui5-dp-item--now") +// .should("exist") +// .and("be.visible") +// .invoke("attr", "data-sap-timestamp") +// .then(timestampAttr => { +// const timestamp = parseInt(timestampAttr!); +// const todayFromTimestamp = new Date(timestamp * 1000); +// const actualToday = new Date(); - expect(todayFromTimestamp.getDate()).to.equal(actualToday.getDate()); - expect(todayFromTimestamp.getMonth()).to.equal(actualToday.getMonth()); - expect(todayFromTimestamp.getFullYear()).to.equal(actualToday.getFullYear()); - }); - }); -}); - -describe("Calendar Global Configuration", () => { - it("Should respect firstDayOfWeek from global formatSettings configuration", () => { - const configurationObject = { - "formatSettings": { - "firstDayOfWeek": 6 // Saturday - } - }; - - cy.window() - .then($el => { - const scriptElement = $el.document.createElement("script"); - scriptElement.type = "application/json"; - scriptElement.setAttribute("data-ui5-config", "true"); - scriptElement.innerHTML = JSON.stringify(configurationObject); - $el.document.head.appendChild(scriptElement); - }); - - cy.wrap({ resetConfiguration }) - .invoke("resetConfiguration", true); - - cy.wrap({ getFirstDayOfWeek }) - .invoke("getFirstDayOfWeek") - .should("equal", 6); - - const date = new Date(Date.UTC(2023, 0, 1, 0, 0, 0)); // January 1, 2023 - cy.mount(); - - cy.get("#calendar1") - .shadow() - .find("[ui5-daypicker]") - .shadow() - .find(".ui5-dp-firstday") - .first() - .should("have.text", "Sat"); - }); +// expect(todayFromTimestamp.getDate()).to.equal(actualToday.getDate()); +// expect(todayFromTimestamp.getMonth()).to.equal(actualToday.getMonth()); +// expect(todayFromTimestamp.getFullYear()).to.equal(actualToday.getFullYear()); +// }); +// }); +// }); + +// describe("Calendar Global Configuration", () => { +// it("Should respect firstDayOfWeek from global formatSettings configuration", () => { +// const configurationObject = { +// "formatSettings": { +// "firstDayOfWeek": 6 // Saturday +// } +// }; + +// cy.window() +// .then($el => { +// const scriptElement = $el.document.createElement("script"); +// scriptElement.type = "application/json"; +// scriptElement.setAttribute("data-ui5-config", "true"); +// scriptElement.innerHTML = JSON.stringify(configurationObject); +// $el.document.head.appendChild(scriptElement); +// }); + +// cy.wrap({ resetConfiguration }) +// .invoke("resetConfiguration", true); + +// cy.wrap({ getFirstDayOfWeek }) +// .invoke("getFirstDayOfWeek") +// .should("equal", 6); + +// const date = new Date(Date.UTC(2023, 0, 1, 0, 0, 0)); // January 1, 2023 +// cy.mount(); + +// cy.get("#calendar1") +// .shadow() +// .find("[ui5-daypicker]") +// .shadow() +// .find(".ui5-dp-firstday") +// .first() +// .should("have.text", "Sat"); +// }); }); From e3625d1c31f5dbda3d95e3a7f20e94b72dfc6f3f Mon Sep 17 00:00:00 2001 From: Georgi Damyanov Date: Tue, 25 Nov 2025 15:13:56 +0200 Subject: [PATCH 05/10] test: add test --- packages/main/cypress/specs/Calendar.cy.tsx | 2922 ++++++++++--------- 1 file changed, 1494 insertions(+), 1428 deletions(-) diff --git a/packages/main/cypress/specs/Calendar.cy.tsx b/packages/main/cypress/specs/Calendar.cy.tsx index e2a0106bf3db..8192d353ef3e 100644 --- a/packages/main/cypress/specs/Calendar.cy.tsx +++ b/packages/main/cypress/specs/Calendar.cy.tsx @@ -39,1460 +39,1526 @@ const getCalendarsWithWeekNumbers = () => (<> describe("Calendar general interaction", () => { it("Focus goes into the header items and then to the current day item of the day picker", () => { - const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); - cy.mount(getDefaultCalendar(date)); + const calendarTestDate = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); + cy.mount(getDefaultCalendar(calendarTestDate)); cy.get("#calendar1") .shadow() .find(".ui5-calheader") .as("calheader"); - cy.get("@calheader") - .should("exist"); + cy.ui5CalendarGetDay("#calendar1", "974851200").as("selectedDay"); - cy.ui5CalendarGetDay("#calendar1", "974851200") - .as("selectedDay"); + cy.get("#calendar1") + .realClick(); cy.realPress("Tab"); - + cy.get("@calheader") .find("[data-ui5-cal-header-btn-prev]") .as("prevBtn"); cy.get("@prevBtn") - .should("have.focus") - .realPress("Tab"); + .should("be.focused"); + + cy.realPress("Tab"); cy.get("@calheader") .find("[data-ui5-cal-header-btn-month]") - .should("have.focus") - .realPress("Tab"); - - // cy.get("@calheader") - // .find("[data-ui5-cal-header-btn-year]") - // .should("have.focus") - // .realPress("Tab"); - - // cy.get("@calheader") - // .find("[data-ui5-cal-header-btn-next]") - // .should("have.focus") - // .realPress("Tab"); - - // cy.get("@selectedDay") - // .should("have.focus"); - // cy.get("@calheader") - // .find("[data-ui5-cal-header-btn-month]") - // .as("monthBtn"); + .as("monthBtn"); + + cy.get("@monthBtn") + .should("be.focused"); + - // cy.get("@monthBtn") - // .should("have.focus") - // .realPress("Tab"); + cy.realPress("Tab"); - // cy.get("@calheader") - // .find("[data-ui5-cal-header-btn-year]") - // .as("yearBtn"); + cy.get("@calheader") + .find("[data-ui5-cal-header-btn-year]") + .as("yearBtn"); + + cy.get("@yearBtn") + .should("be.focused"); - // cy.get("@yearBtn") - // .should("have.focus") - // .realPress(["Shift", "Tab"]); + cy.realPress("Tab"); + + cy.get("@calheader") + .find("[data-ui5-cal-header-btn-next]") + .as("nextBtn"); - // cy.get("@monthBtn") - // .should("have.focus") - // .realPress(["Shift", "Tab"]); + cy.get("@nextBtn") + .should("be.focused"); + + cy.realPress("Tab"); - // cy.get("@selectedDay") - // .should("have.focus"); + cy.get("@selectedDay") + .should("be.focused"); }); -// it("Calendar focuses the selected year when yearpicker is opened", () => { -// const YEAR = 1997; -// const date = Date.UTC(YEAR); -// cy.mount(getDefaultCalendar(new Date(date))); - -// cy.get("#calendar1") -// .shadow() -// .find(".ui5-calheader") -// .find("[data-ui5-cal-header-btn-year]") -// .realClick(); - -// cy.get("#calendar1") -// .shadow() -// .find("[ui5-yearpicker]") -// .shadow() -// .find("[tabindex='0']") -// .invoke("attr", "data-sap-timestamp") -// .then(_timestamp => { -// const focusedYear = new Date(parseInt(_timestamp!) * 1000).getUTCFullYear(); -// expect(focusedYear).to.equal(1997); -// }); -// }); - -// it("Calendar focuses the selected month when monthpicker is opened with space", () => { -// const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); -// cy.mount(getDefaultCalendar(date)); - -// cy.ui5CalendarGetDay("#calendar1", "974851200") -// .realClick(); - -// cy.focused().realPress("Tab"); -// cy.focused().realPress("Space"); - -// cy.get("#calendar1") -// .shadow() -// .find("[ui5-monthpicker]") -// .should("not.have.attr", "hidden"); - -// cy.get("#calendar1") -// .shadow() -// .find("[ui5-monthpicker]") -// .shadow() -// .find("[tabindex='0']") -// .invoke("attr", "data-sap-timestamp") -// .then(_timestamp => { -// const focusedMonth = new Date(parseInt(_timestamp!) * 1000).getUTCMonth(); -// expect(focusedMonth).to.equal(10); -// }); -// }); - -// it("Calendar focuses the selected year when yearpicker is opened with space", () => { -// const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); -// cy.mount(getDefaultCalendar(date)); - -// cy.ui5CalendarGetDay("#calendar1", "974851200") -// .realClick(); - -// cy.focused().realPress("Tab"); -// cy.focused().realPress("Tab"); -// cy.focused().realPress("Space"); - -// cy.get("#calendar1") -// .shadow() -// .find("[ui5-yearpicker]") -// .should("not.have.attr", "hidden"); - -// cy.get("#calendar1") -// .shadow() -// .find("[ui5-yearpicker]") -// .shadow() -// .find("[tabindex='0']") -// .invoke("attr", "data-sap-timestamp") -// .then(_timestamp => { -// const focusedYear = new Date(parseInt(_timestamp!) * 1000).getUTCFullYear(); -// expect(focusedYear).to.equal(2000); -// }); -// }); - -// it("Should focus the selected range when YearRange Picker is opened", () => { -// const YEAR = 1997; -// const date = Date.UTC(YEAR); -// const expectedRangeStart = 1988; -// const expectedRangeEnd = 2007; -// cy.mount(getDefaultCalendar(new Date(date))); - -// cy.get("[ui5-calendar]") -// .as("calendar"); - -// cy.get("@calendar") -// .ui5CalendarShowYearRangePicker(); - -// cy.get("@calendar") -// .shadow() -// .find("[ui5-yearrangepicker]") -// .as("yearRangePicker"); - -// cy.get("@yearRangePicker") -// .shadow() -// .find("[tabindex='0']") -// .as("focusedYearRange"); - -// cy.get("@focusedYearRange") -// .invoke("attr", "data-sap-timestamp") -// .then(_timestamp => { -// const focusedYear = new Date(parseInt(_timestamp!) * 1000).getUTCFullYear(); -// expect(focusedYear).to.equal(expectedRangeStart); -// }); - -// cy.get("@focusedYearRange") -// .find("span") -// .first() -// .should("have.text", `${expectedRangeStart} - ${expectedRangeEnd}`); -// }); - -// it("Calendar doesn't mark year as selected when there are no selected dates", () => { -// const todayDate = new Date(); -// const todayTimestamp = Date.UTC(todayDate.getFullYear(), todayDate.getMonth(), todayDate.getDate(), 0, 0, 0, 0) / 1000; - -// cy.mount(); - -// cy.get("#calendar2") -// .shadow() -// .find(".ui5-calheader") -// .find("[data-ui5-cal-header-btn-year]") -// .realClick(); - -// cy.get("#calendar2") -// .shadow() -// .find("[ui5-yearpicker]") -// .shadow() -// .find(`[data-sap-timestamp=${todayTimestamp}]`) -// .should("have.focus") -// .should("not.have.class", "ui5-yp-item--selected"); -// }); - -// it("Calendar doesn't mark month as selected when there are no selected dates", () => { -// const todayDate = new Date(); -// const todayTimestamp = Date.UTC(todayDate.getFullYear(), todayDate.getMonth(), todayDate.getDate(), 0, 0, 0, 0) / 1000; - -// cy.mount(); - -// cy.get("#calendar2") -// .shadow() -// .find(".ui5-calheader") -// .find("[data-ui5-cal-header-btn-month]") -// .realClick(); - -// cy.ui5CalendarGetMonth("#calendar2", todayTimestamp.toString()) -// .should("have.focus") -// .should("not.have.class", "ui5-mp-item--selected"); -// }); - -// it("Should navigate to Year Picker when selecting a range in Year Range Picker", () => { -// const YEAR = 1997; -// const date = Date.UTC(YEAR); -// const expectedRangeStart = 1948; -// const expectedRangeEnd = 1967; -// cy.mount(getDefaultCalendar(new Date(date))); - -// cy.get("[ui5-calendar]") -// .as("calendar"); - -// cy.get("@calendar") -// .ui5CalendarShowYearRangePicker(); - -// cy.get("@calendar") -// .shadow() -// .find("[ui5-yearrangepicker]") -// .as("yearRangePicker"); - -// cy.get("@yearRangePicker") -// .shadow() -// .find(".ui5-yrp-item") -// .first() // 1948 - 1967 -// .as("yearRangePickerItem"); - -// cy.get("@yearRangePickerItem") -// .find("span") -// .first() -// .should("have.text", `${expectedRangeStart} - ${expectedRangeEnd}`); - -// cy.get("@yearRangePickerItem") -// .realClick({position: "center"}); - -// cy.get("@calendar") -// .shadow() -// .find("[ui5-yearpicker]") -// .as("yearPicker"); - -// cy.get("@yearPicker") -// .should("be.visible"); - -// cy.get("@yearPicker") -// .shadow() -// .find(".ui5-yp-item") -// .first() -// .as("yearPickerItem"); - -// cy.get("@yearPickerItem") -// .invoke("attr", "data-sap-timestamp") -// .then(_timestamp => { -// const year = new Date(parseInt(_timestamp!) * 1000).getUTCFullYear(); -// expect(year).to.equal(expectedRangeStart); -// }); - -// }); - -// it("Page up/down increments/decrements the month value", () => { -// const date = new Date(Date.UTC(2000, 10, 1, 0, 0, 0)); -// cy.mount(getDefaultCalendar(date)); - -// cy.get("#calendar1") -// .shadow() -// .find("[ui5-daypicker]") -// .shadow() -// .find("[tabindex='0']") -// .realClick(); - -// cy.focused().realPress("PageUp"); - -// cy.get("#calendar1") -// .invoke("prop", "timestamp") -// .then(_timestamp => { -// expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(2000, 9, 1, 0, 0, 0))); -// }); - -// cy.focused().realPress("PageDown"); - -// cy.get("#calendar1") -// .invoke("prop", "timestamp") -// .then(_timestamp => { -// expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(2000, 10, 1, 0, 0, 0))); -// }); -// }); - -// it("Shift + Page up/down increments/decrements the year value by one", () => { -// const date = new Date(Date.UTC(2000, 10, 1, 0, 0, 0)); -// cy.mount(getDefaultCalendar(date)); - -// cy.get("#calendar1") -// .shadow() -// .find("[ui5-daypicker]") -// .shadow() -// .find("[tabindex='0']") -// .realClick(); - -// cy.focused().realPress(["Shift", "PageUp"]); - -// cy.get("#calendar1") -// .invoke("prop", "timestamp") -// .then(_timestamp => { -// expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(1999, 10, 1, 0, 0, 0))); -// }); - -// cy.focused().realPress(["Shift", "PageDown"]); - -// cy.get("#calendar1") -// .invoke("prop", "timestamp") -// .then(_timestamp => { -// expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(2000, 10, 1, 0, 0, 0))); -// }); -// }); - -// it("Ctrl + Shift + Page up/down increments/decrements the year value by ten", () => { -// const date = new Date(Date.UTC(2000, 10, 1, 0, 0, 0)); -// cy.mount(getDefaultCalendar(date)); - -// cy.get("#calendar1") -// .shadow() -// .find("[ui5-daypicker]") -// .shadow() -// .find("[tabindex='0']") -// .realClick(); - -// cy.focused().realPress(["Control", "Shift", "PageUp"]); - -// cy.get("#calendar1") -// .invoke("prop", "timestamp") -// .then(_timestamp => { -// expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(1990, 10, 1, 0, 0, 0))); -// }); - -// cy.focused().realPress(["Control", "Shift", "PageDown"]); - -// cy.get("#calendar1") -// .invoke("prop", "timestamp") -// .then(_timestamp => { -// expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(2000, 10, 1, 0, 0, 0))); -// }); -// }); - -// it("Page up/down increments/decrements the year value in the month picker", () => { -// const date = new Date(Date.UTC(2000, 9, 1, 0, 0, 0)); -// cy.mount(getDefaultCalendar(date)); - -// cy.get("#calendar1") -// .shadow() -// .find("[ui5-daypicker]") -// .shadow() -// .find("[tabindex='0']") -// .realClick(); - -// cy.focused().realPress("F4"); -// cy.focused().realPress("PageUp"); - -// cy.get("#calendar1") -// .invoke("prop", "timestamp") -// .then(_timestamp => { -// expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(1999, 9, 1, 0, 0, 0))); -// }); - -// cy.focused().realPress("PageDown"); - -// cy.get("#calendar1") -// .invoke("prop", "timestamp") -// .then(_timestamp => { -// expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(2000, 9, 1, 0, 0, 0))); -// }); -// }); - -// it("Page up/down increments/decrements the year range in the year picker", () => { -// const date = new Date(Date.UTC(2000, 9, 1, 0, 0, 0)); -// cy.mount(getDefaultCalendar(date)); - -// cy.get("#calendar1") -// .shadow() -// .find("[ui5-daypicker]") -// .shadow() -// .find("[tabindex='0']") -// .realClick() -// .should("have.focus"); - -// cy.focused().realPress(["Shift", "F4"]); - -// // Wait for focus to settle before proceeding -// cy.get("#calendar1") -// .shadow() -// .find("[ui5-yearpicker]") -// .shadow() -// .find("[tabindex='0']") -// .should("have.focus"); - -// cy.focused().realPress("PageUp"); - -// cy.get("#calendar1") -// .invoke("prop", "timestamp") -// .then(_timestamp => { -// expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(1980, 9, 1, 0, 0, 0))); -// }); - -// // Wait for focus to settle before proceeding -// cy.get("#calendar1") -// .shadow() -// .find("[ui5-yearpicker]") -// .shadow() -// .find("[tabindex='0']") -// .should("have.focus"); - -// cy.focused().realPress("PageDown"); - -// cy.get("#calendar1") -// .invoke("prop", "timestamp") -// .then(_timestamp => { -// expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(2000, 9, 1, 0, 0, 0))); -// }); -// }); - -// it("Navigation with Page down decrements the year ranges in the year range picker", () => { -// const date = new Date(Date.UTC(1998, 9, 16, 0, 0, 0)); -// cy.mount(getDefaultCalendar(date)); - -// cy.get("#calendar1") -// .ui5CalendarShowYearRangePicker(); - -// cy.get("#calendar1") -// .invoke("prop", "timestamp") -// .then(_timestamp => { -// expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(1998, 9, 16, 0, 0, 0))); -// }); - -// // Wait for focus to settle before proceeding -// cy.get("#calendar1") -// .shadow() -// .find("[ui5-yearrangepicker]") -// .shadow() -// .find("[tabindex='0']") -// .should("have.focus"); - -// cy.focused().realPress("PageUp"); - -// cy.get("#calendar1") -// .invoke("prop", "timestamp") -// .then(_timestamp => { -// expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(1838, 9, 16, 0, 0, 0))); -// }); -// }); + it("Calendar focuses the selected year when yearpicker is opened", () => { + const YEAR = 1997; + const date = Date.UTC(YEAR); + cy.mount(getDefaultCalendar(new Date(date))); -// it("Navigation with Page up increments the year ranges in the year range picker", () => { -// const date = new Date(Date.UTC(1998, 9, 16, 0, 0, 0)); -// cy.mount(getDefaultCalendar(date)); - -// cy.get("#calendar1") -// .ui5CalendarShowYearRangePicker(); - -// cy.get("#calendar1") -// .invoke("prop", "timestamp") -// .then(_timestamp => { -// expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(1998, 9, 16, 0, 0, 0))); -// }); - -// // Wait for focus to settle before proceeding -// cy.get("#calendar1") -// .shadow() -// .find("[ui5-yearrangepicker]") -// .shadow() -// .find("[tabindex='0']") -// .should("have.focus"); - -// cy.focused().realPress("PageDown"); - -// cy.get("#calendar1") -// .invoke("prop", "timestamp") -// .then(_timestamp => { -// expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(2158, 9, 16, 0, 0, 0))); -// }); -// }); - -// it("Calendar with 'Multiple' selection type", () => { -// cy.mount(); -// const timestamp = new Date(Date.UTC(2000, 9, 10, 0, 0, 0)).valueOf() / 1000; - -// cy.get("#calendar1").invoke("prop", "timestamp", timestamp); - -// const timestamps = [971136000, 971222400, 971308800]; - -// timestamps.forEach(_timestamp => { -// cy.ui5CalendarGetDay("#calendar1", _timestamp.toString()) -// .as("date"); - -// cy.get("@date").realClick(); -// cy.get("@date").should("have.class", "ui5-dp-item--selected"); -// }); - -// cy.get("#calendar1") -// .invoke("prop", "selectedDates") -// .then(selectedDates => { -// expect(selectedDates.sort()).to.deep.equal(timestamps.sort()); -// }); -// }); - -// it("Keyboard navigation works properly, when calendar selection type is set to 'Multiple'", () => { -// cy.mount(); - -// const timestamp = new Date(Date.UTC(2000, 9, 10, 0, 0, 0)).valueOf() / 1000; - -// cy.get("#calendar1").invoke("prop", "timestamp", timestamp); - -// cy.ui5CalendarGetDay("#calendar1", timestamp.toString()) -// .focus() -// .should("have.focus"); - -// // Select the focused date -// cy.focused().realPress("Space"); - -// // Deselect the focused date -// cy.focused().realPress("Space"); -// cy.focused().realPress("ArrowRight"); - -// cy.ui5CalendarGetDay("#calendar1", "971222400") -// .should("have.focus"); -// }); - -// it("Calendar with 'Range' selection type", () => { -// cy.mount(); -// const timestamp = new Date(Date.UTC(2000, 9, 10, 0, 0, 0)).valueOf() / 1000; - -// cy.get("#calendar1").invoke("prop", "timestamp", timestamp); - -// const timestamps = [971740800, 971827200, 971913600]; - -// cy.ui5CalendarGetDay("#calendar1", timestamps[0].toString()) -// .realClick(); - -// cy.ui5CalendarGetDay("#calendar1", timestamps[2].toString()) -// .realClick(); - -// cy.ui5CalendarGetDay("#calendar1", timestamps[0].toString()) -// .should("have.class", "ui5-dp-item--selected"); - -// cy.ui5CalendarGetDay("#calendar1", timestamps[1].toString()) -// .should("have.class", "ui5-dp-item--selected-between"); - -// cy.ui5CalendarGetDay("#calendar1", timestamps[2].toString()) -// .should("have.class", "ui5-dp-item--selected"); - -// cy.get("#calendar1") -// .invoke("prop", "selectedDates") -// .then(selectedDates => { -// expect(selectedDates.sort()).to.deep.equal([timestamps[0], timestamps[2]].sort()); -// }); -// }); - -// it("Previous and next buttons are disabled when necessary", () => { -// cy.mount(<> -// -// -// -// ); -// const timestamp = 1594166400; - -// cy.get("#calendar1").invoke("prop", "timestamp", timestamp); - -// cy.get("#calendar1") -// .shadow() -// .find(".ui5-calheader") -// .find("[data-ui5-cal-header-btn-prev]") -// .should("have.class", "ui5-calheader-arrowbtn-disabled"); - -// cy.get("#calendar1") -// .shadow() -// .find(".ui5-calheader") -// .find("[data-ui5-cal-header-btn-next]") -// .should("not.have.class", "ui5-calheader-arrowbtn-disabled") -// .realClick(); - -// cy.get("#calendar1") -// .shadow() -// .find(".ui5-calheader") -// .find("[data-ui5-cal-header-btn-prev]") -// .should("not.have.class", "ui5-calheader-arrowbtn-disabled"); - -// cy.get("#calendar1") -// .shadow() -// .find(".ui5-calheader") -// .find("[data-ui5-cal-header-btn-next]") -// .should("not.have.class", "ui5-calheader-arrowbtn-disabled"); - -// cy.get("#calendar1") -// .shadow() -// .find(".ui5-calheader") -// .find("[data-ui5-cal-header-btn-next]") -// .realClick(); - -// cy.get("#calendar1") -// .shadow() -// .find(".ui5-calheader") -// .find("[data-ui5-cal-header-btn-next]") -// .realClick(); - -// cy.get("#calendar1") -// .shadow() -// .find(".ui5-calheader") -// .find("[data-ui5-cal-header-btn-prev]") -// .should("not.have.class", "ui5-calheader-arrowbtn-disabled"); - -// cy.get("#calendar1") -// .shadow() -// .find(".ui5-calheader") -// .find("[data-ui5-cal-header-btn-next]") -// .should("have.class", "ui5-calheader-arrowbtn-disabled"); -// }); - -// it("Second month and year are rendered in the header", () => { -// cy.mount(); -// const timestamp = new Date(Date.UTC(2000, 9, 10, 0, 0, 0)).valueOf() / 1000; - -// cy.get("#calendar1").invoke("prop", "timestamp", timestamp); - -// cy.get("#calendar1") -// .shadow() -// .find(".ui5-calheader") -// .find("[data-ui5-cal-header-btn-month] > span") -// .should("have.length", 2); - -// cy.get("#calendar1") -// .shadow() -// .find(".ui5-calheader") -// .find("[data-ui5-cal-header-btn-year] > span") -// .should("have.length", 2); -// }); - -// it("Buttons for month and year in header are rendered with correct value", () => { -// cy.mount(); -// const timestamp = new Date(Date.UTC(2000, 9, 10, 0, 0, 0)).valueOf() / 1000; - -// cy.get("#calendar1").invoke("prop", "timestamp", timestamp); - -// cy.get("#calendar1") -// .shadow() -// .find(".ui5-calheader") -// .find("[data-ui5-cal-header-btn-month]") -// .find("span") -// .should(spans => { -// expect(spans[0].textContent).to.equal("Rajab"); -// expect(spans[1].textContent).to.equal("Sep – Oct"); -// }); - -// cy.get("#calendar1") -// .shadow() -// .find(".ui5-calheader") -// .find("[data-ui5-cal-header-btn-year]") -// .find("span") -// .then(spans => { -// expect(spans[0].textContent).to.equal("1421 AH"); -// expect(spans[1].textContent).to.equal("2000"); -// }); -// }); - -// it("Calendar render two type for Month when MonthPicker is opened", () => { -// cy.mount(); -// const timestamp = new Date(Date.UTC(2000, 0, 1, 0, 0, 0)).valueOf() / 1000; - -// cy.get("#calendar1").invoke("prop", "timestamp", timestamp); - -// cy.get("#calendar1") -// .shadow() -// .find(".ui5-calheader") -// .find("[data-ui5-cal-header-btn-month]") -// .realClick(); - -// cy.get("#calendar1") -// .shadow() -// .find("[ui5-monthpicker]") -// .shadow() -// .find(".ui5-mp-item") -// .first() -// .find("span") -// .should("have.length", 2) -// .then(spans => { -// expect(spans[0]).to.have.text("Muharram"); -// expect(spans[1]).to.have.text("Apr – May"); -// }); -// }); - -// it("Calendar renders secondary type for Year when Year Picker is opened", () => { -// cy.mount( -// -// -// ); - - -// cy.get("[ui5-calendar]") -// .as("calendar"); - -// cy.get("@calendar") -// .shadow() -// .find(".ui5-calheader") -// .find("[data-ui5-cal-header-btn-year]") -// .realClick(); - -// cy.get("@calendar") -// .shadow() -// .find("[ui5-yearpicker]") -// .as("yearPicker"); - -// cy.get("@yearPicker") -// .shadow() -// .find(".ui5-yp-item") -// .should("have.length", 8) -// .first() -// .as("yearPickerItem"); - -// cy.get("@yearPickerItem") -// .find("span") -// .should("have.length", 2) -// .then(spans => { -// expect(spans[0]).to.have.text("1414 AH"); -// expect(spans[1]).to.have.text("1993 - 1994"); -// }); -// }); - -// it("Calendar renders secondary type for Year Range Picker", () => { -// cy.mount( -// -// -// -// ); - -// cy.get("[ui5-calendar]") -// .as("calendar"); - -// cy.get("@calendar") -// .ui5CalendarShowYearRangePicker(); - -// cy.get("@calendar") -// .shadow() -// .find("[ui5-yearrangepicker]") -// .as("yearRangePicker"); - -// cy.get("@yearRangePicker") -// .shadow() -// .find(".ui5-yrp-item") -// .should("have.length", 8) -// .first() -// .as("yearRangePickerItem"); - -// cy.get("@yearRangePickerItem") -// .find("span") -// .should("have.length", 2) -// .then(spans => { -// expect(spans[0]).to.have.text("1398 AH - 1405 AH"); -// expect(spans[1]).to.have.text("1977 - 1984"); -// }); -// }); - -// it("Min and max dates are set without format-pattern by using ISO (yyyy-MM-dd) format", () => { -// const maxDate = new Date(Date.UTC(2024, 9, 4, 0, 0, 0)).toISOString().split("T")[0]; -// cy.mount(); - -// cy.get("#calendar1") -// .shadow() -// .find(".ui5-calheader") -// .find("[data-ui5-cal-header-btn-year]") -// .realClick(); - -// cy.get("#calendar1") -// .shadow() -// .find("[ui5-yearpicker]") -// .shadow() -// .find(".ui5-yp-root .ui5-yp-item") -// .eq(11) // year 2025 -// .should("have.class", "ui5-yp-item--disabled"); -// }); - -// it("Min and max dates are NOT set without format-pattern, because are not in ISO format (yyyy-MM-dd)", () => { -// const maxDate = new Date(Date.UTC(2024, 9, 4, 0, 0, 0)).toString(); -// cy.mount(); - -// cy.get("#calendar1") -// .shadow() -// .find(".ui5-calheader") -// .find("[data-ui5-cal-header-btn-year]") -// .realClick(); - -// cy.get("#calendar1") -// .shadow() -// .find("[ui5-yearpicker]") -// .shadow() -// .find(".ui5-yp-root .ui5-yp-item") -// .eq(3) // year 2016 -// .should("not.have.class", "ui5-yp-item--disabled"); - -// cy.get("#calendar1") -// .shadow() -// .find("[ui5-yearpicker]") -// .shadow() -// .find(".ui5-yp-root .ui5-yp-item") -// .eq(10) // year 2024 -// .should("not.have.class", "ui5-yp-item--disabled"); -// }); - -// it("Year Ranges outside of the min and max dates are disabled", () => { -// cy.mount( -// -// -// -// ); - -// cy.get("[ui5-calendar]") -// .as("calendar"); - -// cy.get("@calendar") -// .ui5CalendarShowYearRangePicker(); - -// cy.get("@calendar") -// .shadow() -// .find("[ui5-yearrangepicker]") -// .as("yearRangePicker"); - -// cy.get("@yearRangePicker") -// .shadow() -// .find(".ui5-yrp-item") -// .as("yearRangePickerItems"); - -// cy.get("@yearRangePickerItems") -// .should("have.length", 8); - -// // Only the first 2 items are enabled (1998-2017 and 2018-2037) -// cy.get("@yearRangePickerItems") -// .first() // 1998-2017 -// .as("firstItem"); - -// cy.get("@firstItem") -// .should("not.have.class", "ui5-yrp-item--disabled"); - -// cy.get("@yearRangePickerItems") -// .first() // 2018-2037 -// .as("firstItem"); - -// cy.get("@firstItem") -// .should("not.have.class", "ui5-yrp-item--disabled"); - -// cy.get("@yearRangePickerItems") -// .eq(1) // 2038-2057 -// .as("secondItem"); - -// cy.get("@secondItem") -// .should("not.have.class", "ui5-yrp-item--disabled"); - -// cy.get("@yearRangePickerItems") -// .eq(2) // 2003 - 2022 -// .as("thirdItem"); - -// cy.get("@thirdItem") -// .should("have.class", "ui5-yrp-item--disabled"); -// }); - -// it("Focus goes into first selected day of the range selection", () => { -// cy.mount( -// -// -// ); - -// const timestamp = new Date(Date.UTC(2021, 0, 20, 0, 0, 0)).valueOf() / 1000; // 1611100800 - -// cy.get("#calendar1") -// .shadow() -// .find(".ui5-calheader") -// .find("[data-ui5-cal-header-btn-month]") -// .realClick(); - -// cy.ui5CalendarGetMonth("#calendar1", timestamp.toString()) -// .realClick(); - -// cy.ui5CalendarGetDay("#calendar1", timestamp.toString()) -// .should("have.focus"); -// }); - -// it("Special date respects format-pattern given to the calendar", () => { -// cy.mount( -// -// -// ); - -// cy.get("#calendar1") -// .shadow() -// .find("[ui5-daypicker]") -// .shadow() -// .find(".ui5-dp-root") -// .find("div[data-ui5-special-day]") -// .should("have.length", 1); -// }); - -// it("Check calendar week numbers with specific CalendarWeekNumbering configuration", () => { -// cy.mount(getCalendarsWithWeekNumbers()); - -// // Check first week number in ISO_8601 calendar -// cy.get("#calendar1") -// .shadow() -// .find("[ui5-daypicker]") -// .shadow() -// .find(".ui5-dp-weekname") -// .first() -// .should("have.text", "52"); - -// // Check first week number in MiddleEastern calendar -// cy.get("#calendar2") -// .shadow() -// .find("[ui5-daypicker]") -// .shadow() -// .find(".ui5-dp-weekname") -// .first() -// .should("have.text", "1"); - -// // Check first week number in WesternTraditional calendar -// cy.get("#calendar3") -// .shadow() -// .find("[ui5-daypicker]") -// .shadow() -// .find(".ui5-dp-weekname") -// .first() -// .should("have.text", "1"); -// }); - -// it("Check calendar week day names with specific CalendarWeekNumbering configuration", () => { -// cy.mount(getCalendarsWithWeekNumbers()); -// cy.get("#calendar1") -// .shadow() -// .find("[ui5-daypicker]") -// .shadow() -// .find(".ui5-dp-firstday") -// .first() -// .should("have.text", "Mon"); - -// cy.get("#calendar2") -// .shadow() -// .find("[ui5-daypicker]") -// .shadow() -// .find(".ui5-dp-firstday") -// .first() -// .should("have.text", "Sat"); - -// cy.get("#calendar3") -// .shadow() -// .find("[ui5-daypicker]") -// .shadow() -// .find(".ui5-dp-firstday") -// .first() -// .should("have.text", "Sun"); -// }); -// }); - -// describe("Calendar accessibility", () => { -// it("Should have proper aria-label attributes on header buttons", () => { -// const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); -// cy.mount(getDefaultCalendar(date)); - -// cy.get("#calendar1") -// .shadow() -// .find(".ui5-calheader") -// .as("calheader"); - -// // Check month button aria-label -// cy.get("@calheader") -// .find("[data-ui5-cal-header-btn-month]") -// .should("have.attr", "aria-label") -// .and("contain", "Month November"); - -// // Check year button aria-label -// cy.get("@calheader") -// .find("[data-ui5-cal-header-btn-year]") -// .should("have.attr", "aria-label") -// .and("contain", "Year 2000"); -// }); - -// it("Should have proper aria-description attributes on header buttons", () => { -// const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); -// cy.mount(getDefaultCalendar(date)); - -// cy.get("#calendar1") -// .shadow() -// .find(".ui5-calheader") -// .as("calheader"); - -// // Check month button aria-description -// cy.get("@calheader") -// .find("[data-ui5-cal-header-btn-month]") -// .should("have.attr", "aria-description") -// .and("contain", "Month November"); - -// // Check year button aria-description -// cy.get("@calheader") -// .find("[data-ui5-cal-header-btn-year]") -// .should("have.attr", "aria-description") -// .and("contain", "Year 2000"); -// }); - -// it("Should have proper title (tooltip) attributes on header buttons", () => { -// const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); -// cy.mount(getDefaultCalendar(date)); - -// cy.get("#calendar1") -// .shadow() -// .find(".ui5-calheader") -// .as("calheader"); - -// // Check month button title includes both label and shortcut -// cy.get("@calheader") -// .find("[data-ui5-cal-header-btn-month]") -// .should("have.attr", "title") -// .and("contain", "Month November") -// .and("contain", "(F4)"); - -// // Check year button title includes both label and shortcut -// cy.get("@calheader") -// .find("[data-ui5-cal-header-btn-year]") -// .should("have.attr", "title") -// .and("contain", "Year 2000") -// .and("contain", "(Shift + F4)"); -// }); - -// it("Should have proper aria-keyshortcuts attributes on header buttons", () => { -// const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); -// cy.mount(getDefaultCalendar(date)); - -// cy.get("#calendar1") -// .shadow() -// .find(".ui5-calheader") -// .as("calheader"); - -// // Check month button keyboard shortcut -// cy.get("@calheader") -// .find("[data-ui5-cal-header-btn-month]") -// .should("have.attr", "aria-keyshortcuts", "F4"); - -// // Check year button keyboard shortcut -// cy.get("@calheader") -// .find("[data-ui5-cal-header-btn-year]") -// .should("have.attr", "aria-keyshortcuts", "Shift + F4"); -// }); - -// it("Should have proper accessibility attributes on year range button when visible", () => { -// const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); -// cy.mount(getDefaultCalendar(date)); - -// // Navigate to year picker first to make year range button visible -// cy.get("#calendar1") -// .shadow() -// .find("[data-ui5-cal-header-btn-year]") -// .realClick(); - -// // Now check year range button accessibility attributes -// cy.get("#calendar1") -// .shadow() -// .find(".ui5-calheader") -// .find("[data-ui5-cal-header-btn-year-range]") -// .as("yearRangeBtn"); - -// // Check aria-label for year range -// cy.get("@yearRangeBtn") -// .should("have.attr", "aria-label") -// .and("contain", "Year range from") -// .and("contain", "1991") -// .and("contain", "to") -// .and("contain", "2010"); - -// // Check aria-description for year range -// cy.get("@yearRangeBtn") -// .should("have.attr", "aria-description") -// .and("contain", "Year range from") -// .and("contain", "1991") -// .and("contain", "to") -// .and("contain", "2010"); - -// // Check title includes both label and shortcut -// cy.get("@yearRangeBtn") -// .should("have.attr", "title") -// .and("contain", "Year range from") -// .and("contain", "1991") -// .and("contain", "to") -// .and("contain", "2010") -// .and("contain", "(Shift + F4)"); - -// // Check keyboard shortcut -// cy.get("@yearRangeBtn") -// .should("have.attr", "aria-keyshortcuts", "Shift + F4"); -// }); - -// it("Should update accessibility attributes when navigating between different months", () => { -// const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); // November 2000 -// cy.mount(getDefaultCalendar(date)); - -// cy.get("#calendar1") -// .shadow() -// .find(".ui5-calheader") -// .as("calheader"); - -// // Initial check - November 2000 -// cy.get("@calheader") -// .find("[data-ui5-cal-header-btn-month]") -// .should("have.attr", "aria-label") -// .and("contain", "Month November"); - -// // Navigate to next month -// cy.get("@calheader") -// .find("[data-ui5-cal-header-btn-next]") -// .realClick(); - -// // Check updated aria-label - December 2000 -// cy.get("@calheader") -// .find("[data-ui5-cal-header-btn-month]") -// .should("have.attr", "aria-label") -// .and("contain", "Month December"); - -// // Navigate to previous month twice -// cy.get("@calheader") -// .find("[data-ui5-cal-header-btn-prev]") -// .realClick() -// .realClick(); - -// // Check updated aria-label - October 2000 -// cy.get("@calheader") -// .find("[data-ui5-cal-header-btn-month]") -// .should("have.attr", "aria-label") -// .and("contain", "Month October"); -// }); - -// it("Should update accessibility attributes when navigating between different years", () => { -// const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); // November 2000 -// cy.mount(getDefaultCalendar(date)); - -// cy.get("#calendar1") -// .shadow() -// .find(".ui5-calheader") -// .as("calheader"); - -// // Initial check - Year 2000 -// cy.get("@calheader") -// .find("[data-ui5-cal-header-btn-year]") -// .should("have.attr", "aria-label") -// .and("contain", "Year 2000"); - -// // Navigate to day picker and use keyboard shortcuts to change year -// cy.get("#calendar1") -// .shadow() -// .find("[ui5-daypicker]") -// .shadow() -// .find("[tabindex='0']") -// .realClick() -// .realPress(["Shift", "PageDown"]); // Next year - -// // Check updated aria-label - Year 2001 -// cy.get("@calheader") -// .find("[data-ui5-cal-header-btn-year]") -// .should("have.attr", "aria-label") -// .and("contain", "Year 2001"); - -// // Navigate back one year -// cy.focused() -// .realPress(["Shift", "PageUp"]); // Previous year - -// // Check updated aria-label - Year 2000 -// cy.get("@calheader") -// .find("[data-ui5-cal-header-btn-year]") -// .should("have.attr", "aria-label") -// .and("contain", "Year 2000"); -// }); - -// it("Should maintain accessibility attributes consistency between primary and secondary calendar types", () => { -// const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); -// cy.mount( -// -// -// -// ); - -// cy.get("#calendar1") -// .shadow() -// .find(".ui5-calheader") -// .as("calheader"); - -// // Check that month button still has proper aria-label with dual calendar -// cy.get("@calheader") -// .find("[data-ui5-cal-header-btn-month]") -// .should("have.attr", "aria-label") -// .and("contain", "Month"); - -// // Check that year button still has proper aria-label with dual calendar -// cy.get("@calheader") -// .find("[data-ui5-cal-header-btn-year]") -// .should("have.attr", "aria-label") -// .and("contain", "Year"); - -// // Verify tooltips still contain shortcuts -// cy.get("@calheader") -// .find("[data-ui5-cal-header-btn-month]") -// .should("have.attr", "title") -// .and("contain", "(F4)"); - -// cy.get("@calheader") -// .find("[data-ui5-cal-header-btn-year]") -// .should("have.attr", "title") -// .and("contain", "(Shift + F4)"); -// }); - -// it("Should have proper aria-labels for range selection dates (First, Between, Last)", () => { -// // Mount calendar with predefined range selection (Jan 20-22, 2021) similar to Calendar.html -// cy.mount( -// -// -// -// ); - -// // Find all selected day cells using the part attribute -// cy.get("#calendar1") -// .shadow() -// .find("[ui5-daypicker]") -// .shadow() -// .find("[part*='day-cell-selected']") -// .as("selectedDays"); - -// // Should have exactly 3 selected days (Jan 20, 21, 22) -// cy.get("@selectedDays") -// .should("have.length", 3); - -// // Get the selected days and verify their aria-labels -// cy.get("@selectedDays").each(($day, index) => { -// cy.wrap($day).should("have.attr", "aria-label"); - -// if (index === 0) { -// // First day should contain "First date of range" -// cy.wrap($day) -// .should("have.attr", "aria-label") -// .and("contain", "First date of range"); -// } else if (index === 1) { -// // Middle day should contain "in a selected range" -// cy.wrap($day) -// .should("have.attr", "aria-label") -// .and("contain", "in a selected range"); -// } else if (index === 2) { -// // Last day should contain "Last date of range" -// cy.wrap($day) -// .should("have.attr", "aria-label") -// .and("contain", "Last date of range"); -// } -// }); -// }); -// }); - -// describe("Day Picker Tests", () => { -// it.skip("Select day with Space", () => { -// cy.mount(); - -// cy.get("#calendar1") -// .shadow() -// .find("[ui5-daypicker]") -// .shadow() -// .find(".ui5-dp-item--now") -// .as("today"); - -// cy.get("@today") -// .realClick() -// .should("be.focused") -// .realPress("ArrowRight") -// .realPress("Space"); - -// cy.focused() -// .invoke("attr", "data-sap-timestamp") -// .then(timestampAttr => { -// const timestamp = parseInt(timestampAttr!); -// const selectedDate = new Date(timestamp * 1000).getDate(); -// const expectedDate = new Date(Date.now() + 24 * 3600 * 1000).getDate(); -// expect(selectedDate).to.eq(expectedDate); -// }); + cy.get("#calendar1") + .shadow() + .find(".ui5-calheader") + .find("[data-ui5-cal-header-btn-year]") + .realClick(); + + cy.get("#calendar1") + .shadow() + .find("[ui5-yearpicker]") + .shadow() + .find("[tabindex='0']") + .invoke("attr", "data-sap-timestamp") + .then(_timestamp => { + const focusedYear = new Date(parseInt(_timestamp!) * 1000).getUTCFullYear(); + expect(focusedYear).to.equal(1997); + }); + }); + + it("Calendar focuses the selected month when monthpicker is opened with space", () => { + const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); + cy.mount(getDefaultCalendar(date)); + + cy.get("#calendar1") + .shadow() + .find(".ui5-calheader") + .as("calheader"); + + cy.ui5CalendarGetDay("#calendar1", "974851200").as("selectedDay"); + + cy.get("#calendar1") + .realClick(); + + cy.realPress("Tab"); -// cy.get("#calendar1") -// .should(($calendar) => { -// const selectedDates = $calendar.prop("selectedDates"); -// expect(selectedDates).to.have.length.greaterThan(0); -// }); -// }); - -// it("Select day with Enter", () => { -// const today = new Date(); -// const tomorrow = Math.floor(Date.UTC(today.getFullYear(), today.getMonth(), today.getDate() + 1, 0, 0, 0, 0) / 1000); - -// cy.mount(); + cy.get("@calheader") + .find("[data-ui5-cal-header-btn-prev]") + .as("prevBtn"); + + cy.get("@prevBtn") + .should("be.focused"); -// cy.get("#calendar1") -// .shadow() -// .find("[ui5-daypicker]") -// .shadow() -// .find(".ui5-dp-item--now") -// .realClick(); - -// // Wait for focus to settle before proceeding -// cy.get("#calendar1") -// .shadow() -// .find("[ui5-daypicker]") -// .shadow() -// .find("[tabindex='0']") -// .should("have.focus"); - -// cy.get("#calendar1") -// .realPress("ArrowRight"); - -// cy.get("#calendar1") -// .shadow() -// .find("[ui5-daypicker]") -// .shadow() -// .find(`[data-sap-timestamp='${tomorrow}']`) -// .should("have.focus"); - -// cy.get("#calendar1") -// .realPress("Enter"); - -// // assert the date after today is selected -// cy.get("#calendar1") -// .should(($calendar) => { -// const selectedDates = $calendar.prop("selectedDates"); -// expect(selectedDates).to.include(tomorrow); -// }); -// }); - -// it("Day names are correctly displayed", () => { -// cy.mount(); + cy.realPress("Tab"); + + cy.get("@calheader") + .find("[data-ui5-cal-header-btn-month]") + .as("monthBtn"); + + cy.realPress("Space"); + + cy.get("#calendar1") + .shadow() + .find("[ui5-monthpicker]") + .should("not.have.attr", "hidden"); + + cy.get("#calendar1") + .shadow() + .find("[ui5-monthpicker]") + .shadow() + .find("[tabindex='0']") + .invoke("attr", "data-sap-timestamp") + .then(_timestamp => { + const focusedMonth = new Date(parseInt(_timestamp!) * 1000).getUTCMonth(); + expect(focusedMonth).to.equal(10); + }); + }); + + it("Calendar focuses the selected year when yearpicker is opened with space", () => { + const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); + cy.mount(getDefaultCalendar(date)); + -// cy.get("#calendar1") -// .shadow() -// .find("[ui5-daypicker]") -// .shadow() -// .find(".ui5-dp-firstday") -// .first() -// .should("have.text", "Sun"); // English default -// }); - -// it("Day names container has proper structure", () => { -// cy.mount(); - -// cy.get("#calendar1") -// .shadow() -// .find("[ui5-daypicker]") -// .shadow() -// .find(".ui5-dp-days-names-container") -// .should("exist") -// .find("[role='columnheader']") -// .should("have.length", 8); -// }); - -// it("Arrow navigation works in day picker", () => { -// const date = new Date(Date.UTC(2000, 10, 15, 0, 0, 0)); -// cy.mount(getDefaultCalendar(date)); - -// const timestamp = new Date(Date.UTC(2000, 10, 15, 0, 0, 0)).valueOf() / 1000; -// const nextDayTimestamp = new Date(Date.UTC(2000, 10, 16, 0, 0, 0)).valueOf() / 1000; - -// cy.ui5CalendarGetDay("#calendar1", timestamp.toString()) -// .realClick() -// .should("have.focus"); - -// cy.focused().realPress("ArrowRight"); - -// cy.ui5CalendarGetDay("#calendar1", nextDayTimestamp.toString()) -// .should("have.focus"); - -// cy.focused().realPress("ArrowLeft"); - -// cy.ui5CalendarGetDay("#calendar1", timestamp.toString()) -// .should("have.focus"); -// }); - -// it("Today's date is highlighted correctly", () => { -// cy.mount(); - -// cy.get("#calendar1") -// .shadow() -// .find("[ui5-daypicker]") -// .shadow() -// .find(".ui5-dp-item--now") -// .should("exist") -// .and("be.visible") -// .invoke("attr", "data-sap-timestamp") -// .then(timestampAttr => { -// const timestamp = parseInt(timestampAttr!); -// const todayFromTimestamp = new Date(timestamp * 1000); -// const actualToday = new Date(); - -// expect(todayFromTimestamp.getDate()).to.equal(actualToday.getDate()); -// expect(todayFromTimestamp.getMonth()).to.equal(actualToday.getMonth()); -// expect(todayFromTimestamp.getFullYear()).to.equal(actualToday.getFullYear()); -// }); -// }); -// }); - -// describe("Calendar Global Configuration", () => { -// it("Should respect firstDayOfWeek from global formatSettings configuration", () => { -// const configurationObject = { -// "formatSettings": { -// "firstDayOfWeek": 6 // Saturday -// } -// }; - -// cy.window() -// .then($el => { -// const scriptElement = $el.document.createElement("script"); -// scriptElement.type = "application/json"; -// scriptElement.setAttribute("data-ui5-config", "true"); -// scriptElement.innerHTML = JSON.stringify(configurationObject); -// $el.document.head.appendChild(scriptElement); -// }); - -// cy.wrap({ resetConfiguration }) -// .invoke("resetConfiguration", true); - -// cy.wrap({ getFirstDayOfWeek }) -// .invoke("getFirstDayOfWeek") -// .should("equal", 6); - -// const date = new Date(Date.UTC(2023, 0, 1, 0, 0, 0)); // January 1, 2023 -// cy.mount(); - -// cy.get("#calendar1") -// .shadow() -// .find("[ui5-daypicker]") -// .shadow() -// .find(".ui5-dp-firstday") -// .first() -// .should("have.text", "Sat"); -// }); + cy.get("#calendar1") + .shadow() + .find(".ui5-calheader") + .as("calheader"); + + cy.ui5CalendarGetDay("#calendar1", "974851200").as("selectedDay"); + + cy.get("#calendar1") + .realClick(); + + cy.realPress("Tab"); + + cy.get("@calheader") + .find("[data-ui5-cal-header-btn-prev]") + .as("prevBtn"); + + cy.get("@prevBtn") + .should("be.focused"); + + cy.realPress("Tab"); + + cy.get("@calheader") + .find("[data-ui5-cal-header-btn-month]") + .as("monthBtn"); + + cy.get("@monthBtn") + .should("be.focused"); + + + cy.realPress("Tab"); + + cy.get("@calheader") + .find("[data-ui5-cal-header-btn-year]") + .as("yearBtn"); + + cy.get("@yearBtn") + .should("be.focused"); + + cy.realPress("Space"); + + cy.get("#calendar1") + .shadow() + .find("[ui5-yearpicker]") + .should("not.have.attr", "hidden"); + + cy.get("#calendar1") + .shadow() + .find("[ui5-yearpicker]") + .shadow() + .find("[tabindex='0']") + .invoke("attr", "data-sap-timestamp") + .then(_timestamp => { + const focusedYear = new Date(parseInt(_timestamp!) * 1000).getUTCFullYear(); + expect(focusedYear).to.equal(2000); + }); + }); + + it("Should focus the selected range when YearRange Picker is opened", () => { + const YEAR = 1997; + const date = Date.UTC(YEAR); + const expectedRangeStart = 1988; + const expectedRangeEnd = 2007; + cy.mount(getDefaultCalendar(new Date(date))); + + cy.get("[ui5-calendar]") + .as("calendar"); + + cy.get("@calendar") + .ui5CalendarShowYearRangePicker(); + + cy.get("@calendar") + .shadow() + .find("[ui5-yearrangepicker]") + .as("yearRangePicker"); + + cy.get("@yearRangePicker") + .shadow() + .find("[tabindex='0']") + .as("focusedYearRange"); + + cy.get("@focusedYearRange") + .invoke("attr", "data-sap-timestamp") + .then(_timestamp => { + const focusedYear = new Date(parseInt(_timestamp!) * 1000).getUTCFullYear(); + expect(focusedYear).to.equal(expectedRangeStart); + }); + + cy.get("@focusedYearRange") + .find("span") + .first() + .should("have.text", `${expectedRangeStart} - ${expectedRangeEnd}`); + }); + + it("Calendar doesn't mark year as selected when there are no selected dates", () => { + const todayDate = new Date(); + const todayTimestamp = Date.UTC(todayDate.getFullYear(), todayDate.getMonth(), todayDate.getDate(), 0, 0, 0, 0) / 1000; + + cy.mount(); + + cy.get("#calendar2") + .shadow() + .find(".ui5-calheader") + .find("[data-ui5-cal-header-btn-year]") + .realClick(); + + cy.get("#calendar2") + .shadow() + .find("[ui5-yearpicker]") + .shadow() + .find(`[data-sap-timestamp=${todayTimestamp}]`) + .should("have.focus") + .should("not.have.class", "ui5-yp-item--selected"); + }); + + it("Calendar doesn't mark month as selected when there are no selected dates", () => { + const todayDate = new Date(); + const todayTimestamp = Date.UTC(todayDate.getFullYear(), todayDate.getMonth(), todayDate.getDate(), 0, 0, 0, 0) / 1000; + + cy.mount(); + + cy.get("#calendar2") + .shadow() + .find(".ui5-calheader") + .find("[data-ui5-cal-header-btn-month]") + .realClick(); + + cy.ui5CalendarGetMonth("#calendar2", todayTimestamp.toString()) + .should("have.focus") + .should("not.have.class", "ui5-mp-item--selected"); + }); + + it("Should navigate to Year Picker when selecting a range in Year Range Picker", () => { + const YEAR = 1997; + const date = Date.UTC(YEAR); + const expectedRangeStart = 1948; + const expectedRangeEnd = 1967; + cy.mount(getDefaultCalendar(new Date(date))); + + cy.get("[ui5-calendar]") + .as("calendar"); + + cy.get("@calendar") + .ui5CalendarShowYearRangePicker(); + + cy.get("@calendar") + .shadow() + .find("[ui5-yearrangepicker]") + .as("yearRangePicker"); + + cy.get("@yearRangePicker") + .shadow() + .find(".ui5-yrp-item") + .first() // 1948 - 1967 + .as("yearRangePickerItem"); + + cy.get("@yearRangePickerItem") + .find("span") + .first() + .should("have.text", `${expectedRangeStart} - ${expectedRangeEnd}`); + + cy.get("@yearRangePickerItem") + .realClick({position: "center"}); + + cy.get("@calendar") + .shadow() + .find("[ui5-yearpicker]") + .as("yearPicker"); + + cy.get("@yearPicker") + .should("be.visible"); + + cy.get("@yearPicker") + .shadow() + .find(".ui5-yp-item") + .first() + .as("yearPickerItem"); + + cy.get("@yearPickerItem") + .invoke("attr", "data-sap-timestamp") + .then(_timestamp => { + const year = new Date(parseInt(_timestamp!) * 1000).getUTCFullYear(); + expect(year).to.equal(expectedRangeStart); + }); + + }); + + it("Page up/down increments/decrements the month value", () => { + const date = new Date(Date.UTC(2000, 10, 1, 0, 0, 0)); + cy.mount(getDefaultCalendar(date)); + + cy.get("#calendar1") + .shadow() + .find("[ui5-daypicker]") + .shadow() + .find("[tabindex='0']") + .realClick(); + + cy.focused().realPress("PageUp"); + + cy.get("#calendar1") + .invoke("prop", "timestamp") + .then(_timestamp => { + expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(2000, 9, 1, 0, 0, 0))); + }); + + cy.focused().realPress("PageDown"); + + cy.get("#calendar1") + .invoke("prop", "timestamp") + .then(_timestamp => { + expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(2000, 10, 1, 0, 0, 0))); + }); + }); + + it("Shift + Page up/down increments/decrements the year value by one", () => { + const date = new Date(Date.UTC(2000, 10, 1, 0, 0, 0)); + cy.mount(getDefaultCalendar(date)); + + cy.get("#calendar1") + .shadow() + .find("[ui5-daypicker]") + .shadow() + .find("[tabindex='0']") + .realClick(); + + cy.focused().realPress(["Shift", "PageUp"]); + + cy.get("#calendar1") + .invoke("prop", "timestamp") + .then(_timestamp => { + expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(1999, 10, 1, 0, 0, 0))); + }); + + cy.focused().realPress(["Shift", "PageDown"]); + + cy.get("#calendar1") + .invoke("prop", "timestamp") + .then(_timestamp => { + expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(2000, 10, 1, 0, 0, 0))); + }); + }); + + it("Ctrl + Shift + Page up/down increments/decrements the year value by ten", () => { + const date = new Date(Date.UTC(2000, 10, 1, 0, 0, 0)); + cy.mount(getDefaultCalendar(date)); + + cy.get("#calendar1") + .shadow() + .find("[ui5-daypicker]") + .shadow() + .find("[tabindex='0']") + .realClick(); + + cy.focused().realPress(["Control", "Shift", "PageUp"]); + + cy.get("#calendar1") + .invoke("prop", "timestamp") + .then(_timestamp => { + expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(1990, 10, 1, 0, 0, 0))); + }); + + cy.focused().realPress(["Control", "Shift", "PageDown"]); + + cy.get("#calendar1") + .invoke("prop", "timestamp") + .then(_timestamp => { + expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(2000, 10, 1, 0, 0, 0))); + }); + }); + + it("Page up/down increments/decrements the year value in the month picker", () => { + const date = new Date(Date.UTC(2000, 9, 1, 0, 0, 0)); + cy.mount(getDefaultCalendar(date)); + + cy.get("#calendar1") + .shadow() + .find("[ui5-daypicker]") + .shadow() + .find("[tabindex='0']") + .realClick(); + + cy.focused().realPress("F4"); + cy.focused().realPress("PageUp"); + + cy.get("#calendar1") + .invoke("prop", "timestamp") + .then(_timestamp => { + expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(1999, 9, 1, 0, 0, 0))); + }); + + cy.focused().realPress("PageDown"); + + cy.get("#calendar1") + .invoke("prop", "timestamp") + .then(_timestamp => { + expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(2000, 9, 1, 0, 0, 0))); + }); + }); + + it("Page up/down increments/decrements the year range in the year picker", () => { + const date = new Date(Date.UTC(2000, 9, 1, 0, 0, 0)); + cy.mount(getDefaultCalendar(date)); + + cy.get("#calendar1") + .shadow() + .find("[ui5-daypicker]") + .shadow() + .find("[tabindex='0']") + .realClick() + .should("have.focus"); + + cy.focused().realPress(["Shift", "F4"]); + + // Wait for focus to settle before proceeding + cy.get("#calendar1") + .shadow() + .find("[ui5-yearpicker]") + .shadow() + .find("[tabindex='0']") + .should("have.focus"); + + cy.focused().realPress("PageUp"); + + cy.get("#calendar1") + .invoke("prop", "timestamp") + .then(_timestamp => { + expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(1980, 9, 1, 0, 0, 0))); + }); + + // Wait for focus to settle before proceeding + cy.get("#calendar1") + .shadow() + .find("[ui5-yearpicker]") + .shadow() + .find("[tabindex='0']") + .should("have.focus"); + + cy.focused().realPress("PageDown"); + + cy.get("#calendar1") + .invoke("prop", "timestamp") + .then(_timestamp => { + expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(2000, 9, 1, 0, 0, 0))); + }); + }); + + it("Navigation with Page down decrements the year ranges in the year range picker", () => { + const date = new Date(Date.UTC(1998, 9, 16, 0, 0, 0)); + cy.mount(getDefaultCalendar(date)); + + cy.get("#calendar1") + .ui5CalendarShowYearRangePicker(); + + cy.get("#calendar1") + .invoke("prop", "timestamp") + .then(_timestamp => { + expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(1998, 9, 16, 0, 0, 0))); + }); + + // Wait for focus to settle before proceeding + cy.get("#calendar1") + .shadow() + .find("[ui5-yearrangepicker]") + .shadow() + .find("[tabindex='0']") + .should("have.focus"); + + cy.focused().realPress("PageUp"); + + cy.get("#calendar1") + .invoke("prop", "timestamp") + .then(_timestamp => { + expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(1838, 9, 16, 0, 0, 0))); + }); + }); + + it("Navigation with Page up increments the year ranges in the year range picker", () => { + const date = new Date(Date.UTC(1998, 9, 16, 0, 0, 0)); + cy.mount(getDefaultCalendar(date)); + + cy.get("#calendar1") + .ui5CalendarShowYearRangePicker(); + + cy.get("#calendar1") + .invoke("prop", "timestamp") + .then(_timestamp => { + expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(1998, 9, 16, 0, 0, 0))); + }); + + // Wait for focus to settle before proceeding + cy.get("#calendar1") + .shadow() + .find("[ui5-yearrangepicker]") + .shadow() + .find("[tabindex='0']") + .should("have.focus"); + + cy.focused().realPress("PageDown"); + + cy.get("#calendar1") + .invoke("prop", "timestamp") + .then(_timestamp => { + expect(new Date(_timestamp * 1000)).to.deep.equal(new Date(Date.UTC(2158, 9, 16, 0, 0, 0))); + }); + }); + + it("Calendar with 'Multiple' selection type", () => { + cy.mount(); + const timestamp = new Date(Date.UTC(2000, 9, 10, 0, 0, 0)).valueOf() / 1000; + + cy.get("#calendar1").invoke("prop", "timestamp", timestamp); + + const timestamps = [971136000, 971222400, 971308800]; + + timestamps.forEach(_timestamp => { + cy.ui5CalendarGetDay("#calendar1", _timestamp.toString()) + .as("date"); + + cy.get("@date").realClick(); + cy.get("@date").should("have.class", "ui5-dp-item--selected"); + }); + + cy.get("#calendar1") + .invoke("prop", "selectedDates") + .then(selectedDates => { + expect(selectedDates.sort()).to.deep.equal(timestamps.sort()); + }); + }); + + it("Keyboard navigation works properly, when calendar selection type is set to 'Multiple'", () => { + cy.mount(); + + const timestamp = new Date(Date.UTC(2000, 9, 10, 0, 0, 0)).valueOf() / 1000; + + cy.get("#calendar1").invoke("prop", "timestamp", timestamp); + + cy.ui5CalendarGetDay("#calendar1", timestamp.toString()) + .focus() + .should("have.focus"); + + // Select the focused date + cy.focused().realPress("Space"); + + // Deselect the focused date + cy.focused().realPress("Space"); + cy.focused().realPress("ArrowRight"); + + cy.ui5CalendarGetDay("#calendar1", "971222400") + .should("have.focus"); + }); + + it("Calendar with 'Range' selection type", () => { + cy.mount(); + const timestamp = new Date(Date.UTC(2000, 9, 10, 0, 0, 0)).valueOf() / 1000; + + cy.get("#calendar1").invoke("prop", "timestamp", timestamp); + + const timestamps = [971740800, 971827200, 971913600]; + + cy.ui5CalendarGetDay("#calendar1", timestamps[0].toString()) + .realClick(); + + cy.ui5CalendarGetDay("#calendar1", timestamps[2].toString()) + .realClick(); + + cy.ui5CalendarGetDay("#calendar1", timestamps[0].toString()) + .should("have.class", "ui5-dp-item--selected"); + + cy.ui5CalendarGetDay("#calendar1", timestamps[1].toString()) + .should("have.class", "ui5-dp-item--selected-between"); + + cy.ui5CalendarGetDay("#calendar1", timestamps[2].toString()) + .should("have.class", "ui5-dp-item--selected"); + + cy.get("#calendar1") + .invoke("prop", "selectedDates") + .then(selectedDates => { + expect(selectedDates.sort()).to.deep.equal([timestamps[0], timestamps[2]].sort()); + }); + }); + + it("Previous and next buttons are disabled when necessary", () => { + cy.mount(<> + + + + ); + const timestamp = 1594166400; + + cy.get("#calendar1").invoke("prop", "timestamp", timestamp); + + cy.get("#calendar1") + .shadow() + .find(".ui5-calheader") + .find("[data-ui5-cal-header-btn-prev]") + .should("have.class", "ui5-calheader-arrowbtn-disabled"); + + cy.get("#calendar1") + .shadow() + .find(".ui5-calheader") + .find("[data-ui5-cal-header-btn-next]") + .should("not.have.class", "ui5-calheader-arrowbtn-disabled") + .realClick(); + + cy.get("#calendar1") + .shadow() + .find(".ui5-calheader") + .find("[data-ui5-cal-header-btn-prev]") + .should("not.have.class", "ui5-calheader-arrowbtn-disabled"); + + cy.get("#calendar1") + .shadow() + .find(".ui5-calheader") + .find("[data-ui5-cal-header-btn-next]") + .should("not.have.class", "ui5-calheader-arrowbtn-disabled"); + + cy.get("#calendar1") + .shadow() + .find(".ui5-calheader") + .find("[data-ui5-cal-header-btn-next]") + .realClick(); + + cy.get("#calendar1") + .shadow() + .find(".ui5-calheader") + .find("[data-ui5-cal-header-btn-next]") + .realClick(); + + cy.get("#calendar1") + .shadow() + .find(".ui5-calheader") + .find("[data-ui5-cal-header-btn-prev]") + .should("not.have.class", "ui5-calheader-arrowbtn-disabled"); + + cy.get("#calendar1") + .shadow() + .find(".ui5-calheader") + .find("[data-ui5-cal-header-btn-next]") + .should("have.class", "ui5-calheader-arrowbtn-disabled"); + }); + + it("Second month and year are rendered in the header", () => { + cy.mount(); + const timestamp = new Date(Date.UTC(2000, 9, 10, 0, 0, 0)).valueOf() / 1000; + + cy.get("#calendar1").invoke("prop", "timestamp", timestamp); + + cy.get("#calendar1") + .shadow() + .find(".ui5-calheader") + .find("[data-ui5-cal-header-btn-month] > span") + .should("have.length", 2); + + cy.get("#calendar1") + .shadow() + .find(".ui5-calheader") + .find("[data-ui5-cal-header-btn-year] > span") + .should("have.length", 2); + }); + + it("Buttons for month and year in header are rendered with correct value", () => { + cy.mount(); + const timestamp = new Date(Date.UTC(2000, 9, 10, 0, 0, 0)).valueOf() / 1000; + + cy.get("#calendar1").invoke("prop", "timestamp", timestamp); + + cy.get("#calendar1") + .shadow() + .find(".ui5-calheader") + .find("[data-ui5-cal-header-btn-month]") + .find("span") + .should(spans => { + expect(spans[0].textContent).to.equal("Rajab"); + expect(spans[1].textContent).to.equal("Sep – Oct"); + }); + + cy.get("#calendar1") + .shadow() + .find(".ui5-calheader") + .find("[data-ui5-cal-header-btn-year]") + .find("span") + .then(spans => { + expect(spans[0].textContent).to.equal("1421 AH"); + expect(spans[1].textContent).to.equal("2000"); + }); + }); + + it("Calendar render two type for Month when MonthPicker is opened", () => { + cy.mount(); + const timestamp = new Date(Date.UTC(2000, 0, 1, 0, 0, 0)).valueOf() / 1000; + + cy.get("#calendar1").invoke("prop", "timestamp", timestamp); + + cy.get("#calendar1") + .shadow() + .find(".ui5-calheader") + .find("[data-ui5-cal-header-btn-month]") + .realClick(); + + cy.get("#calendar1") + .shadow() + .find("[ui5-monthpicker]") + .shadow() + .find(".ui5-mp-item") + .first() + .find("span") + .should("have.length", 2) + .then(spans => { + expect(spans[0]).to.have.text("Muharram"); + expect(spans[1]).to.have.text("Apr – May"); + }); + }); + + it("Calendar renders secondary type for Year when Year Picker is opened", () => { + cy.mount( + + + ); + + + cy.get("[ui5-calendar]") + .as("calendar"); + + cy.get("@calendar") + .shadow() + .find(".ui5-calheader") + .find("[data-ui5-cal-header-btn-year]") + .realClick(); + + cy.get("@calendar") + .shadow() + .find("[ui5-yearpicker]") + .as("yearPicker"); + + cy.get("@yearPicker") + .shadow() + .find(".ui5-yp-item") + .should("have.length", 8) + .first() + .as("yearPickerItem"); + + cy.get("@yearPickerItem") + .find("span") + .should("have.length", 2) + .then(spans => { + expect(spans[0]).to.have.text("1414 AH"); + expect(spans[1]).to.have.text("1993 - 1994"); + }); + }); + + it("Calendar renders secondary type for Year Range Picker", () => { + cy.mount( + + + + ); + + cy.get("[ui5-calendar]") + .as("calendar"); + + cy.get("@calendar") + .ui5CalendarShowYearRangePicker(); + + cy.get("@calendar") + .shadow() + .find("[ui5-yearrangepicker]") + .as("yearRangePicker"); + + cy.get("@yearRangePicker") + .shadow() + .find(".ui5-yrp-item") + .should("have.length", 8) + .first() + .as("yearRangePickerItem"); + + cy.get("@yearRangePickerItem") + .find("span") + .should("have.length", 2) + .then(spans => { + expect(spans[0]).to.have.text("1398 AH - 1405 AH"); + expect(spans[1]).to.have.text("1977 - 1984"); + }); + }); + + it("Min and max dates are set without format-pattern by using ISO (yyyy-MM-dd) format", () => { + const maxDate = new Date(Date.UTC(2024, 9, 4, 0, 0, 0)).toISOString().split("T")[0]; + cy.mount(); + + cy.get("#calendar1") + .shadow() + .find(".ui5-calheader") + .find("[data-ui5-cal-header-btn-year]") + .realClick(); + + cy.get("#calendar1") + .shadow() + .find("[ui5-yearpicker]") + .shadow() + .find(".ui5-yp-root .ui5-yp-item") + .eq(11) // year 2025 + .should("have.class", "ui5-yp-item--disabled"); + }); + + it("Min and max dates are NOT set without format-pattern, because are not in ISO format (yyyy-MM-dd)", () => { + const maxDate = new Date(Date.UTC(2024, 9, 4, 0, 0, 0)).toString(); + cy.mount(); + + cy.get("#calendar1") + .shadow() + .find(".ui5-calheader") + .find("[data-ui5-cal-header-btn-year]") + .realClick(); + + cy.get("#calendar1") + .shadow() + .find("[ui5-yearpicker]") + .shadow() + .find(".ui5-yp-root .ui5-yp-item") + .eq(3) // year 2016 + .should("not.have.class", "ui5-yp-item--disabled"); + + cy.get("#calendar1") + .shadow() + .find("[ui5-yearpicker]") + .shadow() + .find(".ui5-yp-root .ui5-yp-item") + .eq(10) // year 2024 + .should("not.have.class", "ui5-yp-item--disabled"); + }); + + it("Year Ranges outside of the min and max dates are disabled", () => { + cy.mount( + + + + ); + + cy.get("[ui5-calendar]") + .as("calendar"); + + cy.get("@calendar") + .ui5CalendarShowYearRangePicker(); + + cy.get("@calendar") + .shadow() + .find("[ui5-yearrangepicker]") + .as("yearRangePicker"); + + cy.get("@yearRangePicker") + .shadow() + .find(".ui5-yrp-item") + .as("yearRangePickerItems"); + + cy.get("@yearRangePickerItems") + .should("have.length", 8); + + // Only the first 2 items are enabled (1998-2017 and 2018-2037) + cy.get("@yearRangePickerItems") + .first() // 1998-2017 + .as("firstItem"); + + cy.get("@firstItem") + .should("not.have.class", "ui5-yrp-item--disabled"); + + cy.get("@yearRangePickerItems") + .first() // 2018-2037 + .as("firstItem"); + + cy.get("@firstItem") + .should("not.have.class", "ui5-yrp-item--disabled"); + + cy.get("@yearRangePickerItems") + .eq(1) // 2038-2057 + .as("secondItem"); + + cy.get("@secondItem") + .should("not.have.class", "ui5-yrp-item--disabled"); + + cy.get("@yearRangePickerItems") + .eq(2) // 2003 - 2022 + .as("thirdItem"); + + cy.get("@thirdItem") + .should("have.class", "ui5-yrp-item--disabled"); + }); + + it("Focus goes into first selected day of the range selection", () => { + cy.mount( + + + ); + + const timestamp = new Date(Date.UTC(2021, 0, 20, 0, 0, 0)).valueOf() / 1000; // 1611100800 + + cy.get("#calendar1") + .shadow() + .find(".ui5-calheader") + .find("[data-ui5-cal-header-btn-month]") + .realClick(); + + cy.ui5CalendarGetMonth("#calendar1", timestamp.toString()) + .realClick(); + + cy.ui5CalendarGetDay("#calendar1", timestamp.toString()) + .should("have.focus"); + }); + + it("Special date respects format-pattern given to the calendar", () => { + cy.mount( + + + ); + + cy.get("#calendar1") + .shadow() + .find("[ui5-daypicker]") + .shadow() + .find(".ui5-dp-root") + .find("div[data-ui5-special-day]") + .should("have.length", 1); + }); + + it("Check calendar week numbers with specific CalendarWeekNumbering configuration", () => { + cy.mount(getCalendarsWithWeekNumbers()); + + // Check first week number in ISO_8601 calendar + cy.get("#calendar1") + .shadow() + .find("[ui5-daypicker]") + .shadow() + .find(".ui5-dp-weekname") + .first() + .should("have.text", "52"); + + // Check first week number in MiddleEastern calendar + cy.get("#calendar2") + .shadow() + .find("[ui5-daypicker]") + .shadow() + .find(".ui5-dp-weekname") + .first() + .should("have.text", "1"); + + // Check first week number in WesternTraditional calendar + cy.get("#calendar3") + .shadow() + .find("[ui5-daypicker]") + .shadow() + .find(".ui5-dp-weekname") + .first() + .should("have.text", "1"); + }); + + it("Check calendar week day names with specific CalendarWeekNumbering configuration", () => { + cy.mount(getCalendarsWithWeekNumbers()); + cy.get("#calendar1") + .shadow() + .find("[ui5-daypicker]") + .shadow() + .find(".ui5-dp-firstday") + .first() + .should("have.text", "Mon"); + + cy.get("#calendar2") + .shadow() + .find("[ui5-daypicker]") + .shadow() + .find(".ui5-dp-firstday") + .first() + .should("have.text", "Sat"); + + cy.get("#calendar3") + .shadow() + .find("[ui5-daypicker]") + .shadow() + .find(".ui5-dp-firstday") + .first() + .should("have.text", "Sun"); + }); +}); + +describe("Calendar accessibility", () => { + it("Header prev/next buttons have correct title and tabindex", () => { + const date = new Date(Date.UTC(2025, 0, 15, 0, 0, 0)); + cy.mount(getDefaultCalendar(date)); + + cy.get("#calendar1") + .shadow() + .find(".ui5-calheader") + .as("calheader"); + + cy.get("@calheader") + .find("[data-ui5-cal-header-btn-prev]") + .should("have.attr", "title") + .and("contain", "Previous Month (Pagedown)"); + + cy.get("@calheader") + .find("[data-ui5-cal-header-btn-next]") + .should("have.attr", "title") + .and("contain", "Next Month (Pageup)"); + }); + + it("Should have proper aria-label attributes on header buttons", () => { + const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); + cy.mount(getDefaultCalendar(date)); + + cy.get("#calendar1") + .shadow() + .find(".ui5-calheader") + .as("calheader"); + + // Check month button aria-label + cy.get("@calheader") + .find("[data-ui5-cal-header-btn-month]") + .should("have.attr", "aria-label") + .and("contain", "Month November"); + + // Check year button aria-label + cy.get("@calheader") + .find("[data-ui5-cal-header-btn-year]") + .should("have.attr", "aria-label") + .and("contain", "Year 2000"); + }); + + it("Should have proper aria-description attributes on header buttons", () => { + const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); + cy.mount(getDefaultCalendar(date)); + + cy.get("#calendar1") + .shadow() + .find(".ui5-calheader") + .as("calheader"); + + // Check month button aria-description + cy.get("@calheader") + .find("[data-ui5-cal-header-btn-month]") + .should("have.attr", "aria-description") + .and("contain", "Month November"); + + // Check year button aria-description + cy.get("@calheader") + .find("[data-ui5-cal-header-btn-year]") + .should("have.attr", "aria-description") + .and("contain", "Year 2000"); + }); + + it("Should have proper title (tooltip) attributes on header buttons", () => { + const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); + cy.mount(getDefaultCalendar(date)); + + cy.get("#calendar1") + .shadow() + .find(".ui5-calheader") + .as("calheader"); + + // Check month button title includes both label and shortcut + cy.get("@calheader") + .find("[data-ui5-cal-header-btn-month]") + .should("have.attr", "title") + .and("contain", "Month November") + .and("contain", "(F4)"); + + // Check year button title includes both label and shortcut + cy.get("@calheader") + .find("[data-ui5-cal-header-btn-year]") + .should("have.attr", "title") + .and("contain", "Year 2000") + .and("contain", "(Shift + F4)"); + }); + + it("Should have proper aria-keyshortcuts attributes on header buttons", () => { + const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); + cy.mount(getDefaultCalendar(date)); + + cy.get("#calendar1") + .shadow() + .find(".ui5-calheader") + .as("calheader"); + + // Check month button keyboard shortcut + cy.get("@calheader") + .find("[data-ui5-cal-header-btn-month]") + .should("have.attr", "aria-keyshortcuts", "F4"); + + // Check year button keyboard shortcut + cy.get("@calheader") + .find("[data-ui5-cal-header-btn-year]") + .should("have.attr", "aria-keyshortcuts", "Shift + F4"); + }); + + it("Should have proper accessibility attributes on year range button when visible", () => { + const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); + cy.mount(getDefaultCalendar(date)); + + // Navigate to year picker first to make year range button visible + cy.get("#calendar1") + .shadow() + .find("[data-ui5-cal-header-btn-year]") + .realClick(); + + // Now check year range button accessibility attributes + cy.get("#calendar1") + .shadow() + .find(".ui5-calheader") + .find("[data-ui5-cal-header-btn-year-range]") + .as("yearRangeBtn"); + + // Check aria-label for year range + cy.get("@yearRangeBtn") + .should("have.attr", "aria-label") + .and("contain", "Year range from") + .and("contain", "1991") + .and("contain", "to") + .and("contain", "2010"); + + // Check aria-description for year range + cy.get("@yearRangeBtn") + .should("have.attr", "aria-description") + .and("contain", "Year range from") + .and("contain", "1991") + .and("contain", "to") + .and("contain", "2010"); + + // Check title includes both label and shortcut + cy.get("@yearRangeBtn") + .should("have.attr", "title") + .and("contain", "Year range from") + .and("contain", "1991") + .and("contain", "to") + .and("contain", "2010") + .and("contain", "(Shift + F4)"); + + // Check keyboard shortcut + cy.get("@yearRangeBtn") + .should("have.attr", "aria-keyshortcuts", "Shift + F4"); + }); + + it("Should update accessibility attributes when navigating between different months", () => { + const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); // November 2000 + cy.mount(getDefaultCalendar(date)); + + cy.get("#calendar1") + .shadow() + .find(".ui5-calheader") + .as("calheader"); + + // Initial check - November 2000 + cy.get("@calheader") + .find("[data-ui5-cal-header-btn-month]") + .should("have.attr", "aria-label") + .and("contain", "Month November"); + + // Navigate to next month + cy.get("@calheader") + .find("[data-ui5-cal-header-btn-next]") + .realClick(); + + // Check updated aria-label - December 2000 + cy.get("@calheader") + .find("[data-ui5-cal-header-btn-month]") + .should("have.attr", "aria-label") + .and("contain", "Month December"); + + // Navigate to previous month twice + cy.get("@calheader") + .find("[data-ui5-cal-header-btn-prev]") + .realClick() + .realClick(); + + // Check updated aria-label - October 2000 + cy.get("@calheader") + .find("[data-ui5-cal-header-btn-month]") + .should("have.attr", "aria-label") + .and("contain", "Month October"); + }); + + it("Should update accessibility attributes when navigating between different years", () => { + const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); // November 2000 + cy.mount(getDefaultCalendar(date)); + + cy.get("#calendar1") + .shadow() + .find(".ui5-calheader") + .as("calheader"); + + // Initial check - Year 2000 + cy.get("@calheader") + .find("[data-ui5-cal-header-btn-year]") + .should("have.attr", "aria-label") + .and("contain", "Year 2000"); + + // Navigate to day picker and use keyboard shortcuts to change year + cy.get("#calendar1") + .shadow() + .find("[ui5-daypicker]") + .shadow() + .find("[tabindex='0']") + .realClick() + .realPress(["Shift", "PageDown"]); // Next year + + // Check updated aria-label - Year 2001 + cy.get("@calheader") + .find("[data-ui5-cal-header-btn-year]") + .should("have.attr", "aria-label") + .and("contain", "Year 2001"); + + // Navigate back one year + cy.focused() + .realPress(["Shift", "PageUp"]); // Previous year + + // Check updated aria-label - Year 2000 + cy.get("@calheader") + .find("[data-ui5-cal-header-btn-year]") + .should("have.attr", "aria-label") + .and("contain", "Year 2000"); + }); + + it("Should maintain accessibility attributes consistency between primary and secondary calendar types", () => { + const date = new Date(Date.UTC(2000, 10, 22, 0, 0, 0)); + cy.mount( + + + + ); + + cy.get("#calendar1") + .shadow() + .find(".ui5-calheader") + .as("calheader"); + + // Check that month button still has proper aria-label with dual calendar + cy.get("@calheader") + .find("[data-ui5-cal-header-btn-month]") + .should("have.attr", "aria-label") + .and("contain", "Month"); + + // Check that year button still has proper aria-label with dual calendar + cy.get("@calheader") + .find("[data-ui5-cal-header-btn-year]") + .should("have.attr", "aria-label") + .and("contain", "Year"); + + // Verify tooltips still contain shortcuts + cy.get("@calheader") + .find("[data-ui5-cal-header-btn-month]") + .should("have.attr", "title") + .and("contain", "(F4)"); + + cy.get("@calheader") + .find("[data-ui5-cal-header-btn-year]") + .should("have.attr", "title") + .and("contain", "(Shift + F4)"); + }); + + it("Should have proper aria-labels for range selection dates (First, Between, Last)", () => { + // Mount calendar with predefined range selection (Jan 20-22, 2021) similar to Calendar.html + cy.mount( + + + + ); + + // Find all selected day cells using the part attribute + cy.get("#calendar1") + .shadow() + .find("[ui5-daypicker]") + .shadow() + .find("[part*='day-cell-selected']") + .as("selectedDays"); + + // Should have exactly 3 selected days (Jan 20, 21, 22) + cy.get("@selectedDays") + .should("have.length", 3); + + // Get the selected days and verify their aria-labels + cy.get("@selectedDays").each(($day, index) => { + cy.wrap($day).should("have.attr", "aria-label"); + + if (index === 0) { + // First day should contain "First date of range" + cy.wrap($day) + .should("have.attr", "aria-label") + .and("contain", "First date of range"); + } else if (index === 1) { + // Middle day should contain "in a selected range" + cy.wrap($day) + .should("have.attr", "aria-label") + .and("contain", "in a selected range"); + } else if (index === 2) { + // Last day should contain "Last date of range" + cy.wrap($day) + .should("have.attr", "aria-label") + .and("contain", "Last date of range"); + } + }); + }); +}); + +describe("Day Picker Tests", () => { + it.skip("Select day with Space", () => { + cy.mount(); + + cy.get("#calendar1") + .shadow() + .find("[ui5-daypicker]") + .shadow() + .find(".ui5-dp-item--now") + .as("today"); + + cy.get("@today") + .realClick() + .should("be.focused") + .realPress("ArrowRight") + .realPress("Space"); + + cy.focused() + .invoke("attr", "data-sap-timestamp") + .then(timestampAttr => { + const timestamp = parseInt(timestampAttr!); + const selectedDate = new Date(timestamp * 1000).getDate(); + const expectedDate = new Date(Date.now() + 24 * 3600 * 1000).getDate(); + expect(selectedDate).to.eq(expectedDate); + }); + + cy.get("#calendar1") + .should(($calendar) => { + const selectedDates = $calendar.prop("selectedDates"); + expect(selectedDates).to.have.length.greaterThan(0); + }); + }); + + it("Select day with Enter", () => { + const today = new Date(); + const tomorrow = Math.floor(Date.UTC(today.getFullYear(), today.getMonth(), today.getDate() + 1, 0, 0, 0, 0) / 1000); + + cy.mount(); + + cy.get("#calendar1") + .shadow() + .find("[ui5-daypicker]") + .shadow() + .find(".ui5-dp-item--now") + .realClick(); + + // Wait for focus to settle before proceeding + cy.get("#calendar1") + .shadow() + .find("[ui5-daypicker]") + .shadow() + .find("[tabindex='0']") + .should("have.focus"); + + cy.get("#calendar1") + .realPress("ArrowRight"); + + cy.get("#calendar1") + .shadow() + .find("[ui5-daypicker]") + .shadow() + .find(`[data-sap-timestamp='${tomorrow}']`) + .should("have.focus"); + + cy.get("#calendar1") + .realPress("Enter"); + + // assert the date after today is selected + cy.get("#calendar1") + .should(($calendar) => { + const selectedDates = $calendar.prop("selectedDates"); + expect(selectedDates).to.include(tomorrow); + }); + }); + + it("Day names are correctly displayed", () => { + cy.mount(); + + cy.get("#calendar1") + .shadow() + .find("[ui5-daypicker]") + .shadow() + .find(".ui5-dp-firstday") + .first() + .should("have.text", "Sun"); // English default + }); + + it("Day names container has proper structure", () => { + cy.mount(); + + cy.get("#calendar1") + .shadow() + .find("[ui5-daypicker]") + .shadow() + .find(".ui5-dp-days-names-container") + .should("exist") + .find("[role='columnheader']") + .should("have.length", 8); + }); + + it("Arrow navigation works in day picker", () => { + const date = new Date(Date.UTC(2000, 10, 15, 0, 0, 0)); + cy.mount(getDefaultCalendar(date)); + + const timestamp = new Date(Date.UTC(2000, 10, 15, 0, 0, 0)).valueOf() / 1000; + const nextDayTimestamp = new Date(Date.UTC(2000, 10, 16, 0, 0, 0)).valueOf() / 1000; + + cy.ui5CalendarGetDay("#calendar1", timestamp.toString()) + .realClick() + .should("have.focus"); + + cy.focused().realPress("ArrowRight"); + + cy.ui5CalendarGetDay("#calendar1", nextDayTimestamp.toString()) + .should("have.focus"); + + cy.focused().realPress("ArrowLeft"); + + cy.ui5CalendarGetDay("#calendar1", timestamp.toString()) + .should("have.focus"); + }); + + it("Today's date is highlighted correctly", () => { + cy.mount(); + + cy.get("#calendar1") + .shadow() + .find("[ui5-daypicker]") + .shadow() + .find(".ui5-dp-item--now") + .should("exist") + .and("be.visible") + .invoke("attr", "data-sap-timestamp") + .then(timestampAttr => { + const timestamp = parseInt(timestampAttr!); + const todayFromTimestamp = new Date(timestamp * 1000); + const actualToday = new Date(); + + expect(todayFromTimestamp.getDate()).to.equal(actualToday.getDate()); + expect(todayFromTimestamp.getMonth()).to.equal(actualToday.getMonth()); + expect(todayFromTimestamp.getFullYear()).to.equal(actualToday.getFullYear()); + }); + }); +}); + +describe("Calendar Global Configuration", () => { + it("Should respect firstDayOfWeek from global formatSettings configuration", () => { + const configurationObject = { + "formatSettings": { + "firstDayOfWeek": 6 // Saturday + } + }; + + cy.window() + .then($el => { + const scriptElement = $el.document.createElement("script"); + scriptElement.type = "application/json"; + scriptElement.setAttribute("data-ui5-config", "true"); + scriptElement.innerHTML = JSON.stringify(configurationObject); + $el.document.head.appendChild(scriptElement); + }); + + cy.wrap({ resetConfiguration }) + .invoke("resetConfiguration", true); + + cy.wrap({ getFirstDayOfWeek }) + .invoke("getFirstDayOfWeek") + .should("equal", 6); + + const date = new Date(Date.UTC(2023, 0, 1, 0, 0, 0)); // January 1, 2023 + cy.mount(); + + cy.get("#calendar1") + .shadow() + .find("[ui5-daypicker]") + .shadow() + .find(".ui5-dp-firstday") + .first() + .should("have.text", "Sat"); + }); }); From 51349fc6484562fe76fd1888e64e24cbd6167ac5 Mon Sep 17 00:00:00 2001 From: Georgi Damyanov Date: Tue, 25 Nov 2025 15:17:50 +0200 Subject: [PATCH 06/10] refactor: remove empty line --- packages/main/cypress/specs/Calendar.cy.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/main/cypress/specs/Calendar.cy.tsx b/packages/main/cypress/specs/Calendar.cy.tsx index 8192d353ef3e..3692a06d22fb 100644 --- a/packages/main/cypress/specs/Calendar.cy.tsx +++ b/packages/main/cypress/specs/Calendar.cy.tsx @@ -69,7 +69,6 @@ describe("Calendar general interaction", () => { cy.get("@monthBtn") .should("be.focused"); - cy.realPress("Tab"); From 418abd1d527e1cdff9d7c0cc4e472e40255d0c8a Mon Sep 17 00:00:00 2001 From: Georgi Damyanov Date: Mon, 8 Dec 2025 19:32:38 +0200 Subject: [PATCH 07/10] test: add assert --- packages/main/cypress/specs/Calendar.cy.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/main/cypress/specs/Calendar.cy.tsx b/packages/main/cypress/specs/Calendar.cy.tsx index 2176d64ff850..c5609bddbbde 100644 --- a/packages/main/cypress/specs/Calendar.cy.tsx +++ b/packages/main/cypress/specs/Calendar.cy.tsx @@ -69,7 +69,8 @@ describe("Calendar general interaction", () => { cy.get("@calheader") .find("[data-ui5-cal-header-btn-prev]") - .as("prevBtn"); + .as("prevBtn") + .should("have.attr", "tabindex", "0"); cy.get("@prevBtn") .should("be.focused"); @@ -78,7 +79,8 @@ describe("Calendar general interaction", () => { cy.get("@calheader") .find("[data-ui5-cal-header-btn-month]") - .as("monthBtn"); + .as("monthBtn") + .should("have.attr", "tabindex", "0");; cy.get("@monthBtn") .should("be.focused"); From 1fcfebf8720c6beaef9d07a433669ee05751c977 Mon Sep 17 00:00:00 2001 From: Georgi Damyanov Date: Mon, 8 Dec 2025 20:23:39 +0200 Subject: [PATCH 08/10] test: fix tests --- packages/main/cypress/specs/DatePicker.cy.tsx | 6 +++++- packages/main/cypress/specs/DateTimePicker.cy.tsx | 10 +++++----- packages/main/cypress/specs/DynamicDateRange.cy.tsx | 6 +++--- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/packages/main/cypress/specs/DatePicker.cy.tsx b/packages/main/cypress/specs/DatePicker.cy.tsx index f748251d8daf..f36920435fa2 100644 --- a/packages/main/cypress/specs/DatePicker.cy.tsx +++ b/packages/main/cypress/specs/DatePicker.cy.tsx @@ -1363,7 +1363,11 @@ describe("Date Picker Tests", () => { .realPress("ArrowDown"); cy.get("@datePicker") - .ui5DatePickerGetDisplayedDay(13) + .shadow() + .find("ui5-calendar") + .as("calendar") + .shadow() + .find("[data-ui5-cal-header-btn-month]") .should("have.focus"); }); diff --git a/packages/main/cypress/specs/DateTimePicker.cy.tsx b/packages/main/cypress/specs/DateTimePicker.cy.tsx index b77b4d5b1718..db73f999520e 100644 --- a/packages/main/cypress/specs/DateTimePicker.cy.tsx +++ b/packages/main/cypress/specs/DateTimePicker.cy.tsx @@ -324,8 +324,8 @@ describe("DateTimePicker general interaction", () => { cy.get("@daypicker") .find(".ui5-dp-item--selected") - .should("be.focused") - .realClick(); + .realClick() + .should("be.focused"); cy.get("[ui5-time-selection-clocks]") .shadow() @@ -397,10 +397,10 @@ describe("DateTimePicker general interaction", () => { cy.get("@daypicker") .shadow() .find("[data-sap-focus-ref]") - .should("be.focused") - .realClick(); + .realClick() + .should("be.focused"); - // act: confirm selection + //act: confirm selection cy.get("@dtp") .ui5DateTimePickerGetSubmitButton() .should("have.prop", "disabled", false); diff --git a/packages/main/cypress/specs/DynamicDateRange.cy.tsx b/packages/main/cypress/specs/DynamicDateRange.cy.tsx index a511950fc6bb..f0931844b0fb 100644 --- a/packages/main/cypress/specs/DynamicDateRange.cy.tsx +++ b/packages/main/cypress/specs/DynamicDateRange.cy.tsx @@ -150,17 +150,17 @@ describe("DynamicDateRange Component", () => { cy.get("@calendar") .should("exist"); - - cy.realPress("Tab"); + cy.realPress("Tab"); cy.realPress("Tab"); cy.get("@calendar") .shadow() - .find("[data-ui5-cal-header-btn-year='true']") + .find("[data-ui5-cal-header-btn-year]") .as("yearButton"); cy.get("@yearButton") + .should("exist") .should("be.focused"); cy.realPress("Space"); From 3706e3a28ff85cc417cec944617e975f41e02098 Mon Sep 17 00:00:00 2001 From: Georgi Damyanov Date: Tue, 9 Dec 2025 11:47:10 +0200 Subject: [PATCH 09/10] test:fix test --- .../cypress/specs/DynamicDateRange.cy.tsx | 45 +++++++++---------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/packages/main/cypress/specs/DynamicDateRange.cy.tsx b/packages/main/cypress/specs/DynamicDateRange.cy.tsx index f0931844b0fb..003cdca803fd 100644 --- a/packages/main/cypress/specs/DynamicDateRange.cy.tsx +++ b/packages/main/cypress/specs/DynamicDateRange.cy.tsx @@ -154,37 +154,14 @@ describe("DynamicDateRange Component", () => { cy.realPress("Tab"); cy.realPress("Tab"); - cy.get("@calendar") - .shadow() - .find("[data-ui5-cal-header-btn-year]") - .as("yearButton"); - - cy.get("@yearButton") - .should("exist") - .should("be.focused"); - - cy.realPress("Space"); - - cy.get("@calendar") - .shadow() - .find("ui5-yearpicker") - .as("yearPicker"); - - cy.get("@yearPicker") - .shadow() - .find(".ui5-dp-yeartext") - .contains("2035") - .realClick(); - - cy.realPress("Tab"); - cy.get("@calendar") .shadow() .find("[data-ui5-cal-header-btn-month='true']") .as("monthButton"); cy.get("@monthButton") - .should("be.focused"); + .should("exist") + .should("have.focus"); cy.realPress("Space"); @@ -199,6 +176,24 @@ describe("DynamicDateRange Component", () => { .contains("May") .realClick(); + cy.get("@calendar") + .shadow() + .find("[data-ui5-cal-header-btn-year='true']") + .as("yearButton") + .should("exist") + .realClick(); + + cy.get("@calendar") + .shadow() + .find("ui5-yearpicker") + .as("yearPicker"); + + cy.get("@yearPicker") + .shadow() + .find(".ui5-dp-yeartext") + .contains("2035") + .realClick(); + cy.get("@calendar") .shadow() .find("ui5-daypicker") From 12f6a2d654c889c6fd149b05ba41dd7ab6a88b5d Mon Sep 17 00:00:00 2001 From: Georgi Damyanov Date: Tue, 9 Dec 2025 12:09:39 +0200 Subject: [PATCH 10/10] test: fix test --- .../main/cypress/specs/DateTimePicker.cy.tsx | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/packages/main/cypress/specs/DateTimePicker.cy.tsx b/packages/main/cypress/specs/DateTimePicker.cy.tsx index db73f999520e..7b3436c5a3b4 100644 --- a/packages/main/cypress/specs/DateTimePicker.cy.tsx +++ b/packages/main/cypress/specs/DateTimePicker.cy.tsx @@ -119,6 +119,9 @@ describe("DateTimePicker general interaction", () => { cy.get("[ui5-calendar]") .shadow() .as("calendar"); + + cy.realPress("Tab"); + cy.realPress("Tab"); cy.get("@calendar") .find("[ui5-daypicker]") @@ -174,7 +177,7 @@ describe("DateTimePicker general interaction", () => { cy.realPress("Tab"); - // Simulate keyboard interactions + //Simulate keyboard interactions cy.get("@dtp") .shadow() .find("[ui5-datetime-input]") @@ -300,7 +303,7 @@ describe("DateTimePicker general interaction", () => { .ui5DateTimePickerClose(); }); - // Unstable test, needs investigation + //Unstable test, needs investigation it("tests selection of 12:34:56 AM", () => { setAnimationMode(AnimationMode.None); @@ -389,11 +392,11 @@ describe("DateTimePicker general interaction", () => { .find("ui5-daypicker") .as("daypicker"); - // act: open the picker + //act: open the picker cy.get("@dtp") .ui5DateTimePickerOpen(); - // act: click today's date + //act: click today's date cy.get("@daypicker") .shadow() .find("[data-sap-focus-ref]") @@ -412,7 +415,7 @@ describe("DateTimePicker general interaction", () => { cy.get("@dtp") .ui5DateTimePickerExpectToBeClosed(); - // assert: the value is not changed + //assert: the value is not changed cy.get("@input") .should("be.focused") .and("have.attr", "value", ""); @@ -488,7 +491,7 @@ describe("DateTimePicker general interaction", () => { .should("have.text", "Invalid entry"); }); - // Unstable test, needs investigation + //Unstable test, needs investigation it("tests change event is fired on submit", () => { cy.mount(); @@ -525,10 +528,10 @@ describe("DateTimePicker general interaction", () => { cy.get("@dtp") .ui5DateTimePickerExpectToBeClosed(); - // Assert the change event was fired once + //Assert the change event was fired once cy.get("@changeStub").should("have.been.calledOnce"); - // Re-open the picker and submit without making a change + //Re-open the picker and submit without making a change cy.get("@dtp") .ui5DateTimePickerOpen(); @@ -540,11 +543,11 @@ describe("DateTimePicker general interaction", () => { .ui5DateTimePickerGetSubmitButton() .realClick(); - // Verify the picker is closed + //Verify the picker is closed cy.get("@dtp") .ui5DateTimePickerExpectToBeClosed(); - // The change event should not have been fired a second time. + //The change event should not have been fired a second time. cy.get("@changeStub").should("have.been.calledOnce"); }); });