sass-references/angular-material/material/datepicker/datepicker-actions.spec.ts

318 lines
11 KiB
TypeScript
Raw Normal View History

2024-12-06 10:42:08 +08:00
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;
}