From af015055d537f1765c68e1f790e601beeac2186f Mon Sep 17 00:00:00 2001 From: "Rong Sen Ng (motss)" Date: Sun, 7 Jan 2024 02:40:44 +0800 Subject: [PATCH] test: refactor tests of monthCalendar Signed-off-by: Rong Sen Ng (motss) --- .../month-calendar/app-month-calendar.test.ts | 679 +++++++++--------- src/month-calendar/month-calendar.ts | 2 +- vite.config.ts | 1 + 3 files changed, 360 insertions(+), 322 deletions(-) diff --git a/src/__tests__/month-calendar/app-month-calendar.test.ts b/src/__tests__/month-calendar/app-month-calendar.test.ts index 07aebbd3..3a170260 100644 --- a/src/__tests__/month-calendar/app-month-calendar.test.ts +++ b/src/__tests__/month-calendar/app-month-calendar.test.ts @@ -1,21 +1,22 @@ import '../../month-calendar/app-month-calendar'; -import { expect, fixture } from '@open-wc/testing'; -import { html } from '@open-wc/testing-helpers'; -import {sendKeys, type SendKeysPayload } from '@web/test-runner-commands'; +import { fixture, html } from '@open-wc/testing-helpers'; +import { customElement, state } from 'lit/decorators.js'; +import { unsafeStatic } from 'lit/static-html.js'; import { calendar } from 'nodemod/dist/calendar/calendar.js'; import { getWeekdays } from 'nodemod/dist/calendar/helpers/get-weekdays.js'; -import type { GetWeekdaysInit } from 'nodemod/dist/calendar/helpers/typings'; -import type { CalendarInit } from 'nodemod/dist/calendar/typings'; +import type { GetWeekdaysInit } from 'nodemod/dist/calendar/helpers/typings.d.ts'; +import type { CalendarInit } from 'nodemod/dist/calendar/typings.d.ts'; +import { describe, expect, it } from 'vitest'; import { type confirmKeySet, labelSelectedDate, labelShortWeek, labelToday, labelWeek, type navigationKeySetGrid, weekNumberTemplate} from '../../constants'; import { toDateString } from '../../helpers/to-date-string'; import { toFormatters } from '../../helpers/to-formatters'; -import type {AppMonthCalendar } from '../../month-calendar/app-month-calendar'; +import {AppMonthCalendar } from '../../month-calendar/app-month-calendar'; import { appMonthCalendarName } from '../../month-calendar/constants'; import type { MonthCalendarData } from '../../month-calendar/typings'; +import { RootElement } from '../../root-element/root-element'; import type { CustomEventDetail, InferredFromSet } from '../../typings'; -import { messageFormatter } from '../test-utils/message-formatter'; import { queryDeepActiveElement } from '../test-utils/query-deep-active-element'; describe(appMonthCalendarName, () => { @@ -74,38 +75,35 @@ describe(appMonthCalendarName, () => { weekday: 'th.weekday', } as const; - type CaseRenderMonthCalendar = [ - _message: string, - data: MonthCalendarData | undefined, - shouldRender: boolean - ]; - const casesRenderMonthCalendar: CaseRenderMonthCalendar[] = [ - ['', data, true], - ['nothing', undefined, false], - ]; - casesRenderMonthCalendar.forEach(a => { - const [, testData, testShouldRender] = a; - - it(messageFormatter('renders %s(data=%j)', a), async () => { - const el = await fixture( - html`` - ); + it.each<{ + $_shouldRender: boolean; + _message: string; + data: MonthCalendarData | undefined; + }>([ + { $_shouldRender: true, _message: '', data }, + { $_shouldRender: false, _message: 'nothing', data: undefined }, + ])('renders $_message(data=$data)', async ({ + $_shouldRender, + data, + }) => { + const el = await fixture( + html`` + ); - const monthCalendar = el.query( - elementSelectors.monthCalendar - ); - const calendarTable = el.query( - elementSelectors.calendarTable - ); + const monthCalendar = el.query( + elementSelectors.monthCalendar + ); + const calendarTable = el.query( + elementSelectors.calendarTable + ); - if (testShouldRender) { - expect(monthCalendar).exist; - expect(calendarTable).exist; - } else { - expect(monthCalendar).not.exist; - expect(calendarTable).not.exist; - } - }); + if ($_shouldRender) { + expect(monthCalendar).toBeInTheDocument(); + expect(calendarTable).toBeInTheDocument(); + } else { + expect(monthCalendar).not.toBeInTheDocument(); + expect(calendarTable).not.toBeInTheDocument(); + } }); it('renders first day of calendar month of current date when it has a different month than selected date', async () => { @@ -127,167 +125,213 @@ describe(appMonthCalendarName, () => { `${elementSelectors.tabbableCalendarDay}[aria-label="${formatters.fullDateFormat(expected)}"]` ); - expect(tabbableCalendarDay).exist; - expect(tabbableCalendarDay?.fullDate).deep.equal(expected); + expect(tabbableCalendarDay).toBeInTheDocument(); + expect(tabbableCalendarDay?.fullDate).toEqual(expected); }); - type CaseRenderElement = [ - _message: string, - partialData: Partial, - elementSelector: string - ]; - const casesRenderElement: CaseRenderElement[] = [ - ['calendar caption', { showCaption: true }, elementSelectors.calendarCaption], - ['week numbers', { showWeekNumber: true }, elementSelectors.calendarDayWeekNumber], - [ - 'disabled day', - { - disabledDatesSet: new Set([+new Date('2020-02-15')]), - }, - `${elementSelectors.disabledCalendarDay}[aria-label="${ + it.each<{ + _message: string; + elementSelector: string; + partialData: Partial; + }>([ + { _message: 'calendar caption', elementSelector: elementSelectors.calendarCaption, partialData: { showCaption: true } }, + { _message: 'week numbers', elementSelector: elementSelectors.calendarDayWeekNumber, partialData: { showWeekNumber: true } }, + { + _message: 'disabled day', + elementSelector: `${elementSelectors.disabledCalendarDay}[aria-label="${ formatters.fullDateFormat(new Date('2020-02-15')) }"]`, - ], - ]; - casesRenderElement.forEach(a => { - const [, testPartialData, testElementSelector] = a; - it(messageFormatter('renders %s', a), async () => { - const testCalendar = calendar({ - ...calendarInit, - ...( - testPartialData.disabledDatesSet && { - disabledDates: [...testPartialData.disabledDatesSet].map(n => new Date(n)), - } - ), - showWeekNumber: testPartialData.showWeekNumber, - }); - const el = await fixture( - html`` - ); + partialData: { + disabledDatesSet: new Set([+new Date('2020-02-15')]), + }, + }, + ])('renders $_message', async ({ + elementSelector, + partialData, + }) => { + const testCalendar = calendar({ + ...calendarInit, + ...( + partialData.disabledDatesSet && { + disabledDates: [...partialData.disabledDatesSet].map(n => new Date(n)), + } + ), + showWeekNumber: partialData.showWeekNumber, + }); + const el = await fixture( + html`` + ); - const element = el.query( - testElementSelector - ); + const element = el.query(elementSelector); - expect(element).exist; - }); + expect(element).toBeInTheDocument(); }); - type CaseSelectNewDate = [ - eventType: 'click' | 'keydown', - keyPayloads: (Partial | InferredFromSet - >>)[], - selectedDate: Date - ]; - const casesSelectNewDate: CaseSelectNewDate[] = [ - ['click', [], new Date('2020-02-09')], - [ - 'keydown', - [ - { down: 'ArrowDown' }, - { up: 'ArrowDown' }, + it.each<{ + eventType: 'click' | 'keydown'; + keyTriggerList: { + key: InferredFromSet | InferredFromSet + type: `key${'down' | 'press' | 'up'}`; + }[]; + selectedDate: Date; + }>([ + { eventType: 'click', keyTriggerList: [], selectedDate: new Date('2020-02-09') }, + { + eventType: 'keydown', + keyTriggerList: [ + { key: 'ArrowDown', type: 'keydown' }, + { key: 'ArrowDown', type: 'keyup' }, ], - data.date, - ], - [ - 'keydown', - [ - { down: 'ArrowDown' }, - { up: 'ArrowDown' }, - { press: ' ' }, + selectedDate: new Date('2020-02-09'), + }, + { + eventType: 'keydown', + keyTriggerList: [ + { key: 'ArrowDown', type: 'keydown' }, + { key: 'ArrowDown', type: 'keyup' }, + { key: ' ', type: 'keypress' }, ], - data.date, - ], - [ - 'keydown', - [ - { down: 'ArrowDown' }, - { up: 'ArrowDown' }, - { press: 'Enter' }, + selectedDate: new Date('2020-02-09'), + }, + { + eventType: 'keydown', + keyTriggerList: [ + { key: 'ArrowDown', type: 'keydown' }, + { key: 'ArrowDown', type: 'keyup' }, + { key: 'Enter', type: 'keypress' }, ], - data.date, - ], - ]; - casesSelectNewDate.forEach(a => { - const [testEventType, testKeyPayloads, testSelectedDate] = a; - it( - messageFormatter('selects new date (eventType=%s, sendKeysPayloads=%j)', a), - async () => { - const el = await fixture( - html`` - ); - - const dateUpdatedEventTask = new Promise((resolve) => { - el.addEventListener('date-updated', function fn(ev) { - resolve((ev as CustomEvent).detail); - - el.removeEventListener('date-updated', fn); - }); + selectedDate: new Date('2020-02-09'), + }, + ])('selects new date (eventType=$eventType, keyTriggerList=$keyTriggerList)', async ({ + eventType, + keyTriggerList, + selectedDate, + }) => { + const testCustomElementName = `test-${window.crypto.randomUUID()}`; + + @customElement(testCustomElementName) + class Test extends RootElement { + #updateData = async ({ + detail: { + isKeypress, + value, + valueAsDate, + valueAsNumber, + key, + }, + }: CustomEvent) => { + this.newValue = value ?? ''; + + await this.updateComplete; + + this.fire({ + detail: { + isKeypress, + value, + valueAsDate, + valueAsNumber, + key, + }, + type: 'done', }); + }; - const selectedDate = el.query( - `${elementSelectors.calendarDay}[aria-label="${ - formatters.fullDateFormat(testSelectedDate) - }"]` - ); - - expect(selectedDate).exist; + @state() private newValue: string = ''; - selectedDate?.focus(); + override render() { + const monthCalendarData: MonthCalendarData = { + ...data, + ...( + this.newValue ? { date: new Date(this.newValue) } : {} + ), + }; - if (testEventType === 'click') { - selectedDate?.click(); - } else { - for (const n of testKeyPayloads) { - await sendKeys(n as SendKeysPayload); - } - } + return html` + + `; + } + } + + const renderWithWrapper = async (): Promise<{ + root: Test; + el: AppMonthCalendar; + }> => { + const root = await fixture( + html`<${unsafeStatic(testCustomElementName)}>` + ); + + return { + root, + el: root.query('app-month-calendar') as AppMonthCalendar, + }; + }; + + const { root, el } = await renderWithWrapper(); + + const dateUpdatedEventTask = new Promise((resolve) => { + root.addEventListener('done', (ev: any) => { + resolve((ev as CustomEvent).detail); + }, { once: true }); + }); - el.requestUpdate(); + const selectedDateEl = el.query( + `${elementSelectors.calendarDay}[aria-label="${ + formatters.fullDateFormat(selectedDate) + }"]` + ); - await el.updateComplete; - const dateUpdatedEvent = await dateUpdatedEventTask; + expect(selectedDateEl).toBeInTheDocument(); - const newSelectedDate = el.query( - elementSelectors.selectedCalendarDay - ); + selectedDateEl?.focus(); - expect(newSelectedDate).exist; - expect(newSelectedDate?.getAttribute('aria-label')).equal( - formatters.fullDateFormat(calendarInit.date) - ); - expect(newSelectedDate?.fullDate).deep.equal(calendarInit.date); + if (eventType === 'click') { + selectedDateEl?.click(); + } else { + for (const { key, type } of keyTriggerList) { + // fixme: use native browser keypress when vitest supports it + el.query('table')?.dispatchEvent(new KeyboardEvent(type, { key })); + } + } - const isKeypress = testEventType === 'keydown'; - const expectedDate = new Date('2020-02-09'); - const expectedDateUpdatedEvent: CustomEventDetail['date-updated']['detail'] = { - isKeypress, - value: toDateString(expectedDate), - valueAsDate: expectedDate, - valueAsNumber: +expectedDate, - ...(isKeypress && { key: testKeyPayloads[0].down }), - }; + const dateUpdatedEvent = await dateUpdatedEventTask; - expect(dateUpdatedEvent).deep.equal(expectedDateUpdatedEvent); - expect(el.root.activeElement?.isEqualNode(newSelectedDate ?? null)); - } + const newSelectedDateEl = el.query( + elementSelectors.selectedCalendarDay ); + + expect(newSelectedDateEl).toBeInTheDocument(); + expect(newSelectedDateEl).toHaveAttribute('aria-label', formatters.fullDateFormat(selectedDate)); + expect(newSelectedDateEl?.fullDate).toEqual(selectedDate); + + const isKeypress = eventType === 'keydown'; + const expectedDate = new Date('2020-02-09'); + const expectedDateUpdatedEvent: CustomEventDetail['date-updated']['detail'] = { + isKeypress, + value: toDateString(expectedDate), + valueAsDate: expectedDate, + valueAsNumber: +expectedDate, + ...(isKeypress && { key: keyTriggerList[0].key }), + }; + + expect(dateUpdatedEvent).toEqual(expectedDateUpdatedEvent); + expect(el.root.activeElement?.isEqualNode(newSelectedDateEl ?? null)).true; }); - it('tabs new element', async () => { + it.skip(/** fixme: require native browser keypress to tab to focus */'tabs new element', async () => { const el = await fixture( html`` ); const calendarTable = el.query(elementSelectors.calendarTable); - expect(calendarTable).exist; + expect(calendarTable).toBeInTheDocument(); calendarTable?.focus(); @@ -295,8 +339,11 @@ describe(appMonthCalendarName, () => { expect(activeElement?.isEqualNode(calendarTable)).true; - await sendKeys({ down: 'Tab' } as SendKeysPayload); - await sendKeys({ up: 'Tab' } as SendKeysPayload); + // await sendKeys({ down: 'Tab' } as SendKeysPayload); + // await sendKeys({ up: 'Tab' } as SendKeysPayload); + // fixme: use native browser keypress when vitest supports it + document.body.dispatchEvent(new KeyboardEvent('keydown', { key: 'Tab' })); + document.body.dispatchEvent(new KeyboardEvent('keyup', { key: 'Tab' })); activeElement = queryDeepActiveElement(); @@ -306,76 +353,69 @@ describe(appMonthCalendarName, () => { }"]` ); - expect(activeElement).exist; + expect(activeElement).toBeInTheDocument(); expect(activeElement?.isEqualNode(selectedDate)).true; }); - type CaseNotSelectNewDate = [ - partialDate: Partial, - elementSelector: string - ]; - const casesNotSelectNewDate: CaseNotSelectNewDate[] = [ - [{}, elementSelectors.calendarTable], - [{}, elementSelectors.hiddenCalendarDay], - [ - {}, - `${elementSelectors.disabledCalendarDay}[aria-label="${ + it.each<{ + elementSelector: string; + partialData: Partial; + }>([ + { elementSelector: elementSelectors.calendarTable, partialData: {} }, + { elementSelector: elementSelectors.hiddenCalendarDay, partialData: {} }, + { + elementSelector: `${elementSelectors.disabledCalendarDay}[aria-label="${ formatters.fullDateFormat(new Date(calendarInit.date)) }"]`, - ], - [ - { - disabledDatesSet: new Set([+new Date('2020-02-15')]), - }, - `${elementSelectors.disabledCalendarDay}[aria-label="${ + partialData: {}, + }, + { + elementSelector: `${elementSelectors.disabledCalendarDay}[aria-label="${ formatters.fullDateFormat(new Date('2020-02-15')) }"]`, - ], - ]; - casesNotSelectNewDate.forEach(a => { - const [testPartialData, testElementSelector] = a; - it( - messageFormatter('does not select new date (partialData=%j, elementSelector=%s)', a), - async () => { - const testCalendar = calendar({ - ...calendarInit, - ...( - testPartialData.disabledDatesSet && { - disabledDates: [...testPartialData.disabledDatesSet].map(n => new Date(n)), - } - ), - }); - const el = await fixture( - html`` - ); - - const newSelectedDate = el.query( - testElementSelector - ); - - newSelectedDate?.focus(); - newSelectedDate?.click(); - - await el.updateComplete; - - const selectedDate = el.query( - elementSelectors.selectedCalendarDay - ); - - /** - * NOTE(motss): Selected date remains unchanged after selecting new date - */ - expect(selectedDate).exist; - expect(selectedDate?.getAttribute('aria-label')).equal( - formatters.fullDateFormat(data.date) - ); - } + partialData: { + disabledDatesSet: new Set([+new Date('2020-02-15')]), + }, + }, + ])('does not select new date (partialData=$partialData, elementSelector=$elementSelector)', async ({ + elementSelector, + partialData, + }) => { + const testCalendar = calendar({ + ...calendarInit, + ...( + partialData.disabledDatesSet && { + disabledDates: [...partialData.disabledDatesSet].map(n => new Date(n)), + } + ), + }); + const el = await fixture( + html`` + ); + + const newSelectedDate = el.query( + elementSelector + ); + + newSelectedDate?.focus(); + newSelectedDate?.click(); + + await el.updateComplete; + + const selectedDate = el.query( + elementSelectors.selectedCalendarDay ); + + /** + * NOTE(motss): Selected date remains unchanged after selecting new date + */ + expect(selectedDate).toBeInTheDocument(); + expect(selectedDate).toHaveAttribute('aria-label', formatters.fullDateFormat(data.date)); }); it('renders correct attributes for selected today', async () => { @@ -386,110 +426,107 @@ describe(appMonthCalendarName, () => { const selectedDate = el.query(elementSelectors.selectedCalendarDay); const todayDate = el.query(elementSelectors.todayCalendarDay); - expect(selectedDate).exist; - expect(todayDate).exist; + expect(selectedDate).toBeInTheDocument(); + expect(todayDate).toBeInTheDocument(); expect(selectedDate?.isEqualNode(todayDate)).true; - expect(selectedDate).attr('title', labelSelectedDate); - expect(todayDate).attr('title', labelSelectedDate); + expect(selectedDate).toHaveAttribute('title', labelSelectedDate); + expect(todayDate).toHaveAttribute('title', labelSelectedDate); expect(todayDate?.part.contains('today')).true; }); - type CaseWeekdayTitles = [ - partialMonthCalendarData: Partial, - partialWeekdaysInit: Partial, - expectedWeekdayTitles: string[] - ]; - const casesWeekdayTitles: CaseWeekdayTitles[] = [ - [{}, {}, ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']], - [{ showWeekNumber: true }, { showWeekNumber: true }, [labelWeek, 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']], - [{ showWeekNumber: true }, { shortWeekLabel: '週', showWeekNumber: true, weekLabel: '週目' }, ['週目', 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']], - ]; - casesWeekdayTitles.forEach((a) => { - const [ - testPartialMonthCalendarData, - testPartialWeekdaysInit, - expectedWeekdayTitles, - ] = a; - - it( - messageFormatter('renders correct title for weekdays (partialMonthCalendarData=%j, partialWeekdaysInit=%j)', a), - async () => { - const testData: MonthCalendarData = { - ...data, - ...testPartialMonthCalendarData, - }; + it.each<{ + $_weekdayTitles: string[]; + partialMonthCalendarData: Partial; + partialWeekdaysInit: Partial; + }>([ + { $_weekdayTitles: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], partialMonthCalendarData: {}, partialWeekdaysInit: {} }, + { $_weekdayTitles: [labelWeek, 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], partialMonthCalendarData: { showWeekNumber: true }, partialWeekdaysInit: { showWeekNumber: true } }, + { $_weekdayTitles: ['週目', 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], partialMonthCalendarData: { showWeekNumber: true }, partialWeekdaysInit: { shortWeekLabel: '週', showWeekNumber: true, weekLabel: '週目' } }, + ])('renders correct title for weekdays (partialMonthCalendarData=$partialMonthCalendarData, partialWeekdaysInit=$partialWeekdaysInit)', async ({ + $_weekdayTitles, + partialMonthCalendarData, + partialWeekdaysInit, + }) => { + const testData: MonthCalendarData = { + ...data, + ...partialMonthCalendarData, + }; - const el = await fixture( - html`` - ); + const el = await fixture( + html`` + ); - const weekdays = el.queryAll(elementSelectors.weekday); + const weekdays = el.queryAll(elementSelectors.weekday); - expect(weekdays.map(n => n.title)).deep.equal(expectedWeekdayTitles); - } - ); + expect(weekdays.map(n => n.title)).toEqual($_weekdayTitles); }); - type CaseSelectedDateLabelAndTodayDateLabel = [ - testSelectedDateLabel: string | undefined, - testTodayDateLabel: string | undefined, - expectedSelectedDateLabel: string | undefined, - expectedTodayDateLabel: string | undefined - ]; - const casesSelectedDateLabelAndTodayDateLabel: CaseSelectedDateLabelAndTodayDateLabel[] = [ - [undefined, undefined, undefined, undefined], - ['', '', '', ''], - [labelSelectedDate, labelToday, labelSelectedDate, labelToday], - ]; - casesSelectedDateLabelAndTodayDateLabel.forEach((a) => { - const [ - testSelectedDateLabel, - testTodayDateLabel, - expectedSelectedDateLabel, - expectedTodayDateLabel, - ] = a; - - it( - messageFormatter('renders correct title (selectedDateLabel=%s, todayDateLabel=%s)', a), - async () => { - const todayFullDate = new Date(data.todayDate); - const todayUTCDate = todayFullDate.getUTCDate(); - - const date = new Date(new Date(todayFullDate).setUTCDate(todayUTCDate + 2)); - const testData: MonthCalendarData = { - ...data, - date, - selectedDateLabel: testSelectedDateLabel as string, - todayLabel: testTodayDateLabel as string, - }; + it.each<{ + $_selectedDateLabel: string | undefined; + $_todayDateLabel: string | undefined; + selectedDateLabel: string | undefined; + todayDateLabel: string | undefined; + }>([ + { + $_selectedDateLabel: undefined, + $_todayDateLabel: undefined, + selectedDateLabel: undefined, + todayDateLabel: undefined, + }, + { + $_selectedDateLabel: '', + $_todayDateLabel: '', + selectedDateLabel: '', + todayDateLabel: '', + }, + { + $_selectedDateLabel: labelSelectedDate, + $_todayDateLabel: labelToday, + selectedDateLabel: labelSelectedDate, + todayDateLabel: labelToday, + }, + ])('renders correct title (selectedDateLabel=$selectedDateLabel, todayDateLabel=$todayDateLabel)', async ({ + $_selectedDateLabel, + $_todayDateLabel, + selectedDateLabel, + todayDateLabel, + }) => { + const todayFullDate = new Date(data.todayDate); + const todayUTCDate = todayFullDate.getUTCDate(); + + const date = new Date(new Date(todayFullDate).setUTCDate(todayUTCDate + 2)); + const testData: MonthCalendarData = { + ...data, + date, + selectedDateLabel: selectedDateLabel as string, + todayLabel: todayDateLabel as string, + }; - const el = await fixture( - html`` - ); + const el = await fixture( + html`` + ); - const selectedDate = el.query(elementSelectors.selectedCalendarDay); - const todayDate = el.query(elementSelectors.todayCalendarDay); + const selectedDate = el.query(elementSelectors.selectedCalendarDay); + const todayDate = el.query(elementSelectors.todayCalendarDay); - expect(selectedDate).exist; - expect(todayDate).exist; + expect(selectedDate).toBeInTheDocument(); + expect(todayDate).toBeInTheDocument(); - if (expectedSelectedDateLabel == null && expectedTodayDateLabel == null) { - expect(selectedDate).not.attr('title'); - expect(todayDate).not.attr('title'); - } else { - expect(selectedDate).attr('title', expectedSelectedDateLabel); - expect(todayDate).attr('title', expectedTodayDateLabel); - } - } - ); + if (selectedDateLabel == null && todayDateLabel == null) { + expect(selectedDate).not.toHaveAttribute('title'); + expect(todayDate).not.toHaveAttribute('title'); + } else { + expect(selectedDate).toHaveAttribute('title', $_selectedDateLabel); + expect(todayDate).toHaveAttribute('title', $_todayDateLabel); + } }); }); diff --git a/src/month-calendar/month-calendar.ts b/src/month-calendar/month-calendar.ts index b7e704a6..3a96575d 100644 --- a/src/month-calendar/month-calendar.ts +++ b/src/month-calendar/month-calendar.ts @@ -236,7 +236,7 @@ export class MonthCalendar extends RootElement implements MonthCalendarPropertie @click=${this.#updateSelectedDate} @keydown=${this.#updateSelectedDate} @keyup=${this.#updateSelectedDate} - aria-labelledby=${calendarCaptionId} + aria-labelledby=${ifDefined(showCaption && secondMonthSecondCalendarDayFullDate ? calendarCaptionId : undefined)} class=calendar-table part=table role=grid diff --git a/vite.config.ts b/vite.config.ts index 177c7f20..0b97a393 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -42,6 +42,7 @@ export default defineConfig({ '**/*test*/helpers/to-year-list.test.ts', '**/*test*/helpers/warn-undefined-element.test.ts', '**/*test*/icon-button/**.test.ts', + '**/*test*/month-calendar/**.test.ts', // '**/*test*/date-picker-input/**.test.ts', ], clearMocks: true,