318 lines
11 KiB
TypeScript
318 lines
11 KiB
TypeScript
import {Component, ElementRef, Type, ViewChild} from '@angular/core';
|
|
import {ComponentFixture, TestBed, fakeAsync, flush, tick} from '@angular/core/testing';
|
|
import {FormControl, FormsModule, ReactiveFormsModule} from '@angular/forms';
|
|
import {MatNativeDateModule} from '@angular/material/core';
|
|
import {MatFormFieldModule} from '@angular/material/form-field';
|
|
import {MatInputModule} from '@angular/material/input';
|
|
import {NoopAnimationsModule} from '@angular/platform-browser/animations';
|
|
import {MatDatepicker} from './datepicker';
|
|
import {MatDatepickerModule} from './datepicker-module';
|
|
|
|
describe('MatDatepickerActions', () => {
|
|
function createComponent<T>(component: Type<T>): ComponentFixture<T> {
|
|
TestBed.configureTestingModule({
|
|
declarations: [component],
|
|
imports: [
|
|
FormsModule,
|
|
MatDatepickerModule,
|
|
MatFormFieldModule,
|
|
MatInputModule,
|
|
NoopAnimationsModule,
|
|
ReactiveFormsModule,
|
|
MatNativeDateModule,
|
|
],
|
|
});
|
|
|
|
return TestBed.createComponent(component);
|
|
}
|
|
|
|
it('should render the actions inside calendar panel in popup mode', fakeAsync(() => {
|
|
const fixture = createComponent(DatepickerWithActions);
|
|
fixture.detectChanges();
|
|
fixture.componentInstance.datepicker.open();
|
|
fixture.detectChanges();
|
|
tick();
|
|
flush();
|
|
|
|
const actions = document.querySelector('.mat-datepicker-content .mat-datepicker-actions');
|
|
expect(actions).toBeTruthy();
|
|
expect(actions?.querySelector('.cancel')).toBeTruthy();
|
|
expect(actions?.querySelector('.apply')).toBeTruthy();
|
|
}));
|
|
|
|
it('should render the actions inside calendar panel in touch UI mode', fakeAsync(() => {
|
|
const fixture = createComponent(DatepickerWithActions);
|
|
fixture.componentInstance.touchUi = true;
|
|
fixture.changeDetectorRef.markForCheck();
|
|
fixture.detectChanges();
|
|
fixture.componentInstance.datepicker.open();
|
|
fixture.detectChanges();
|
|
tick();
|
|
flush();
|
|
|
|
const actions = document.querySelector('.mat-datepicker-content .mat-datepicker-actions');
|
|
expect(actions).toBeTruthy();
|
|
expect(actions?.querySelector('.cancel')).toBeTruthy();
|
|
expect(actions?.querySelector('.apply')).toBeTruthy();
|
|
}));
|
|
|
|
it('should not assign the value or close the datepicker when a value is selected', fakeAsync(() => {
|
|
const fixture = createComponent(DatepickerWithActions);
|
|
fixture.detectChanges();
|
|
const {control, datepicker, onDateChange, input} = fixture.componentInstance;
|
|
datepicker.open();
|
|
fixture.detectChanges();
|
|
tick();
|
|
|
|
const content = document.querySelector('.mat-datepicker-content')!;
|
|
const cells = content.querySelectorAll<HTMLElement>('.mat-calendar-body-cell');
|
|
|
|
expect(datepicker.opened).toBe(true);
|
|
expect(input.nativeElement.value).toBeFalsy();
|
|
expect(control.value).toBeFalsy();
|
|
expect(onDateChange).not.toHaveBeenCalled();
|
|
expect(content.querySelector('.mat-calendar-body-selected')).toBeFalsy();
|
|
|
|
cells[10].click();
|
|
fixture.detectChanges();
|
|
flush();
|
|
|
|
expect(datepicker.opened).toBe(true);
|
|
expect(input.nativeElement.value).toBeFalsy();
|
|
expect(control.value).toBeFalsy();
|
|
expect(onDateChange).not.toHaveBeenCalled();
|
|
expect(content.querySelector('.mat-calendar-body-selected')).toBeTruthy();
|
|
}));
|
|
|
|
it('should close without changing the value when clicking on the cancel button', fakeAsync(() => {
|
|
const fixture = createComponent(DatepickerWithActions);
|
|
fixture.detectChanges();
|
|
const {control, datepicker, onDateChange, input} = fixture.componentInstance;
|
|
datepicker.open();
|
|
fixture.detectChanges();
|
|
tick();
|
|
flush();
|
|
|
|
const content = document.querySelector('.mat-datepicker-content')!;
|
|
const cells = content.querySelectorAll<HTMLElement>('.mat-calendar-body-cell');
|
|
|
|
expect(datepicker.opened).toBe(true);
|
|
expect(input.nativeElement.value).toBeFalsy();
|
|
expect(control.value).toBeFalsy();
|
|
expect(onDateChange).not.toHaveBeenCalled();
|
|
expect(content.querySelector('.mat-calendar-body-selected')).toBeFalsy();
|
|
|
|
cells[10].click();
|
|
fixture.detectChanges();
|
|
tick();
|
|
flush();
|
|
|
|
expect(datepicker.opened).toBe(true);
|
|
expect(input.nativeElement.value).toBeFalsy();
|
|
expect(control.value).toBeFalsy();
|
|
expect(onDateChange).not.toHaveBeenCalled();
|
|
expect(content.querySelector('.mat-calendar-body-selected')).toBeTruthy();
|
|
|
|
(content.querySelector('.cancel') as HTMLElement).click();
|
|
fixture.detectChanges();
|
|
flush();
|
|
|
|
expect(datepicker.opened).toBe(false);
|
|
expect(input.nativeElement.value).toBeFalsy();
|
|
expect(control.value).toBeFalsy();
|
|
expect(onDateChange).not.toHaveBeenCalled();
|
|
}));
|
|
|
|
it('should close while keeping the previous control value when clicking on cancel', fakeAsync(() => {
|
|
const fixture = createComponent(DatepickerWithActions);
|
|
fixture.detectChanges();
|
|
const {control, datepicker, onDateChange} = fixture.componentInstance;
|
|
const value = new Date(2021, 0, 20);
|
|
control.setValue(value);
|
|
fixture.detectChanges();
|
|
datepicker.open();
|
|
fixture.detectChanges();
|
|
tick();
|
|
flush();
|
|
|
|
const content = document.querySelector('.mat-datepicker-content')!;
|
|
const cells = content.querySelectorAll<HTMLElement>('.mat-calendar-body-cell');
|
|
|
|
expect(datepicker.opened).toBe(true);
|
|
expect(control.value).toBe(value);
|
|
expect(onDateChange).not.toHaveBeenCalled();
|
|
|
|
cells[10].click();
|
|
fixture.detectChanges();
|
|
tick();
|
|
flush();
|
|
|
|
expect(datepicker.opened).toBe(true);
|
|
expect(control.value).toBe(value);
|
|
expect(onDateChange).not.toHaveBeenCalled();
|
|
|
|
(content.querySelector('.cancel') as HTMLElement).click();
|
|
fixture.detectChanges();
|
|
flush();
|
|
|
|
expect(datepicker.opened).toBe(false);
|
|
expect(control.value).toBe(value);
|
|
expect(onDateChange).not.toHaveBeenCalled();
|
|
}));
|
|
|
|
it('should close and accept the value when clicking on the apply button', fakeAsync(() => {
|
|
const fixture = createComponent(DatepickerWithActions);
|
|
fixture.detectChanges();
|
|
const {control, datepicker, onDateChange, input} = fixture.componentInstance;
|
|
datepicker.open();
|
|
fixture.detectChanges();
|
|
tick();
|
|
flush();
|
|
|
|
const content = document.querySelector('.mat-datepicker-content')!;
|
|
const cells = content.querySelectorAll<HTMLElement>('.mat-calendar-body-cell');
|
|
|
|
expect(datepicker.opened).toBe(true);
|
|
expect(input.nativeElement.value).toBeFalsy();
|
|
expect(control.value).toBeFalsy();
|
|
expect(onDateChange).not.toHaveBeenCalled();
|
|
expect(content.querySelector('.mat-calendar-body-selected')).toBeFalsy();
|
|
|
|
cells[10].click();
|
|
fixture.detectChanges();
|
|
tick();
|
|
flush();
|
|
|
|
expect(datepicker.opened).toBe(true);
|
|
expect(input.nativeElement.value).toBeFalsy();
|
|
expect(control.value).toBeFalsy();
|
|
expect(onDateChange).not.toHaveBeenCalled();
|
|
expect(content.querySelector('.mat-calendar-body-selected')).toBeTruthy();
|
|
|
|
(content.querySelector('.apply') as HTMLElement).click();
|
|
fixture.detectChanges();
|
|
flush();
|
|
|
|
expect(datepicker.opened).toBe(false);
|
|
expect(input.nativeElement.value).toBeTruthy();
|
|
expect(control.value).toBeTruthy();
|
|
expect(onDateChange).toHaveBeenCalledTimes(1);
|
|
}));
|
|
|
|
it('should revert to the default behavior if the actions are removed', fakeAsync(() => {
|
|
const fixture = createComponent(DatepickerWithActions);
|
|
fixture.detectChanges();
|
|
const {control, datepicker, onDateChange} = fixture.componentInstance;
|
|
datepicker.open();
|
|
fixture.detectChanges();
|
|
tick();
|
|
flush();
|
|
|
|
let content = document.querySelector('.mat-datepicker-content')!;
|
|
let actions = content.querySelector('.mat-datepicker-actions')!;
|
|
let cells = content.querySelectorAll<HTMLElement>('.mat-calendar-body-cell');
|
|
|
|
expect(actions).toBeTruthy();
|
|
expect(datepicker.opened).toBe(true);
|
|
expect(control.value).toBeFalsy();
|
|
expect(onDateChange).not.toHaveBeenCalled();
|
|
|
|
cells[10].click();
|
|
fixture.detectChanges();
|
|
tick();
|
|
flush();
|
|
|
|
expect(datepicker.opened).toBe(true);
|
|
expect(control.value).toBeFalsy();
|
|
expect(onDateChange).not.toHaveBeenCalled();
|
|
|
|
(actions.querySelector('.cancel') as HTMLElement).click();
|
|
fixture.detectChanges();
|
|
flush();
|
|
|
|
expect(datepicker.opened).toBe(false);
|
|
expect(control.value).toBeFalsy();
|
|
expect(onDateChange).not.toHaveBeenCalled();
|
|
|
|
fixture.componentInstance.renderActions = false;
|
|
fixture.changeDetectorRef.markForCheck();
|
|
fixture.detectChanges();
|
|
datepicker.open();
|
|
fixture.detectChanges();
|
|
content = document.querySelector('.mat-datepicker-content')!;
|
|
actions = content.querySelector('.mat-datepicker-actions')!;
|
|
cells = content.querySelectorAll<HTMLElement>('.mat-calendar-body-cell');
|
|
|
|
expect(actions).toBeFalsy();
|
|
expect(datepicker.opened).toBe(true);
|
|
expect(control.value).toBeFalsy();
|
|
expect(onDateChange).not.toHaveBeenCalled();
|
|
|
|
cells[10].click();
|
|
fixture.detectChanges();
|
|
tick();
|
|
flush();
|
|
|
|
expect(datepicker.opened).toBe(false);
|
|
expect(control.value).toBeTruthy();
|
|
expect(onDateChange).toHaveBeenCalledTimes(1);
|
|
}));
|
|
|
|
it('should be able to toggle the actions while the datepicker is open', fakeAsync(() => {
|
|
const fixture = createComponent(DatepickerWithActions);
|
|
fixture.componentInstance.renderActions = false;
|
|
fixture.changeDetectorRef.markForCheck();
|
|
fixture.detectChanges();
|
|
|
|
fixture.componentInstance.datepicker.open();
|
|
fixture.detectChanges();
|
|
tick();
|
|
flush();
|
|
|
|
const content = document.querySelector('.mat-datepicker-content')!;
|
|
expect(content.querySelector('.mat-datepicker-actions')).toBeFalsy();
|
|
|
|
fixture.componentInstance.renderActions = true;
|
|
fixture.changeDetectorRef.markForCheck();
|
|
fixture.detectChanges();
|
|
expect(content.querySelector('.mat-datepicker-actions')).toBeTruthy();
|
|
|
|
fixture.componentInstance.renderActions = false;
|
|
fixture.changeDetectorRef.markForCheck();
|
|
fixture.detectChanges();
|
|
expect(content.querySelector('.mat-datepicker-actions')).toBeFalsy();
|
|
}));
|
|
});
|
|
|
|
@Component({
|
|
template: `
|
|
<mat-form-field>
|
|
<mat-label>Pick a date</mat-label>
|
|
<input
|
|
#input
|
|
matInput
|
|
[matDatepicker]="picker"
|
|
[formControl]="control"
|
|
(dateChange)="onDateChange()">
|
|
<mat-datepicker #picker [touchUi]="touchUi" [startAt]="startAt">
|
|
@if (renderActions) {
|
|
<mat-datepicker-actions>
|
|
<button mat-button class="cancel" matDatepickerCancel>Cancel</button>
|
|
<button mat-raised-button class="apply" matDatepickerApply>Apply</button>
|
|
</mat-datepicker-actions>
|
|
}
|
|
</mat-datepicker>
|
|
</mat-form-field>
|
|
`,
|
|
standalone: false,
|
|
})
|
|
class DatepickerWithActions {
|
|
@ViewChild(MatDatepicker) datepicker: MatDatepicker<Date>;
|
|
@ViewChild('input', {read: ElementRef}) input: ElementRef<HTMLInputElement>;
|
|
control = new FormControl<Date | null>(null);
|
|
onDateChange = jasmine.createSpy('dateChange spy');
|
|
touchUi = false;
|
|
startAt = new Date(2021, 0, 15);
|
|
renderActions = true;
|
|
}
|