357 lines
14 KiB
TypeScript
357 lines
14 KiB
TypeScript
import {HarnessLoader, parallel} from '@angular/cdk/testing';
|
||
import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed';
|
||
import {Component} from '@angular/core';
|
||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||
import {MatNativeDateModule} from '@angular/material/core';
|
||
import {
|
||
DateRange,
|
||
DefaultMatCalendarRangeStrategy,
|
||
MAT_DATE_RANGE_SELECTION_STRATEGY,
|
||
MatDatepickerModule,
|
||
} from '@angular/material/datepicker';
|
||
import {CalendarView, MatCalendarHarness} from './calendar-harness';
|
||
|
||
/** Date at which the calendars are set. */
|
||
const calendarDate = new Date(2020, 7, 1);
|
||
|
||
describe('MatCalendarHarness', () => {
|
||
let fixture: ComponentFixture<CalendarHarnessTest>;
|
||
let loader: HarnessLoader;
|
||
|
||
beforeEach(() => {
|
||
TestBed.configureTestingModule({
|
||
imports: [MatNativeDateModule, MatDatepickerModule, CalendarHarnessTest],
|
||
providers: [
|
||
{
|
||
// Usually it's the date range picker that provides the default range selection strategy,
|
||
// but since we're testing the calendar on its own, we have to provide it manually.
|
||
provide: MAT_DATE_RANGE_SELECTION_STRATEGY,
|
||
useClass: DefaultMatCalendarRangeStrategy,
|
||
},
|
||
],
|
||
});
|
||
|
||
fixture = TestBed.createComponent(CalendarHarnessTest);
|
||
fixture.detectChanges();
|
||
loader = TestbedHarnessEnvironment.loader(fixture);
|
||
});
|
||
|
||
it('should load all calendar harnesses', async () => {
|
||
const calendars = await loader.getAllHarnesses(MatCalendarHarness);
|
||
expect(calendars.length).toBe(2);
|
||
});
|
||
|
||
it('should go to a different view', async () => {
|
||
const calendar = await loader.getHarness(MatCalendarHarness.with({selector: '#single'}));
|
||
expect(await calendar.getCurrentView()).toBe(CalendarView.MONTH);
|
||
|
||
await calendar.changeView();
|
||
expect(await calendar.getCurrentView()).toBe(CalendarView.MULTI_YEAR);
|
||
});
|
||
|
||
it('should get the current view label', async () => {
|
||
const calendar = await loader.getHarness(MatCalendarHarness.with({selector: '#single'}));
|
||
expect(await calendar.getCurrentViewLabel()).toBe('AUG 2020');
|
||
|
||
await calendar.changeView();
|
||
expect(await calendar.getCurrentViewLabel()).toBe('2016 – 2039');
|
||
});
|
||
|
||
it('should go to the next page in the view', async () => {
|
||
const calendar = await loader.getHarness(MatCalendarHarness.with({selector: '#single'}));
|
||
expect(await calendar.getCurrentViewLabel()).toBe('AUG 2020');
|
||
|
||
await calendar.next();
|
||
expect(await calendar.getCurrentViewLabel()).toBe('SEP 2020');
|
||
});
|
||
|
||
it('should go to the previous page in the view', async () => {
|
||
const calendar = await loader.getHarness(MatCalendarHarness.with({selector: '#single'}));
|
||
expect(await calendar.getCurrentViewLabel()).toBe('AUG 2020');
|
||
|
||
await calendar.previous();
|
||
expect(await calendar.getCurrentViewLabel()).toBe('JUL 2020');
|
||
});
|
||
|
||
it('should get all of the date cells inside the calendar', async () => {
|
||
const calendar = await loader.getHarness(MatCalendarHarness.with({selector: '#single'}));
|
||
expect((await calendar.getCells()).length).toBe(31);
|
||
});
|
||
|
||
it('should get the text of a calendar cell', async () => {
|
||
const calendar = await loader.getHarness(MatCalendarHarness.with({selector: '#single'}));
|
||
const cells = await calendar.getCells();
|
||
|
||
expect(await cells[0].getText()).toBe('1');
|
||
expect(await cells[15].getText()).toBe('16');
|
||
expect(await cells[30].getText()).toBe('31');
|
||
});
|
||
|
||
it('should be able to select a specific cell through the calendar', async () => {
|
||
const calendar = await loader.getHarness(MatCalendarHarness.with({selector: '#single'}));
|
||
const targetCell = (await calendar.getCells({text: '16'}))[0];
|
||
expect(await targetCell.isSelected()).toBe(false);
|
||
|
||
await calendar.selectCell({text: '16'});
|
||
expect(await targetCell.isSelected()).toBe(true);
|
||
});
|
||
|
||
it('should get the aria-label of a cell', async () => {
|
||
const calendar = await loader.getHarness(MatCalendarHarness.with({selector: '#single'}));
|
||
const cells = await calendar.getCells();
|
||
|
||
expect(await cells[0].getAriaLabel()).toBe('August 1, 2020');
|
||
expect(await cells[15].getAriaLabel()).toBe('August 16, 2020');
|
||
expect(await cells[30].getAriaLabel()).toBe('August 31, 2020');
|
||
});
|
||
|
||
it('should get the disabled state of a cell', async () => {
|
||
fixture.componentInstance.minDate = new Date(
|
||
calendarDate.getFullYear(),
|
||
calendarDate.getMonth(),
|
||
20,
|
||
);
|
||
fixture.changeDetectorRef.markForCheck();
|
||
|
||
const calendar = await loader.getHarness(MatCalendarHarness.with({selector: '#single'}));
|
||
const cells = await calendar.getCells();
|
||
|
||
expect(await cells[0].isDisabled()).toBe(true);
|
||
expect(await cells[15].isDisabled()).toBe(true);
|
||
expect(await cells[30].isDisabled()).toBe(false);
|
||
});
|
||
|
||
it('should select a cell', async () => {
|
||
const calendar = await loader.getHarness(MatCalendarHarness.with({selector: '#single'}));
|
||
const cell = (await calendar.getCells())[10];
|
||
expect(await cell.isSelected()).toBe(false);
|
||
|
||
await cell.select();
|
||
expect(await cell.isSelected()).toBe(true);
|
||
});
|
||
|
||
it('should get whether a cell is active', async () => {
|
||
const calendar = await loader.getHarness(MatCalendarHarness.with({selector: '#single'}));
|
||
const cells = await calendar.getCells();
|
||
|
||
expect(await cells[0].isActive()).toBe(true);
|
||
expect(await cells[15].isActive()).toBe(false);
|
||
});
|
||
|
||
it('should get the state of the cell within the main range', async () => {
|
||
const calendar = await loader.getHarness(MatCalendarHarness.with({selector: '#range'}));
|
||
const allCells = await calendar.getCells();
|
||
const [initialStartStates, initialInRangeStates, initialEndStates] = await parallel(() => [
|
||
parallel(() => allCells.map(cell => cell.isRangeStart())),
|
||
parallel(() => allCells.map(cell => cell.isInRange())),
|
||
parallel(() => allCells.map(cell => cell.isRangeEnd())),
|
||
]);
|
||
|
||
expect(initialStartStates.every(state => state === false)).toBe(true);
|
||
expect(initialInRangeStates.every(state => state === false)).toBe(true);
|
||
expect(initialEndStates.every(state => state === false)).toBe(true);
|
||
|
||
await (await calendar.getCells({text: '5'}))[0].select();
|
||
await (await calendar.getCells({text: '8'}))[0].select();
|
||
|
||
expect(await allCells[4].isRangeStart()).toBe(true);
|
||
expect(await allCells[4].isInRange()).toBe(true);
|
||
expect(await allCells[4].isRangeEnd()).toBe(false);
|
||
|
||
expect(await allCells[5].isRangeStart()).toBe(false);
|
||
expect(await allCells[5].isInRange()).toBe(true);
|
||
expect(await allCells[5].isRangeEnd()).toBe(false);
|
||
|
||
expect(await allCells[6].isRangeStart()).toBe(false);
|
||
expect(await allCells[6].isInRange()).toBe(true);
|
||
expect(await allCells[6].isRangeEnd()).toBe(false);
|
||
|
||
expect(await allCells[7].isRangeStart()).toBe(false);
|
||
expect(await allCells[7].isInRange()).toBe(true);
|
||
expect(await allCells[7].isRangeEnd()).toBe(true);
|
||
});
|
||
|
||
it('should get the state of the cell within the comparison range', async () => {
|
||
const calendar = await loader.getHarness(MatCalendarHarness.with({selector: '#range'}));
|
||
const allCells = await calendar.getCells();
|
||
const [initialStartStates, initialInRangeStates, initialEndStates] = await parallel(() => [
|
||
parallel(() => allCells.map(cell => cell.isComparisonRangeStart())),
|
||
parallel(() => allCells.map(cell => cell.isInComparisonRange())),
|
||
parallel(() => allCells.map(cell => cell.isComparisonRangeEnd())),
|
||
]);
|
||
|
||
expect(initialStartStates.every(state => state === false)).toBe(true);
|
||
expect(initialInRangeStates.every(state => state === false)).toBe(true);
|
||
expect(initialEndStates.every(state => state === false)).toBe(true);
|
||
|
||
fixture.componentInstance.comparisonStart = new Date(
|
||
calendarDate.getFullYear(),
|
||
calendarDate.getMonth(),
|
||
5,
|
||
);
|
||
fixture.componentInstance.comparisonEnd = new Date(
|
||
calendarDate.getFullYear(),
|
||
calendarDate.getMonth(),
|
||
8,
|
||
);
|
||
fixture.changeDetectorRef.markForCheck();
|
||
|
||
expect(await allCells[4].isComparisonRangeStart()).toBe(true);
|
||
expect(await allCells[4].isInComparisonRange()).toBe(true);
|
||
expect(await allCells[4].isComparisonRangeEnd()).toBe(false);
|
||
|
||
expect(await allCells[5].isComparisonRangeStart()).toBe(false);
|
||
expect(await allCells[5].isInComparisonRange()).toBe(true);
|
||
expect(await allCells[5].isComparisonRangeEnd()).toBe(false);
|
||
|
||
expect(await allCells[6].isComparisonRangeStart()).toBe(false);
|
||
expect(await allCells[6].isInComparisonRange()).toBe(true);
|
||
expect(await allCells[6].isComparisonRangeEnd()).toBe(false);
|
||
|
||
expect(await allCells[7].isComparisonRangeStart()).toBe(false);
|
||
expect(await allCells[7].isInComparisonRange()).toBe(true);
|
||
expect(await allCells[7].isComparisonRangeEnd()).toBe(true);
|
||
});
|
||
|
||
it('should get the state of the cell within the preview range', async () => {
|
||
const calendar = await loader.getHarness(MatCalendarHarness.with({selector: '#range'}));
|
||
const allCells = await calendar.getCells();
|
||
const [initialStartStates, initialInRangeStates, initialEndStates] = await parallel(() => [
|
||
parallel(() => allCells.map(cell => cell.isPreviewRangeStart())),
|
||
parallel(() => allCells.map(cell => cell.isInPreviewRange())),
|
||
parallel(() => allCells.map(cell => cell.isPreviewRangeEnd())),
|
||
]);
|
||
|
||
expect(initialStartStates.every(state => state === false)).toBe(true);
|
||
expect(initialInRangeStates.every(state => state === false)).toBe(true);
|
||
expect(initialEndStates.every(state => state === false)).toBe(true);
|
||
|
||
await (await calendar.getCells({text: '5'}))[0].select();
|
||
await (await calendar.getCells({text: '8'}))[0].hover();
|
||
|
||
expect(await allCells[4].isPreviewRangeStart()).toBe(true);
|
||
expect(await allCells[4].isInPreviewRange()).toBe(true);
|
||
expect(await allCells[4].isPreviewRangeEnd()).toBe(false);
|
||
|
||
expect(await allCells[5].isPreviewRangeStart()).toBe(false);
|
||
expect(await allCells[5].isInPreviewRange()).toBe(true);
|
||
expect(await allCells[5].isPreviewRangeEnd()).toBe(false);
|
||
|
||
expect(await allCells[6].isPreviewRangeStart()).toBe(false);
|
||
expect(await allCells[6].isInPreviewRange()).toBe(true);
|
||
expect(await allCells[6].isPreviewRangeEnd()).toBe(false);
|
||
|
||
expect(await allCells[7].isPreviewRangeStart()).toBe(false);
|
||
expect(await allCells[7].isInPreviewRange()).toBe(true);
|
||
expect(await allCells[7].isPreviewRangeEnd()).toBe(true);
|
||
});
|
||
|
||
it('should filter cells by their text', async () => {
|
||
const calendar = await loader.getHarness(MatCalendarHarness.with({selector: '#single'}));
|
||
const cells = await calendar.getCells({text: /^3/});
|
||
expect(await parallel(() => cells.map(cell => cell.getText()))).toEqual(['3', '30', '31']);
|
||
});
|
||
|
||
it('should filter cells by their selected state', async () => {
|
||
const calendar = await loader.getHarness(MatCalendarHarness.with({selector: '#single'}));
|
||
const allCells = await calendar.getCells();
|
||
|
||
await allCells[0].select();
|
||
|
||
const selectedCells = await calendar.getCells({selected: true});
|
||
expect(await parallel(() => selectedCells.map(cell => cell.getText()))).toEqual(['1']);
|
||
});
|
||
|
||
it('should filter cells by their active state', async () => {
|
||
const calendar = await loader.getHarness(MatCalendarHarness.with({selector: '#single'}));
|
||
const cells = await calendar.getCells({active: true});
|
||
expect(await parallel(() => cells.map(cell => cell.getText()))).toEqual(['1']);
|
||
});
|
||
|
||
it('should filter cells by their disabled state', async () => {
|
||
fixture.componentInstance.minDate = new Date(
|
||
calendarDate.getFullYear(),
|
||
calendarDate.getMonth(),
|
||
3,
|
||
);
|
||
fixture.changeDetectorRef.markForCheck();
|
||
|
||
const calendar = await loader.getHarness(MatCalendarHarness.with({selector: '#single'}));
|
||
const cells = await calendar.getCells({disabled: true});
|
||
expect(await parallel(() => cells.map(cell => cell.getText()))).toEqual(['1', '2']);
|
||
});
|
||
|
||
it('should filter cells based on whether they are inside the comparison range', async () => {
|
||
const calendar = await loader.getHarness(MatCalendarHarness.with({selector: '#range'}));
|
||
|
||
fixture.componentInstance.comparisonStart = new Date(
|
||
calendarDate.getFullYear(),
|
||
calendarDate.getMonth(),
|
||
5,
|
||
);
|
||
fixture.componentInstance.comparisonEnd = new Date(
|
||
calendarDate.getFullYear(),
|
||
calendarDate.getMonth(),
|
||
8,
|
||
);
|
||
fixture.changeDetectorRef.markForCheck();
|
||
|
||
const cells = await calendar.getCells({inComparisonRange: true});
|
||
expect(await parallel(() => cells.map(cell => cell.getText()))).toEqual(['5', '6', '7', '8']);
|
||
});
|
||
|
||
it('should filter cells based on whether they are inside the preview range', async () => {
|
||
const calendar = await loader.getHarness(MatCalendarHarness.with({selector: '#range'}));
|
||
|
||
await (await calendar.getCells({text: '5'}))[0].select();
|
||
await (await calendar.getCells({text: '8'}))[0].hover();
|
||
|
||
const cells = await calendar.getCells({inPreviewRange: true});
|
||
expect(await parallel(() => cells.map(cell => cell.getText()))).toEqual(['5', '6', '7', '8']);
|
||
});
|
||
});
|
||
|
||
@Component({
|
||
template: `
|
||
<mat-calendar
|
||
id="single"
|
||
[startAt]="startAt"
|
||
[minDate]="minDate"
|
||
[selected]="singleValue"
|
||
(selectedChange)="singleValue = $event"></mat-calendar>
|
||
|
||
<mat-calendar
|
||
id="range"
|
||
[startAt]="startAt"
|
||
[minDate]="minDate"
|
||
[selected]="rangeValue"
|
||
[comparisonStart]="comparisonStart"
|
||
[comparisonEnd]="comparisonEnd"
|
||
(selectedChange)="rangeChanged($event)"></mat-calendar>
|
||
`,
|
||
standalone: true,
|
||
imports: [MatNativeDateModule, MatDatepickerModule],
|
||
})
|
||
class CalendarHarnessTest {
|
||
// Start the datepickers off at a specific date so tests
|
||
// run consistently no matter what the current date is.
|
||
readonly startAt = new Date(calendarDate);
|
||
minDate: Date | null;
|
||
singleValue: Date | null = null;
|
||
rangeValue = new DateRange<Date>(null, null);
|
||
comparisonStart: Date | null = null;
|
||
comparisonEnd: Date | null = null;
|
||
|
||
rangeChanged(selectedDate: Date) {
|
||
let {start, end} = this.rangeValue;
|
||
|
||
if (start == null || end != null) {
|
||
start = selectedDate;
|
||
} else if (end == null) {
|
||
end = selectedDate;
|
||
}
|
||
|
||
this.rangeValue = new DateRange<Date>(start, end);
|
||
}
|
||
}
|