| /******************************************************************************** |
| * Copyright (c) 2020 Contributors to the Eclipse Foundation |
| * |
| * See the NOTICE file(s) distributed with this work for additional |
| * information regarding copyright ownership. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0 |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| ********************************************************************************/ |
| |
| import {Component, ViewChild} from "@angular/core"; |
| import {async, ComponentFixture, TestBed} from "@angular/core/testing"; |
| import {FormsModule, NgForm, NgModel} from "@angular/forms"; |
| import {MatIcon} from "@angular/material/icon"; |
| import {By} from "@angular/platform-browser"; |
| import {BrowserAnimationsModule} from "@angular/platform-browser/animations"; |
| import {Calendar} from "primeng/calendar"; |
| import {EKeyboardKeys} from "../../../../util/events"; |
| import {DateControlModule} from "../date-control.module"; |
| import {DateControlComponent} from "./date-control.component"; |
| |
| describe("DateControlComponent", () => { |
| let component: DateControlSpecComponent; |
| let fixture: ComponentFixture<DateControlSpecComponent>; |
| let textInput: HTMLInputElement; |
| let matIcon: HTMLElement; |
| |
| function getCalendar(): Calendar { |
| try { |
| const componentInstance = fixture.debugElement.query(By.directive(Calendar)).componentInstance; |
| return componentInstance instanceof Calendar ? componentInstance : undefined; |
| } catch (e) { |
| return; |
| } |
| } |
| |
| function getCalendarDayElement(index: number): HTMLElement { |
| try { |
| return fixture?.debugElement == null ? [] : fixture.debugElement |
| .queryAll(By.css(".ui-state-default:not(.ui-state-disabled)")) |
| .map((debugElement) => debugElement.nativeElement)[index]; |
| } catch (e) { |
| return undefined; |
| } |
| } |
| |
| beforeEach(async(() => { |
| TestBed.configureTestingModule({ |
| declarations: [ |
| DateControlSpecComponent |
| ], |
| imports: [ |
| DateControlModule, |
| BrowserAnimationsModule, |
| FormsModule |
| ] |
| }).compileComponents(); |
| })); |
| |
| beforeEach(async () => { |
| fixture = TestBed.createComponent(DateControlSpecComponent); |
| component = fixture.componentInstance; |
| fixture.detectChanges(); |
| await fixture.whenStable(); |
| textInput = fixture.debugElement.query(By.css("input")).nativeElement; |
| matIcon = fixture.debugElement.query(By.directive(MatIcon)).nativeElement; |
| }); |
| |
| it("should register to Angular forms", async () => { |
| expect(component).toBeDefined(); |
| expect(component?.ngForm?.value).toBeDefined(); |
| expect(component.ngForm.value.date).toBe("2020-05-01"); |
| }); |
| |
| it("should update value via text input", async () => { |
| expect(textInput?.value).toBe("01.05.2020"); |
| |
| textInput.value = "02.05.2020"; |
| textInput.dispatchEvent(new InputEvent("input")); |
| fixture.detectChanges(); |
| expect(component.value).toBe("2020-05-02"); |
| expect(component.ngForm.value.date).toBe("2020-05-02"); |
| }); |
| |
| it("should handle faulty user input", async () => { |
| expect(textInput?.value).toBe("01.05.2020"); |
| |
| textInput.value = "19.05.2020abcdef"; |
| textInput.dispatchEvent(new InputEvent("input")); |
| fixture.detectChanges(); |
| |
| expect(component.value).toBe("2020-05-19"); |
| expect(component.ngForm.value.date).toBe("2020-05-19"); |
| expect(textInput.value).toBe("19.05.2020abcdef"); |
| |
| textInput.dispatchEvent(new Event("blur")); |
| fixture.detectChanges(); |
| |
| expect(component.value).toBe("2020-05-19"); |
| expect(component.ngForm.value.date).toBe("2020-05-19"); |
| expect(textInput.value).toBe("19.05.2020"); |
| }); |
| |
| it("should update value via calendar", async () => { |
| expect(component.value).toBe("2020-05-01"); |
| |
| component.dateControlComponent.toggle(true); |
| await fixture.whenStable(); |
| fixture.detectChanges(); |
| |
| const dayElement = getCalendarDayElement(19); |
| dayElement.dispatchEvent(new Event("click")); |
| expect(component.value).toBe("2020-05-20"); |
| expect(component.ngForm.value.date).toBe("2020-05-20"); |
| await fixture.whenStable(); |
| fixture.detectChanges(); |
| |
| expect(getCalendar()).not.toBeDefined(); |
| }); |
| |
| it("should toggle overlay", async () => { |
| expect(getCalendar()).not.toBeDefined(); |
| |
| textInput.dispatchEvent(new Event("mousedown")); |
| expect(getCalendar()).toBeDefined(); |
| |
| textInput.dispatchEvent(new Event("mousedown")); |
| expect(getCalendar()).toBeDefined(); |
| |
| document.dispatchEvent(new Event("click")); |
| expect(getCalendar()).not.toBeDefined(); |
| |
| matIcon.dispatchEvent(new Event("mousedown")); |
| expect(getCalendar()).toBeDefined(); |
| |
| matIcon.dispatchEvent(new Event("mousedown")); |
| expect(getCalendar()).not.toBeDefined(); |
| }); |
| |
| it("should close overlay when tabbing or pressing enter from the text input", async () => { |
| textInput.dispatchEvent(new Event("mousedown")); |
| fixture.detectChanges(); |
| await fixture.whenStable(); |
| expect(getCalendar()).toBeDefined(); |
| |
| textInput.dispatchEvent(new KeyboardEvent("keydown", {key: EKeyboardKeys.TAB})); |
| fixture.detectChanges(); |
| await fixture.whenStable(); |
| |
| expect(getCalendar()).not.toBeDefined(); |
| |
| textInput.dispatchEvent(new Event("mousedown")); |
| fixture.detectChanges(); |
| await fixture.whenStable(); |
| expect(getCalendar()).toBeDefined(); |
| |
| textInput.dispatchEvent(new KeyboardEvent("keydown", {key: "Enter"})); |
| fixture.detectChanges(); |
| await fixture.whenStable(); |
| |
| expect(getCalendar()).not.toBeDefined(); |
| }); |
| |
| it("should close overlay when tabbing from the calendar", async () => { |
| component.dateControlComponent.toggle(true); |
| fixture.detectChanges(); |
| await fixture.whenStable(); |
| expect(getCalendar()).toBeDefined(); |
| |
| getCalendar().el.nativeElement.dispatchEvent(new KeyboardEvent("keydown", {key: EKeyboardKeys.TAB})); |
| fixture.detectChanges(); |
| await fixture.whenStable(); |
| |
| expect(getCalendar()).not.toBeDefined(); |
| }); |
| |
| it("should allow no interactions when disabled", async () => { |
| component.dateControlComponent.toggle(true); |
| fixture.detectChanges(); |
| await fixture.whenStable(); |
| |
| expect(getCalendar()).toBeDefined(); |
| |
| component.ngModel.control.disable(); |
| fixture.detectChanges(); |
| await fixture.whenStable(); |
| expect(textInput.disabled).toBeTrue(); |
| expect(getCalendar()).not.toBeDefined(); |
| |
| textInput.dispatchEvent(new Event("click")); |
| fixture.detectChanges(); |
| await fixture.whenStable(); |
| expect(textInput.disabled).toBeTrue(); |
| expect(getCalendar()).not.toBeDefined(); |
| }); |
| |
| }); |
| |
| @Component({ |
| selector: "app-date-control-spec", |
| template: ` |
| <form> |
| <app-date-control [(appValue)]="value" [ngModel]="value" name="date"> |
| </app-date-control> |
| </form> |
| ` |
| }) |
| class DateControlSpecComponent { |
| |
| public value = "2020-05-01"; |
| |
| @ViewChild(NgForm) |
| public ngForm: NgForm; |
| |
| @ViewChild(NgModel) |
| public ngModel: NgModel; |
| |
| @ViewChild(DateControlComponent) |
| public dateControlComponent: DateControlComponent; |
| |
| } |