@rifansi/angular-datetime-picker
Version:
Angular Date Time Picker
595 lines (491 loc) • 22.4 kB
text/typescript
/**
* calendar.component.spec
*/
import {
ComponentFixture,
inject,
TestBed
} from '@angular/core/testing';
import { Component, NgZone } from '@angular/core';
import {
MockNgZone,
dispatchFakeEvent,
dispatchMouseEvent,
dispatchKeyboardEvent
} from '../../test-helpers';
import { OwlNativeDateTimeModule } from './adapter/native-date-time.module';
import { OwlDateTimeModule } from './date-time.module';
import { OwlCalendarComponent } from './calendar.component';
import { OwlDateTimeIntl } from './date-time-picker-intl.service';
import { By } from '@angular/platform-browser';
import { ENTER, RIGHT_ARROW } from '@angular/cdk/keycodes';
import { OwlMonthViewComponent } from './calendar-month-view.component';
import { OwlYearViewComponent } from './calendar-year-view.component';
import { OwlMultiYearViewComponent } from './calendar-multi-year-view.component';
import {DateView} from './date-time.class';
export const JAN = 0,
FEB = 1,
MAR = 2,
APR = 3,
MAY = 4,
JUN = 5,
JUL = 6,
AUG = 7,
SEP = 8,
OCT = 9,
NOV = 10,
DEC = 11;
describe('OwlCalendarComponent', () => {
let zone: MockNgZone;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [OwlNativeDateTimeModule, OwlDateTimeModule],
declarations: [
StandardCalendarComponent,
CalendarWithCalendarWeeks,
CalendarWithMinMaxComponent,
CalendarWithDateFilterComponent
],
providers: [
OwlDateTimeIntl,
{ provide: NgZone, useFactory: () => (zone = new MockNgZone()) }
]
}).compileComponents();
});
describe('standard calendar', () => {
let fixture: ComponentFixture<StandardCalendarComponent>;
let testComponent: StandardCalendarComponent;
let calendarElement: HTMLElement;
let periodButton: HTMLElement;
let calendarInstance: OwlCalendarComponent<Date>;
beforeEach(() => {
fixture = TestBed.createComponent(StandardCalendarComponent);
fixture.detectChanges();
const calendarDebugElement = fixture.debugElement.query(
By.directive(OwlCalendarComponent)
);
calendarElement = calendarDebugElement.nativeElement;
periodButton = calendarElement.querySelector(
'.owl-dt-control-period-button'
) as HTMLElement;
calendarInstance = calendarDebugElement.componentInstance;
testComponent = fixture.componentInstance;
});
it('should be in month view with specified month active', () => {
expect(calendarInstance.currentView).toBe(DateView.MONTH);
expect(calendarInstance.pickerMoment).toEqual(
new Date(2018, JAN, 31)
);
});
it('should select date in month view', () => {
const monthCell = calendarElement.querySelector(
'[aria-label="January 31, 2018"]'
);
(monthCell as HTMLElement).click();
fixture.detectChanges();
expect(calendarInstance.currentView).toBe(DateView.MONTH);
expect(testComponent.selected).toEqual(new Date(2018, JAN, 31));
});
it('should emit the selected month on cell clicked in year view', () => {
periodButton.click();
fixture.detectChanges();
expect(calendarInstance.currentView).toBe(DateView.MULTI_YEARS);
expect(calendarInstance.pickerMoment).toEqual(
new Date(2018, JAN, 31)
);
(calendarElement.querySelector(
'.owl-dt-calendar-cell-active'
) as HTMLElement).click();
fixture.detectChanges();
expect(calendarInstance.currentView).toBe(DateView.YEAR);
(calendarElement.querySelector(
'.owl-dt-calendar-cell-active'
) as HTMLElement).click();
const normalizedMonth: Date =
fixture.componentInstance.selectedMonth;
expect(normalizedMonth.getMonth()).toEqual(0);
});
it('should emit the selected year on cell clicked in multi-years view', () => {
periodButton.click();
fixture.detectChanges();
expect(calendarInstance.currentView).toBe(DateView.MULTI_YEARS);
expect(calendarInstance.pickerMoment).toEqual(
new Date(2018, JAN, 31)
);
(calendarElement.querySelector(
'.owl-dt-calendar-cell-active'
) as HTMLElement).click();
fixture.detectChanges();
const normalizedYear: Date = fixture.componentInstance.selectedYear;
expect(normalizedYear.getFullYear()).toEqual(2018);
});
it('should re-render when the i18n labels have changed', () => {
inject([OwlDateTimeIntl], (intl: OwlDateTimeIntl) => {
const button = fixture.debugElement.nativeElement.querySelector(
'.owl-dt-control-period-button'
);
intl.switchToMultiYearViewLabel = 'Go to multi-year view?';
intl.changes.next();
fixture.detectChanges();
expect(button.getAttribute('aria-label')).toBe(
'Go to multi-year view?'
);
});
});
it('should set all buttons to be `type="button"`', () => {
const invalidButtons = calendarElement.querySelectorAll(
'button:not([type="button"])'
);
expect(invalidButtons.length).toBe(0);
});
describe('a11y', () => {
describe('calendar body', () => {
let calendarMainEl: HTMLElement;
beforeEach(() => {
calendarMainEl = calendarElement.querySelector(
'.owl-dt-calendar-main'
) as HTMLElement;
expect(calendarMainEl).not.toBeNull();
dispatchFakeEvent(calendarMainEl, 'focus');
fixture.detectChanges();
});
it('should initially set pickerMoment', () => {
expect(calendarInstance.pickerMoment).toEqual(
new Date(2018, JAN, 31)
);
});
it('should make the calendar main focusable', () => {
expect(calendarMainEl.getAttribute('tabindex')).toBe('-1');
});
it('should not move focus to the active cell on init', () => {
const activeCell = calendarMainEl.querySelector(
'.owl-dt-calendar-cell-active'
) as HTMLElement;
spyOn(activeCell, 'focus').and.callThrough();
fixture.detectChanges();
zone.simulateZoneExit();
expect(activeCell.focus).not.toHaveBeenCalled();
});
it('should move focus to the active cell when the view changes', () => {
const activeCell = calendarMainEl.querySelector(
'.owl-dt-calendar-cell-active'
) as HTMLElement;
spyOn(activeCell, 'focus').and.callThrough();
fixture.detectChanges();
zone.simulateZoneExit();
expect(activeCell.focus).not.toHaveBeenCalled();
calendarInstance.currentView = DateView.MULTI_YEARS;
fixture.detectChanges();
zone.simulateZoneExit();
expect(activeCell.focus).toHaveBeenCalled();
});
describe('year view', () => {
beforeEach(() => {
dispatchMouseEvent(periodButton, 'click');
fixture.detectChanges();
expect(calendarInstance.currentView).toBe(
DateView.MULTI_YEARS
);
(calendarMainEl.querySelector(
'.owl-dt-calendar-cell-active'
) as HTMLElement).click();
fixture.detectChanges();
expect(calendarInstance.currentView).toBe(DateView.YEAR);
});
it('should return to month view on enter', () => {
const tableBodyEl = calendarMainEl.querySelector(
'.owl-dt-calendar-body'
) as HTMLElement;
dispatchKeyboardEvent(
tableBodyEl,
'keydown',
RIGHT_ARROW
);
fixture.detectChanges();
dispatchKeyboardEvent(tableBodyEl, 'keydown', ENTER);
fixture.detectChanges();
expect(calendarInstance.currentView).toBe(DateView.MONTH);
expect(calendarInstance.pickerMoment).toEqual(
new Date(2018, FEB, 28)
);
expect(testComponent.selected).toBeUndefined();
});
});
describe('multi-years view', () => {
beforeEach(() => {
dispatchMouseEvent(periodButton, 'click');
fixture.detectChanges();
expect(calendarInstance.currentView).toBe(
DateView.MULTI_YEARS
);
});
it('should return to year view on enter', () => {
const tableBodyEl = calendarMainEl.querySelector(
'.owl-dt-calendar-body'
) as HTMLElement;
dispatchKeyboardEvent(
tableBodyEl,
'keydown',
RIGHT_ARROW
);
fixture.detectChanges();
dispatchKeyboardEvent(tableBodyEl, 'keydown', ENTER);
fixture.detectChanges();
expect(calendarInstance.currentView).toBe(DateView.YEAR);
expect(calendarInstance.pickerMoment).toEqual(
new Date(2019, JAN, 31)
);
expect(testComponent.selected).toBeUndefined();
});
});
});
});
});
describe('calendar with Calendar Weeks', () => {
let fixture: ComponentFixture<CalendarWithCalendarWeeks>;
let testComponent: CalendarWithCalendarWeeks;
let calendarElement: HTMLElement;
let calendarInstance: OwlCalendarComponent<Date>;
beforeEach(() => {
fixture = TestBed.createComponent(CalendarWithCalendarWeeks);
fixture.detectChanges();
const calendarDebugElement = fixture.debugElement.query(
By.directive(OwlCalendarComponent)
);
calendarElement = calendarDebugElement.nativeElement;
calendarInstance = calendarDebugElement.componentInstance;
testComponent = fixture.componentInstance;
});
it('should show calendar weeks when attribute showCalendarWeeks in true', () => {
// Check the initial value is false
expect(calendarInstance.showCalendarWeeks).toBe(false);
testComponent.showCalendarWeeks = true;
fixture.detectChanges(); // Trigger change detection to apply the new value
// Now check if the calendarInstance reflects this change
expect(calendarInstance.showCalendarWeeks).toBe(true);
});
it('should show calendar weeks classes only when attribute showCalendarWeeks in true', () => {
// Check the initial value is false
expect(calendarInstance.showCalendarWeeks).toBe(false);
// Verify classes are not present initially
let weekNumberElement = fixture.debugElement.nativeElement.querySelector('.week-number');
let owlCalendarWeeksElement = fixture.debugElement.nativeElement.querySelector('.owl-calendar-weeks');
expect(weekNumberElement).toBeNull();
expect(owlCalendarWeeksElement).toBeNull();
// Set showCalendarWeeks to true
testComponent.showCalendarWeeks = true;
fixture.detectChanges(); // Trigger change detection to apply the new value
// Now check if the calendarInstance reflects this change
expect(calendarInstance.showCalendarWeeks).toBe(true);
// Verify classes are present after the change
weekNumberElement = fixture.debugElement.nativeElement.querySelector('.week-number');
owlCalendarWeeksElement = fixture.debugElement.nativeElement.querySelector('.owl-calendar-weeks');
expect(weekNumberElement).toBeTruthy();
expect(owlCalendarWeeksElement).toBeTruthy();
});
});
describe('calendar with min and max', () => {
let fixture: ComponentFixture<CalendarWithMinMaxComponent>;
let testComponent: CalendarWithMinMaxComponent;
let calendarElement: HTMLElement;
let calendarInstance: OwlCalendarComponent<Date>;
beforeEach(() => {
fixture = TestBed.createComponent(CalendarWithMinMaxComponent);
fixture.detectChanges();
const calendarDebugElement = fixture.debugElement.query(
By.directive(OwlCalendarComponent)
);
calendarElement = calendarDebugElement.nativeElement;
calendarInstance = calendarDebugElement.componentInstance;
testComponent = fixture.componentInstance;
});
it('should re-render the month view when the minDate changes', () => {
const monthViewDebugElm = fixture.debugElement.query(
By.directive(OwlMonthViewComponent)
);
const monthViewComp = monthViewDebugElm.componentInstance;
expect(monthViewComp).toBeTruthy();
spyOn(monthViewComp, 'generateCalendar').and.callThrough();
testComponent.minDate = new Date(2017, NOV, 1);
fixture.detectChanges();
expect(monthViewComp.generateCalendar).toHaveBeenCalled();
});
it('should re-render the month view when the maxDate changes', () => {
const monthViewDebugElm = fixture.debugElement.query(
By.directive(OwlMonthViewComponent)
);
const monthViewComp = monthViewDebugElm.componentInstance;
expect(monthViewComp).toBeTruthy();
spyOn(monthViewComp, 'generateCalendar').and.callThrough();
testComponent.maxDate = new Date(2017, NOV, 1);
fixture.detectChanges();
expect(monthViewComp.generateCalendar).toHaveBeenCalled();
});
it('should re-render the year view when the minDate changes', () => {
fixture.detectChanges();
const periodButton = calendarElement.querySelector(
'.owl-dt-control-period-button'
) as HTMLElement;
periodButton.click();
fixture.detectChanges();
(calendarElement.querySelector(
'.owl-dt-calendar-cell-active'
) as HTMLElement).click();
fixture.detectChanges();
const yearViewDebugElm = fixture.debugElement.query(
By.directive(OwlYearViewComponent)
);
const yearViewComp = yearViewDebugElm.componentInstance;
expect(yearViewComp).toBeTruthy();
spyOn(yearViewComp, 'generateMonthList').and.callThrough();
testComponent.minDate = new Date(2017, NOV, 1);
fixture.detectChanges();
expect(yearViewComp.generateMonthList).toHaveBeenCalled();
});
it('should re-render the year view when the maxDate changes', () => {
fixture.detectChanges();
const periodButton = calendarElement.querySelector(
'.owl-dt-control-period-button'
) as HTMLElement;
periodButton.click();
fixture.detectChanges();
(calendarElement.querySelector(
'.owl-dt-calendar-cell-active'
) as HTMLElement).click();
fixture.detectChanges();
const yearViewDebugElm = fixture.debugElement.query(
By.directive(OwlYearViewComponent)
);
const yearViewComp = yearViewDebugElm.componentInstance;
expect(yearViewComp).toBeTruthy();
spyOn(yearViewComp, 'generateMonthList').and.callThrough();
testComponent.maxDate = new Date(2017, NOV, 1);
fixture.detectChanges();
expect(yearViewComp.generateMonthList).toHaveBeenCalled();
});
it('should re-render the multi-years view when the minDate changes', () => {
fixture.detectChanges();
const periodButton = calendarElement.querySelector(
'.owl-dt-control-period-button'
) as HTMLElement;
periodButton.click();
fixture.detectChanges();
const multiYearsViewDebugElm = fixture.debugElement.query(
By.directive(OwlMultiYearViewComponent)
);
const multiYearsViewComp = multiYearsViewDebugElm.componentInstance;
expect(multiYearsViewComp).toBeTruthy();
spyOn(multiYearsViewComp, 'generateYearList').and.callThrough();
testComponent.minDate = new Date(2017, NOV, 1);
fixture.detectChanges();
expect(multiYearsViewComp.generateYearList).toHaveBeenCalled();
});
it('should re-render the multi-years view when the maxDate changes', () => {
fixture.detectChanges();
const periodButton = calendarElement.querySelector(
'.owl-dt-control-period-button'
) as HTMLElement;
periodButton.click();
fixture.detectChanges();
const multiYearsViewDebugElm = fixture.debugElement.query(
By.directive(OwlMultiYearViewComponent)
);
const multiYearsViewComp = multiYearsViewDebugElm.componentInstance;
expect(multiYearsViewComp).toBeTruthy();
spyOn(multiYearsViewComp, 'generateYearList').and.callThrough();
testComponent.maxDate = new Date(2017, NOV, 1);
fixture.detectChanges();
expect(multiYearsViewComp.generateYearList).toHaveBeenCalled();
});
});
describe('calendar with date filter', () => {
let fixture: ComponentFixture<CalendarWithDateFilterComponent>;
let testComponent: CalendarWithDateFilterComponent;
let calendarElement: HTMLElement;
let calendarInstance: OwlCalendarComponent<Date>;
beforeEach(() => {
fixture = TestBed.createComponent(CalendarWithDateFilterComponent);
fixture.detectChanges();
const calendarDebugElement = fixture.debugElement.query(
By.directive(OwlCalendarComponent)
);
calendarElement = calendarDebugElement.nativeElement;
calendarInstance = calendarDebugElement.componentInstance;
testComponent = fixture.componentInstance;
});
it('should disable and prevent selection of filtered dates', () => {
const monthCell = calendarElement.querySelector(
'[aria-label="January 2, 2018"]'
);
expect(testComponent.selected).toBeFalsy();
(monthCell as HTMLElement).click();
fixture.detectChanges();
expect(testComponent.selected).toEqual(new Date(2018, JAN, 2));
});
});
});
({
standalone: false,
template: `
<owl-date-time-calendar
[(selected)]="selected"
[selectMode]="selectMode"
[pickerMoment]="pickerMoment"
(monthSelected)="selectedMonth=$event"
(yearSelected)="selectedYear=$event"></owl-date-time-calendar>
`
})
class StandardCalendarComponent {
selectMode = 'single';
selected: Date;
selectedYear: Date;
selectedMonth: Date;
pickerMoment = new Date(2018, JAN, 31);
}
({
standalone: false,
template: `
<owl-date-time-calendar [selectMode]="selectMode"
[pickerMoment]="pickerMoment"
[minDate]="minDate"
[maxDate]="maxDate"></owl-date-time-calendar>
`
})
class CalendarWithMinMaxComponent {
selectMode = 'single';
startAt: Date;
minDate = new Date(2016, JAN, 1);
maxDate = new Date(2019, JAN, 1);
pickerMoment = new Date(2018, JAN, 31);
}
({
standalone: false,
template: `
<owl-date-time-calendar [selectMode]="selectMode"
[pickerMoment]="pickerMoment"
[showCalendarWeeks]="showCalendarWeeks"></owl-date-time-calendar>
`
})
class CalendarWithCalendarWeeks {
selectMode = 'single';
startAt: Date;
showCalendarWeeks = false;
pickerMoment = new Date(2018, JAN, 31);
}
({
standalone: false,
template: `
<owl-date-time-calendar [(selected)]="selected"
[selectMode]="selectMode"
[pickerMoment]="pickerMoment"
[dateFilter]="dateFilter"></owl-date-time-calendar>
`
})
class CalendarWithDateFilterComponent {
selectMode = 'single';
selected: Date;
pickerMoment = new Date(2018, JAN, 31);
dateFilter(date: Date) {
return !(date.getDate() % 2) && date.getMonth() !== NOV;
}
}