import { format , fromUnixTime , isSameDay } from 'date-fns' ; import { dispatchKeyboardEvent , dispatchMouseEvent } from 'ngx-tethys/testing' ; import { ESCAPE } from '@angular/cdk/keycodes' ; import { OverlayContainer } from '@angular/cdk/overlay' ; import { registerLocaleData } from '@angular/common' ; import zh from '@angular/common/locales/zh' ; import { Component , DebugElement , TemplateRef , ViewChild } from '@angular/core' ; import { ComponentFixture , fakeAsync , flush , inject , TestBed , tick } from '@angular/core/testing' ; import { FormsModule } from '@angular/forms' ; import { By } from '@angular/platform-browser' ; import { ThyDatePickerModule } from './date-picker.module' ; import { ThyPickerComponent } from './picker.component' ; import { DateEntry } from './standard-types' ; registerLocaleData ( zh ) ; describe ( 'ThyDatePickerComponent' , ( ) => { let fixture ; let fixtureInstance ; let debugElement ; let overlayContainer ; let overlayContainerElement ; beforeEach ( fakeAsync ( ( ) => { TestBed . configureTestingModule ( { imports : [ FormsModule , ThyDatePickerModule ] , declarations : [ ThyTestDatePickerComponent ] } ) ; TestBed . compileComponents ( ) ; } ) ) ; beforeEach ( ( ) => { fixture = TestBed . createComponent ( ThyTestDatePickerComponent ) ; fixtureInstance = fixture . componentInstance ; debugElement = fixture . debugElement ; } ) ; beforeEach ( inject ( [ OverlayContainer ] , ( oc ) => { overlayContainer = oc ; overlayContainerElement = oc . getContainerElement ( ) ; } ) ) ; afterEach ( ( ) => { overlayContainer . ngOnDestroy ( ) ; } ) ; describe ( 'general api testing' , ( ) => { beforeEach ( ( ) => ( fixtureInstance . useSuite = 1 ) ) ; it ( 'should open by click and close by click at outside' , fakeAsync ( ( ) => { fixture . detectChanges ( ) ; dispatchMouseEvent ( getPickerTriggerWrapper ( ) , 'click' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; expect ( getPickerContainer ( ) ) . not . toBeNull ( ) ; dispatchMouseEvent ( queryFromOverlay ( '.cdk-overlay-backdrop' ) , 'click' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; expect ( getPickerContainer ( ) ) . toBeNull ( ) ; } ) ) ; it ( 'should focus on the trigger after a click outside' , fakeAsync ( ( ) => { fixture . detectChanges ( ) ; openPickerByClickTrigger ( ) ; dispatchMouseEvent ( queryFromOverlay ( '.cdk-overlay-backdrop' ) , 'click' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; expect ( document . activeElement ) . toEqual ( getPickerTrigger ( ) ) ; } ) ) ; it ( 'should be openable after closed by "Escape" key' , fakeAsync ( ( ) => { fixture . detectChanges ( ) ; dispatchMouseEvent ( getPickerTriggerWrapper ( ) , 'click' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; expect ( getPickerContainer ( ) ) . not . toBeNull ( ) ; dispatchKeyboardEvent ( document . body , 'keydown' , ESCAPE ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; expect ( getPickerContainer ( ) ) . toBeNull ( ) ; dispatchMouseEvent ( getPickerTriggerWrapper ( ) , 'click' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; expect ( getPickerContainer ( ) ) . not . toBeNull ( ) ; } ) ) ; it ( 'should support thyAllowClear and work properly' , fakeAsync ( ( ) => { const clearBtnSelector = By . css ( 'thy-picker .thy-calendar-picker-clear .thy-icon' ) ; const initial = ( fixtureInstance . thyValue = new Date ( ) ) ; fixtureInstance . thyAllowClear = false ; fixture . detectChanges ( ) ; expect ( debugElement . query ( clearBtnSelector ) ) . toBeFalsy ( ) ; fixtureInstance . thyAllowClear = true ; tick ( 500 ) ; fixture . detectChanges ( ) ; expect ( fixtureInstance . thyValue ) . toBe ( initial ) ; expect ( debugElement . query ( clearBtnSelector ) ) . toBeDefined ( ) ; const thyOnChange = spyOn ( fixtureInstance , 'thyOnChange' ) ; debugElement . query ( clearBtnSelector ) . nativeElement . click ( ) ; fixture . detectChanges ( ) ; expect ( fixtureInstance . thyValue ) . toBe ( initial ) ; expect ( thyOnChange ) . toHaveBeenCalledWith ( null ) ; expect ( debugElement . query ( clearBtnSelector ) ) . toBeFalsy ( ) ; } ) ) ; it ( 'should support thyAutoFocus' , ( ) => { fixtureInstance . thyAutoFocus = true ; fixture . detectChanges ( ) ; expect ( getPickerTrigger ( ) === document . activeElement ) . toBeTruthy ( ) ; } ) ; it ( 'should support thyDisabled' , fakeAsync ( ( ) => { fixtureInstance . thyAllowClear = true ; fixtureInstance . thyValue = new Date ( ) ; fixtureInstance . thyDisabled = true ; fixture . detectChanges ( ) ; flush ( ) ; fixture . detectChanges ( ) ; expect ( debugElement . query ( By . css ( 'thy-picker .thy-input-disabled' ) ) ) . toBeDefined ( ) ; expect ( debugElement . query ( By . css ( 'thy-picker thy-icon.thy-calendar-picker-clear' ) ) ) . toBeNull ( ) ; fixtureInstance . thyDisabled = false ; tick ( 500 ) ; fixture . detectChanges ( ) ; expect ( debugElement . query ( By . css ( 'thy-picker .thy-input-disabled' ) ) ) . toBeNull ( ) ; expect ( debugElement . query ( By . css ( 'thy-picker thy-icon.thy-calendar-picker-clear' ) ) ) . toBeDefined ( ) ; } ) ) ; it ( 'should support thyDisabledDate' , fakeAsync ( ( ) => { fixture . detectChanges ( ) ; const compareDate = new Date ( '2018-11-15 00:00:00' ) ; fixtureInstance . thyValue = new Date ( '2018-11-11 12:12:12' ) ; fixtureInstance . thyDisabledDate = ( current ) => isSameDay ( current , compareDate ) ; fixture . detectChanges ( ) ; dispatchMouseEvent ( getPickerTriggerWrapper ( ) , 'click' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; const disabledCell = queryFromOverlay ( 'tbody.thy-calendar-tbody td.thy-calendar-disabled-cell' ) ; expect ( disabledCell . textContent . trim ( ) ) . toBe ( '15' ) ; } ) ) ; it ( 'should support thyPlaceHolder' , ( ) => { const featureKey = ( fixtureInstance . thyPlaceHolder = 'TEST_PLACEHOLDER' ) ; fixture . detectChanges ( ) ; expect ( getPickerTrigger ( ) . getAttribute ( 'placeholder' ) ) . toBe ( featureKey ) ; } ) ; it ( 'should support thySize' , ( ) => { fixture . detectChanges ( ) ; expect ( getPickerTrigger ( ) . classList . contains ( 'form-control-lg' ) ) . not . toBeTruthy ( ) ; fixtureInstance . thySize = 'lg' ; fixture . detectChanges ( ) ; expect ( getPickerTrigger ( ) . classList . contains ( 'form-control-lg' ) ) . toBeTruthy ( ) ; } ) ; it ( 'should support thySuffixIcon' , ( ) => { fixture . detectChanges ( ) ; expect ( getPickerTriggerWrapper ( ) . querySelector ( '.thy-icon-angry' ) ) . toBeNull ( ) ; fixtureInstance . thySuffixIcon = 'angry' ; fixture . detectChanges ( ) ; expect ( getPickerTriggerWrapper ( ) . querySelector ( '.thy-icon-angry' ) ) . toBeTruthy ( ) ; } ) ; it ( 'should support thyReadonly' , fakeAsync ( ( ) => { fixtureInstance . thyReadonly = true ; fixture . detectChanges ( ) ; expect ( getPickerTrigger ( ) . readOnly ) . toBe ( true ) ; fixtureInstance . thyReadonly = false ; fixture . detectChanges ( ) ; expect ( getPickerTrigger ( ) . readOnly ) . not . toBe ( false ) ; } ) ) ; it ( 'should support thyFormat' , fakeAsync ( ( ) => { fixtureInstance . thyFormat = 'dd.MM.yyyy' ; fixtureInstance . thyValue = new Date ( '2020-03-04' ) ; fixture . detectChanges ( ) ; openPickerByClickTrigger ( ) ; const input = getPickerTrigger ( ) ; expect ( input . value ) . toBe ( '04.03.2020' ) ; } ) ) ; it ( 'should support thyOpenChange' , ( ) => { const thyOpenChange = spyOn ( fixtureInstance , 'thyOpenChange' ) ; fixture . detectChanges ( ) ; dispatchMouseEvent ( getPickerTriggerWrapper ( ) , 'click' ) ; fixture . detectChanges ( ) ; expect ( thyOpenChange ) . toHaveBeenCalledWith ( true ) ; dispatchMouseEvent ( queryFromOverlay ( '.cdk-overlay-backdrop' ) , 'click' ) ; fixture . detectChanges ( ) ; expect ( thyOpenChange ) . toHaveBeenCalledWith ( false ) ; expect ( thyOpenChange ) . toHaveBeenCalledTimes ( 2 ) ; } ) ; it ( 'should not emit thyOpenChange when thyOpen is false and input is clicked' , ( ) => { const thyOpenChange = spyOn ( fixtureInstance , 'thyOpenChange' ) ; fixtureInstance . useSuite = 2 ; fixtureInstance . thyOpen = false ; fixture . detectChanges ( ) ; dispatchMouseEvent ( getPickerTriggerWrapper ( ) , 'click' ) ; fixture . detectChanges ( ) ; expect ( thyOpenChange ) . not . toHaveBeenCalledWith ( true ) ; } ) ; it ( 'should support thyValue' , fakeAsync ( ( ) => { fixtureInstance . thyValue = new Date ( '2018-11-11' ) ; fixture . detectChanges ( ) ; dispatchMouseEvent ( getPickerTriggerWrapper ( ) , 'click' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; expect ( getSelectedDayCell ( ) . textContent . trim ( ) ) . toBe ( '11' ) ; } ) ) ; it ( 'should support thyDefaultPickerValue' , fakeAsync ( ( ) => { fixtureInstance . thyDefaultPickerValue = new Date ( '2021-10-10' ) ; fixture . detectChanges ( ) ; openPickerByClickTrigger ( ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; expect ( getSelectedDayCell ( ) . textContent . trim ( ) ) . toBe ( '10' ) ; expect ( queryFromOverlay ( '.thy-calendar-year-btn' ) . textContent . includes ( '2021' ) ) . toBeTruthy ( ) ; expect ( queryFromOverlay ( '.thy-calendar-month-btn' ) . textContent . includes ( '10' ) ) . toBeTruthy ( ) ; } ) ) ; it ( 'should support thyOnChange' , fakeAsync ( ( ) => { fixtureInstance . thyValue = new Date ( '2018-11-11' ) ; const thyOnChange = spyOn ( fixtureInstance , 'thyOnChange' ) ; const thyOnCalendarChange = spyOn ( fixtureInstance , 'thyOnCalendarChange' ) ; fixture . detectChanges ( ) ; dispatchMouseEvent ( getPickerTriggerWrapper ( ) , 'click' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; const cell = getFirstCell ( ) ; const cellText = cell . textContent . trim ( ) ; dispatchMouseEvent ( cell , 'click' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; expect ( thyOnChange ) . toHaveBeenCalled ( ) ; expect ( thyOnCalendarChange ) . not . toHaveBeenCalled ( ) ; const result = ( thyOnChange . calls . allArgs ( ) [ 0 ] as number [ ] ) [ 0 ] ; expect ( fromUnixTime ( result ) . getDate ( ) ) . toBe ( + cellText ) ; } ) ) ; } ) ; describe ( 'panel switch and move forward/afterward' , ( ) => { beforeEach ( ( ) => ( fixtureInstance . useSuite = 1 ) ) ; it ( 'should support date panel changes' , fakeAsync ( ( ) => { fixtureInstance . thyValue = new Date ( '2018-11-11' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; openPickerByClickTrigger ( ) ; dispatchMouseEvent ( queryFromOverlay ( '.thy-calendar-prev-year-btn' ) , 'click' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; expect ( queryFromOverlay ( '.thy-calendar-year-btn' ) . textContent . indexOf ( '2017' ) > - 1 ) . toBeTruthy ( ) ; dispatchMouseEvent ( queryFromOverlay ( '.thy-calendar-next-year-btn' ) , 'click' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; dispatchMouseEvent ( queryFromOverlay ( '.thy-calendar-next-year-btn' ) , 'click' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; expect ( queryFromOverlay ( '.thy-calendar-year-btn' ) . textContent . indexOf ( '2019' ) > - 1 ) . toBeTruthy ( ) ; dispatchMouseEvent ( queryFromOverlay ( '.thy-calendar-prev-month-btn' ) , 'click' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; expect ( queryFromOverlay ( '.thy-calendar-month-btn' ) . textContent . indexOf ( '10' ) > - 1 ) . toBeTruthy ( ) ; dispatchMouseEvent ( queryFromOverlay ( '.thy-calendar-next-month-btn' ) , 'click' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; dispatchMouseEvent ( queryFromOverlay ( '.thy-calendar-next-month-btn' ) , 'click' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; expect ( queryFromOverlay ( '.thy-calendar-month-btn' ) . textContent . indexOf ( '12' ) > - 1 ) . toBeTruthy ( ) ; } ) ) ; it ( 'should set correct cell selected' , fakeAsync ( ( ) => { fixtureInstance . thyValue = new Date ( '2018-11-11' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; openPickerByClickTrigger ( ) ; expect ( getSelectedDayCell ( ) . textContent . trim ( ) ) . toBe ( '11' ) ; dispatchMouseEvent ( queryFromOverlay ( '.thy-calendar-next-month-btn' ) , 'click' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; expect ( getSelectedDayCell ( ) ) . toBeNull ( ) ; dispatchMouseEvent ( queryFromOverlay ( '.thy-calendar-prev-month-btn' ) , 'click' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; expect ( getSelectedDayCell ( ) . textContent . trim ( ) ) . toBe ( '11' ) ; } ) ) ; it ( 'should support month panel changes' , fakeAsync ( ( ) => { fixtureInstance . thyValue = new Date ( '2018-11-11' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; openPickerByClickTrigger ( ) ; dispatchMouseEvent ( queryFromOverlay ( '.thy-calendar-header .thy-calendar-month-btn' ) , 'click' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; expect ( queryFromOverlay ( '.thy-calendar .thy-calendar-month' ) ) . toBeDefined ( ) ; expect ( queryFromOverlay ( '.thy-calendar-my-select' ) . textContent . indexOf ( '2018' ) > - 1 ) . toBeTruthy ( ) ; dispatchMouseEvent ( queryFromOverlay ( '.thy-calendar-prev-year-btn' ) , 'click' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; expect ( queryFromOverlay ( '.thy-calendar-my-select' ) . textContent . indexOf ( '2017' ) > - 1 ) . toBeTruthy ( ) ; dispatchMouseEvent ( queryFromOverlay ( '.thy-calendar-next-year-btn' ) , 'click' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; expect ( queryFromOverlay ( '.thy-calendar-my-select' ) . textContent . indexOf ( '2018' ) > - 1 ) . toBeTruthy ( ) ; dispatchMouseEvent ( queryFromOverlay ( '.thy-calendar-month-panel-selected-cell' ) , 'click' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; expect ( queryFromOverlay ( '.thy-calendar .thy-calendar-month' ) ) . toBeFalsy ( ) ; } ) ) ; it ( 'should support year panel changes' , fakeAsync ( ( ) => { fixtureInstance . thyValue = new Date ( '2018-11-11' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; openPickerByClickTrigger ( ) ; dispatchMouseEvent ( queryFromOverlay ( '.thy-calendar .thy-calendar-year-btn' ) , 'click' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; expect ( queryFromOverlay ( '.thy-calendar .thy-calendar-year' ) ) . toBeDefined ( ) ; expect ( queryFromOverlay ( '.thy-calendar-year-btn' ) . textContent . indexOf ( '2010' ) > - 1 ) . toBeTruthy ( ) ; expect ( queryFromOverlay ( '.thy-calendar-year-btn' ) . textContent . indexOf ( '2019' ) > - 1 ) . toBeTruthy ( ) ; dispatchMouseEvent ( queryFromOverlay ( '.thy-calendar-prev-year-btn' ) , 'click' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; expect ( queryFromOverlay ( '.thy-calendar-year-btn' ) . textContent . indexOf ( '2000' ) > - 1 ) . toBeTruthy ( ) ; expect ( queryFromOverlay ( '.thy-calendar-year-btn' ) . textContent . indexOf ( '2009' ) > - 1 ) . toBeTruthy ( ) ; dispatchMouseEvent ( queryFromOverlay ( '.thy-calendar-next-year-btn' ) , 'click' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; dispatchMouseEvent ( queryFromOverlay ( '.thy-calendar-next-year-btn' ) , 'click' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; expect ( queryFromOverlay ( '.thy-calendar-year-btn' ) . textContent . indexOf ( '2020' ) > - 1 ) . toBeTruthy ( ) ; expect ( queryFromOverlay ( '.thy-calendar-year-btn' ) . textContent . indexOf ( '2029' ) > - 1 ) . toBeTruthy ( ) ; dispatchMouseEvent ( queryFromOverlay ( 'td.thy-calendar-year-panel-cell' ) , 'click' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; expect ( queryFromOverlay ( '.thy-calendar .thy-calendar-year' ) ) . toBeFalsy ( ) ; } ) ) ; } ) ; describe ( 'specified date picker testing' , ( ) => { beforeEach ( ( ) => ( fixtureInstance . useSuite = 1 ) ) ; it ( 'should use format rule yyyy-MM-dd when with_time is 0' , fakeAsync ( ( ) => { const initial = { date : 1587629556 , with_time : 0 } as DateEntry ; fixtureInstance . thyValue = initial ; fixture . detectChanges ( ) ; openPickerByClickTrigger ( ) ; dispatchMouseEvent ( getSelectedDayCell ( ) , 'click' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; expect ( getPickerTrigger ( ) . value ) . toBe ( format ( new Date ( 1587629556000 ) , 'yyyy-MM-dd' ) ) ; } ) ) ; it ( 'should use format rule yyyy-MM-dd HH:mm when with_time is 1' , fakeAsync ( ( ) => { const initial = { date : 1587629556 , with_time : 1 } as DateEntry ; fixtureInstance . thyValue = initial ; fixtureInstance . thyShowTime = true ; fixture . detectChanges ( ) ; openPickerByClickTrigger ( ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; expect ( getPickerTrigger ( ) . value ) . toBe ( format ( new Date ( 1587629556000 ) , 'yyyy-MM-dd HH:mm' ) ) ; } ) ) ; it ( 'should use format rule yyyy年MM月dd日 HH:mm when initial value is empty' , fakeAsync ( ( ) => { const formatValue = 'yyyy年MM月dd日 HH:mm' ; const changeValue = 1587629556 ; fixtureInstance . thyValue = null ; fixtureInstance . thyFormat = formatValue ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixtureInstance . thyValue = changeValue ; fixture . detectChanges ( ) ; openPickerByClickTrigger ( ) ; fixtureInstance . thyValue = changeValue ; fixture . detectChanges ( ) ; tick ( 500 ) ; expect ( getPickerTrigger ( ) . value ) . toBe ( format ( new Date ( changeValue * 1000 ) , formatValue ) ) ; } ) ) ; it ( 'should emit value type is same with incoming value type' , fakeAsync ( ( ) => { const initial = 1587629556 ; fixtureInstance . thyValue = initial ; fixture . detectChanges ( ) ; openPickerByClickTrigger ( ) ; const thyOnChange = spyOn ( fixtureInstance , 'thyOnChange' ) ; dispatchMouseEvent ( getSelectedDayCell ( ) , 'click' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; expect ( thyOnChange ) . toHaveBeenCalledWith ( initial ) ; } ) ) ; it ( 'should support thyDateRender' , fakeAsync ( ( ) => { fixtureInstance . thyDateRender = fixtureInstance . tplDateRender ; fixture . detectChanges ( ) ; dispatchMouseEvent ( getPickerTriggerWrapper ( ) , 'click' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; expect ( queryFromOverlay ( '.test-first-day' ) . textContent . trim ( ) ) . toBe ( '1' ) ; } ) ) ; it ( 'should support thyDateRender with typeof function' , fakeAsync ( ( ) => { const featureKey = 'TEST_FIRST_DAY' ; fixtureInstance . thyDateRender = ( d ) => ( d . getDate ( ) === 1 ? featureKey : d . getDate ( ) ) ; fixture . detectChanges ( ) ; dispatchMouseEvent ( getPickerTriggerWrapper ( ) , 'click' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; expect ( overlayContainerElement . textContent . indexOf ( featureKey ) > - 1 ) . toBeTruthy ( ) ; } ) ) ; it ( 'should support thyShowTime' , fakeAsync ( ( ) => { fixtureInstance . thyValue = new Date ( '2018-11-11 11:22:33' ) ; fixtureInstance . thyShowTime = true ; fixture . detectChanges ( ) ; openPickerByClickTrigger ( ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; expect ( queryFromOverlay ( '.time-picker-section' ) ) . toBeDefined ( ) ; dispatchMouseEvent ( getSetTimeButton ( ) , 'click' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; expect ( getTimePickerWrap ( ) ) . toBeDefined ( ) ; expect ( ( queryFromOverlay ( '.time-picker-wrap input.thy-time-picker-field' ) as HTMLInputElement ) . value ) . toBe ( '11' ) ; } ) ) ; it ( 'should support thyPlacement' , fakeAsync ( ( ) => { let placement = 'top' ; fixtureInstance . thyPlacement = placement ; fixture . detectChanges ( ) ; openPickerByClickTrigger ( ) ; const pickComponentInstance = fixture . debugElement . query ( By . directive ( ThyPickerComponent ) ) . componentInstance ; expect ( pickComponentInstance . overlayPositions [ 0 ] . originY ) . toEqual ( placement ) ; } ) ) ; it ( 'should support thyMode' , fakeAsync ( ( ) => { fixtureInstance . thyValue = new Date ( '2020-12-01' ) ; fixture . detectChanges ( ) ; flush ( ) ; fixture . detectChanges ( ) ; expect ( getPickerTrigger ( ) . placeholder ) . toEqual ( '请选择日期' ) ; fixtureInstance . thyMode = 'month' ; fixture . detectChanges ( ) ; flush ( ) ; fixture . detectChanges ( ) ; openPickerByClickTrigger ( ) ; expect ( overlayContainerElement . querySelector ( '.thy-calendar .thy-calendar-month' ) ) . toBeDefined ( ) ; } ) ) ; it ( 'should support thyOnPanelChange' , fakeAsync ( ( ) => { spyOn ( fixtureInstance , 'thyOnPanelChange' ) ; fixture . detectChanges ( ) ; openPickerByClickTrigger ( ) ; dispatchMouseEvent ( overlayContainerElement . querySelector ( '.thy-calendar-header .thy-calendar-month-btn' ) , 'click' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; expect ( fixtureInstance . thyOnPanelChange ) . toHaveBeenCalledWith ( 'month' ) ; } ) ) ; it ( 'should support thyOnOk' , fakeAsync ( ( ) => { spyOn ( fixtureInstance , 'thyOnOk' ) ; fixtureInstance . thyValue = new Date ( '2018-11-11 11:22:33' ) ; fixtureInstance . thyShowTime = true ; fixture . detectChanges ( ) ; flush ( ) ; fixture . detectChanges ( ) ; openPickerByClickTrigger ( ) ; dispatchMouseEvent ( getSetTimeButton ( ) , 'click' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; dispatchMouseEvent ( overlayContainerElement . querySelector ( '.time-picker-btn-wrap > .time-picker-ok-btn' ) , 'click' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; expect ( fixtureInstance . thyOnOk ) . toHaveBeenCalledWith ( fixtureInstance . thyValue ) ; } ) ) ; } ) ; describe ( 'ngModel value accesors' , ( ) => { beforeEach ( ( ) => ( fixtureInstance . useSuite = 3 ) ) ; it ( 'should specified date provide by "modelValue" be choose' , fakeAsync ( ( ) => { fixtureInstance . modelValue = new Date ( '2018-11-11' ) ; fixture . detectChanges ( ) ; flush ( ) ; fixture . detectChanges ( ) ; expect ( getSelectedDayCell ( ) . textContent . trim ( ) ) . toBe ( '11' ) ; const cell = getFirstCell ( ) ; const cellText = cell . textContent . trim ( ) ; dispatchMouseEvent ( cell , 'click' ) ; fixture . detectChanges ( ) ; const result = ( fixtureInstance . modelValue as unknown ) as number ; expect ( fromUnixTime ( result ) . getDate ( ) ) . toBe ( + cellText ) ; } ) ) ; } ) ; describe ( 'date picker offset testing' , ( ) => { beforeEach ( ( ) => ( fixtureInstance . useSuite = 1 ) ) ; it ( 'should open date picker offset' , fakeAsync ( ( ) => { fixtureInstance . thyValue = new Date ( '2020-12-07' ) ; fixture . detectChanges ( ) ; flush ( ) ; fixture . detectChanges ( ) ; openPickerByClickTrigger ( ) ; fixture . detectChanges ( ) ; const result = getCdkOverlayPane ( ) ; fixture . detectChanges ( ) ; expect ( result . style . transform ) . toBe ( 'translateY(4px)' ) ; } ) ) ; } ) ; function getPickerTrigger ( ) { return debugElement . query ( By . css ( 'thy-picker input.thy-calendar-picker-input' ) ) . nativeElement as HTMLInputElement ; } function getPickerTriggerWrapper ( ) { return debugElement . query ( By . css ( 'thy-picker .thy-calendar-picker' ) ) . nativeElement as HTMLInputElement ; } function getPickerContainer ( ) { return queryFromOverlay ( '.thy-calendar-picker-container' ) as HTMLElement ; } function getSelectedDayCell ( ) { return queryFromOverlay ( 'tbody.thy-calendar-tbody td.thy-calendar-selected-day' ) as HTMLElement ; } function getFirstCell ( ) { return queryFromOverlay ( 'tbody.thy-calendar-tbody td.thy-calendar-cell' ) as HTMLElement ; } function getTimePickerWrap ( ) { return queryFromOverlay ( 'calendar-footer time-picker-wrap' ) as HTMLElement ; } function getSetTimeButton ( ) { return queryFromOverlay ( 'calendar-footer .time-picker-set-btn' ) as HTMLElement ; } function getConfirmButton ( ) { return queryFromOverlay ( 'calendar-footer .time-picker-ok-btn' ) as HTMLElement ; } function getClearButton ( ) { return queryFromOverlay ( 'calendar-footer .time-picker-clear-btn' ) as HTMLElement ; } function getCdkOverlayPane ( ) { return queryFromOverlay ( '.cdk-overlay-pane' ) as HTMLElement ; } function queryFromOverlay ( selector ) { return overlayContainerElement . querySelector ( selector ) as HTMLElement ; } function openPickerByClickTrigger ( ) { dispatchMouseEvent ( getPickerTriggerWrapper ( ) , 'click' ) ; fixture . detectChanges ( ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; } } ) ; @ Component ( { template : `
        <ng-container [ngSwitch]="useSuite">
            <!-- Suite 1 -->
            <thy-date-picker
                *ngSwitchCase="1"
                [thyAllowClear]="thyAllowClear"
                [thyAutoFocus]="thyAutoFocus"
                [thyDisabled]="thyDisabled"
                [thyDisabledDate]="thyDisabledDate"
                [thyPlaceHolder]="thyPlaceHolder"
                [thyPanelClassName]="thyPanelClassName"
                [thyDefaultPickerValue]="thyDefaultPickerValue"
                [thySize]="thySize"
                [thyFormat]="thyFormat"
                [thySuffixIcon]="thySuffixIcon"
                [thyReadonly]="thyReadonly"
                (thyOpenChange)="thyOpenChange($event)"
                [ngModel]="thyValue"
                (ngModelChange)="thyOnChange($event)"
                [thyDateRender]="thyDateRender"
                [thyMode]="thyMode"
                [thyPlacement]="thyPlacement"
                (thyOnPanelChange)="thyOnPanelChange($event)"
                (thyOnCalendarChange)="thyOnCalendarChange($event)"
                [thyShowTime]="thyShowTime"
                (thyOnOk)="thyOnOk($event)"
            ></thy-date-picker>
            <ng-template #tplDateRender let-current>
                <div [class.test-first-day]="current.getDate() === 1">{{ current.getDate() }}</div>
            </ng-template>

            <!-- Suite 2 -->
            <!-- use another picker to avoid thyOpen's side-effects because thyOpen act as "true" if used -->
            <thy-date-picker *ngSwitchCase="2" [thyOpen]="thyOpen" (thyOpenChange)="thyOpenChange($event)"></thy-date-picker>

            <!-- Suite 3 -->
            <thy-date-picker *ngSwitchCase="3" thyOpen [(ngModel)]="modelValue"></thy-date-picker>
        </ng-container>
    ` } ) class ThyTestDatePickerComponent { useSuite : 1 | 2 | 3 ; @ ViewChild ( 'tplDateRender' , { static : true } ) tplDateRender : TemplateRef < Date > ; thyAllowClear : boolean ; thyAutoFocus : boolean ; thyDisabled : boolean ; thyDisabledDate : ( d : Date ) => boolean ; thyPlaceHolder : string ; thyPanelClassName : string ; thySize : string ; thySuffixIcon : string ; thyFormat : string ; thyReadonly : boolean ; thyValue : Date | null | DateEntry | number ; thyDefaultPickerValue : Date | number ; thyDateRender : any ; thyShowTime : boolean | object = false ; thyMode : string ; thyPlacement : string = 'bottomLeft' ; thyOnChange ( ) { } thyOnCalendarChange ( ) { } thyOpenChange ( ) { } thyOnPanelChange ( ) { } thyOnOk ( ) { } thyOpen : boolean ; modelValue : Date ; }