Skip to content
Open
58 changes: 58 additions & 0 deletions packages/main/cypress/specs/Calendar.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import "@ui5/webcomponents-localization/dist/features/calendar/Gregorian.js";
import { resetConfiguration } from "@ui5/webcomponents-base/dist/InitialConfiguration.js";
import { getFirstDayOfWeek } from "@ui5/webcomponents-base/dist/config/FormatSettings.js";
import CalendarSelectionMode from "../../src/types/CalendarSelectionMode.js";
import { setLanguage } from "@ui5/webcomponents-base/dist/config/Language.js";
import "../../src/Assets.js";

const getDefaultCalendar = (date: Date) => {
const calDate = new Date(date);
Expand Down Expand Up @@ -1291,6 +1293,11 @@ describe("Calendar general interaction", () => {
});

describe("Calendar accessibility", () => {
beforeEach(() => {
cy.wrap({ setLanguage })
.then(api => { api.setLanguage("en"); });
});

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));
Expand Down Expand Up @@ -1605,6 +1612,57 @@ describe("Calendar accessibility", () => {
}
});
});

it("Should format day cell aria-label with en locale", () => {
const date = new Date(Date.UTC(2024, 0, 15, 0, 0, 0));
cy.mount(
<Calendar id="calendar1" timestamp={date.valueOf() / 1000} primaryCalendarType="Gregorian">
<CalendarDate value="Jan 15, 2024"></CalendarDate>
</Calendar>
);

cy.get<Calendar>("#calendar1")
.shadow()
.find("[ui5-daypicker]")
.shadow()
.find("[tabindex='0']")
.should("have.attr", "aria-label", "January 15, 2024");
});

it("Should format day cell aria-label with bg locale", () => {
cy.wrap({ setLanguage })
.then(api => { api.setLanguage("bg"); });

const date = new Date(Date.UTC(2024, 0, 15, 0, 0, 0));
cy.mount(
<Calendar id="calendar1" timestamp={date.valueOf() / 1000} primaryCalendarType="Gregorian">
<CalendarDate value="Jan 15, 2024"></CalendarDate>
</Calendar>
);

cy.get<Calendar>("#calendar1")
.shadow()
.find("[ui5-daypicker]")
.shadow()
.find("[tabindex='0']")
.should("have.attr", "aria-label", "15 януари 2024\u202fг.");
});

it("Should append secondary Islamic calendar date in day cell aria-label", () => {
const date = new Date(Date.UTC(2024, 0, 15, 0, 0, 0));
cy.mount(
<Calendar id="calendar1" timestamp={date.valueOf() / 1000} primaryCalendarType="Gregorian" secondaryCalendarType="Islamic">
<CalendarDate value="Jan 15, 2024"></CalendarDate>
</Calendar>
);

cy.get<Calendar>("#calendar1")
.shadow()
.find("[ui5-daypicker]")
.shadow()
.find("[tabindex='0']")
.should("have.attr", "aria-label", "January 15, 2024 Rajab 4, 1445 AH");
});
});

describe("Day Picker Tests", () => {
Expand Down
30 changes: 18 additions & 12 deletions packages/main/src/DayPicker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,16 +217,15 @@ class DayPicker extends CalendarPart implements ICalendarPicker {

onBeforeRendering() {
const localeData = getCachedLocaleDataInstance(getLocale());
this._buildWeeks(localeData);
this._buildWeeks();
this._buildDayNames(localeData);
}

/**
* Builds the "_weeks" object that represents the month.
* @param localeData
* @private
*/
_buildWeeks(localeData: LocaleData) {
_buildWeeks() {
if (this._hidden) {
return; // Optimization to not do any work unless the current picker
}
Expand All @@ -235,8 +234,6 @@ class DayPicker extends CalendarPart implements ICalendarPicker {

const firstDayOfWeek = this._getFirstDayOfWeek();
const specialCalendarDates = this._specialCalendarDates;
const monthsNames = localeData.getMonths("wide", this._primaryCalendarType);
const secondaryMonthsNames = this.hasSecondaryCalendarType ? localeData.getMonths("wide", this.secondaryCalendarType) : [];
const nonWorkingDayLabel = DayPicker.i18nBundle.getText(DAY_PICKER_NON_WORKING_DAY);
const todayLabel = DayPicker.i18nBundle.getText(DAY_PICKER_TODAY);
const tempDate = this._getFirstDay(); // date that will be changed by 1 day 42 times
Expand Down Expand Up @@ -277,15 +274,16 @@ class DayPicker extends CalendarPart implements ICalendarPicker {
: "";
const todayAriaLabel = isToday ? `${todayLabel} ` : "";

const tempSecondDateNumber = tempSecondDate ? tempSecondDate.getDate() : "";
const tempSecondYearNumber = tempSecondDate ? tempSecondDate.getYear() : "";
const secondaryMonthsNamesString = secondaryMonthsNames.length > 0 ? secondaryMonthsNames[tempSecondDate!.getMonth()] : "";

const tooltip = `${todayAriaLabel}${nonWorkingAriaLabel}${unnamedCalendarTypeLabel}`.trim();

let ariaLabel = this.hasSecondaryCalendarType
? `${monthsNames[tempDate.getMonth()]} ${tempDate.getDate()}, ${tempDate.getYear()}; ${secondaryMonthsNamesString} ${tempSecondDateNumber}, ${tempSecondYearNumber} ${tooltip}`.trim()
: `${monthsNames[tempDate.getMonth()]} ${tempDate.getDate()}, ${tempDate.getYear()} ${tooltip}`.trim();
let ariaLabel = this._formatLong.format(tempDate.toUTCJSDate(), true);
if (this.hasSecondaryCalendarType && tempSecondDate) {
ariaLabel += ` ${this._formatLongSecondary.format(tempSecondDate.toUTCJSDate(), true)}`;
}

if (tooltip) {
ariaLabel += ` ${tooltip}`;
}

if (this.selectionMode === CalendarSelectionMode.Range) {
if (isSelected && this._isRangeEndDate(timestamp)) {
Expand Down Expand Up @@ -1004,6 +1002,14 @@ class DayPicker extends CalendarPart implements ICalendarPicker {
? `${this._primaryCalendarType} calendar with secondary ${this.secondaryCalendarType as string} calendar`
: `${this._primaryCalendarType} calendar`;
}

get _formatLong() {
return DateFormat.getDateInstance({ style: "long", calendarType: this._primaryCalendarType });
}

get _formatLongSecondary() {
return DateFormat.getDateInstance({ style: "long", calendarType: this._secondaryCalendarType });
}
}

DayPicker.define();
Expand Down
4 changes: 2 additions & 2 deletions packages/main/test/pages/Calendar.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@
// delete Document.prototype.adoptedStyleSheets;
</script>

<!-- <script data-ui5-config type="application/json">
<script data-ui5-config type="application/json">
{
"language": "EN"
}
</script> -->
</script>
<script data-id="sap-ui-config" type="application/json">
{
"rtl": false,
Expand Down
Loading