lion/packages/calendar/test-helpers/CalendarObject.js
2020-10-06 12:41:03 +02:00

162 lines
4.2 KiB
JavaScript

import { DayObject } from './DayObject.js';
/**
* Abstraction around calendar DOM structure,
* allows for writing readable, 'DOM structure agnostic' tests
*/
export class CalendarObject {
/**
* @param {import('../src/LionCalendar').LionCalendar} calendarEl
*/
constructor(calendarEl) {
this.el = calendarEl;
}
/**
* Node references
*/
get rootEl() {
return this.el.shadowRoot?.querySelector('.calendar');
}
get headerEl() {
return this.el.shadowRoot?.querySelector('.calendar__navigation');
}
get yearHeadingEl() {
return this.el.shadowRoot?.querySelector('#year');
}
get monthHeadingEl() {
return this.el.shadowRoot?.querySelector('#month');
}
get nextYearButtonEl() {
return /** @type {HTMLElement & { ariaLabel: string }} */ (this.el.shadowRoot?.querySelectorAll(
'.calendar__next-button',
)[0]);
}
get previousYearButtonEl() {
return /** @type {HTMLElement & { ariaLabel: string }} */ (this.el.shadowRoot?.querySelectorAll(
'.calendar__previous-button',
)[0]);
}
get nextMonthButtonEl() {
return this.el.shadowRoot?.querySelectorAll('.calendar__next-button')[1];
}
get previousMonthButtonEl() {
return this.el.shadowRoot?.querySelectorAll('.calendar__previous-button')[1];
}
get gridEl() {
return this.el.shadowRoot?.querySelector('.calendar__grid');
}
get weekdayHeaderEls() {
return /** @type {HTMLElement[]} */ (Array.from(
/** @type {ShadowRoot} */ (this.el.shadowRoot).querySelectorAll('.calendar__weekday-header'),
));
}
get dayEls() {
return /** @type {HTMLElement[]} */ (Array.from(
/** @type {ShadowRoot} */ (this.el.shadowRoot).querySelectorAll(
'.calendar__day-button[current-month]',
),
));
}
get previousMonthDayEls() {
return /** @type {HTMLElement[]} */ (Array.from(
/** @type {ShadowRoot} */ (this.el.shadowRoot).querySelectorAll(
'.calendar__day-button[previous-month]',
),
));
}
get nextMonthDayEls() {
return /** @type {HTMLElement[]} */ (Array.from(
/** @type {ShadowRoot} */ (this.el.shadowRoot).querySelectorAll(
'.calendar__day-button[next-month]',
),
));
}
get dayObjs() {
return this.dayEls.map(d => new DayObject(d));
}
get previousMonthDayObjs() {
return this.previousMonthDayEls.map(d => new DayObject(d));
}
get nextMonthDayObjs() {
return this.nextMonthDayEls.map(d => new DayObject(d));
}
/**
* @param {number} monthDayNumber
*/
getDayEl(monthDayNumber) {
// Relies on the fact that empty cells don't have .calendar__day-button[current-month]
return /** @type {HTMLElement} */ (this.el.shadowRoot?.querySelectorAll(
'.calendar__day-button[current-month]',
)[monthDayNumber - 1]);
}
/**
* @param {number} monthDayNumber
*/
getDayObj(monthDayNumber) {
return new DayObject(/** @type{HTMLElement} */ (this.getDayEl(monthDayNumber)));
}
get selectedDayObj() {
return this.dayObjs.find(d => d.isSelected);
}
get centralDayObj() {
return this.dayObjs.find(d => d.isCentral);
}
get focusedDayObj() {
return this.dayObjs.find(d => d.el === this.el.shadowRoot?.activeElement);
}
/**
* @desc Applies condition to all days, or days in filter
*
* @param {function} condition : condition that should apply for "filter" days
* - Example: "(dayObj) => dayObj.selected"
* @param {number[]|function} [filter] - month day numbers for which condition should apply.
* - Example 1: "[15, 20]"
* - Example 2: "(dayNumber) => dayNumber === 15" (1 based ,not zero based)
*/
checkForAllDayObjs(condition, filter) {
return this.dayEls.every(d => {
const dayObj = new DayObject(d);
const dayNumber = dayObj.monthday;
let shouldApply = true;
if (filter !== undefined) {
shouldApply = filter instanceof Array ? filter.includes(dayNumber) : filter(dayNumber);
}
// for instance, should be 'disabled' for the 15th and 20th day
return !shouldApply || (condition(dayObj) && shouldApply);
});
}
/**
* States
*/
get activeMonth() {
return this.monthHeadingEl?.textContent?.trim();
}
get activeYear() {
return this.yearHeadingEl?.textContent?.trim();
}
}