import {TestBed, ComponentFixture, fakeAsync, tick} from '@angular/core/testing'; import {By} from '@angular/platform-browser'; import {createGenericTestComponent} from '../test/common'; import {Component} from '@angular/core'; import {FormsModule, NgForm} from '@angular/forms'; import {Ng2vDatepickerModule} from './datepicker.module'; import {Ng2vInputDatepicker} from './datepicker-input'; import {Ng2vDatepicker} from './datepicker'; import {Ng2vDateStruct} from './ng2v-date-struct'; import {Ng2vDate} from './ng2v-date'; const createTestCmpt = (html: string) => createGenericTestComponent(html, TestComponent) as ComponentFixture; describe('Ng2vInputDatepicker', () => { beforeEach(() => { TestBed.configureTestingModule( {declarations: [TestComponent], imports: [Ng2vDatepickerModule.forRoot(), FormsModule]}); }); describe('open, close and toggle', () => { it('should allow controlling datepicker popup from outside', () => { const fixture = createTestCmpt(` `); const buttons = fixture.nativeElement.querySelectorAll('button'); buttons[0].click(); // open fixture.detectChanges(); expect(fixture.nativeElement.querySelector('ng2v-datepicker')).not.toBeNull(); buttons[1].click(); // close fixture.detectChanges(); expect(fixture.nativeElement.querySelector('ng2v-datepicker')).toBeNull(); buttons[2].click(); // toggle fixture.detectChanges(); expect(fixture.nativeElement.querySelector('ng2v-datepicker')).not.toBeNull(); buttons[2].click(); // toggle fixture.detectChanges(); expect(fixture.nativeElement.querySelector('ng2v-datepicker')).toBeNull(); }); }); describe('ngModel interactions', () => { it('should format bound date as ISO (by default) in the input field', fakeAsync(() => { const fixture = createTestCmpt(``); const input = fixture.nativeElement.querySelector('input'); fixture.componentInstance.date = {year: 2016, month: 10, day: 10}; fixture.detectChanges(); tick(); expect(input.value).toBe('2016-10-10'); fixture.componentInstance.date = {year: 2016, month: 10, day: 15}; fixture.detectChanges(); tick(); expect(input.value).toBe('2016-10-15'); })); it('should parse user-entered date as ISO (by default)', () => { const fixture = createTestCmpt(``); const inputDebugEl = fixture.debugElement.query(By.css('input')); inputDebugEl.triggerEventHandler('change', {target: {value: '2016-09-10'}}); expect(fixture.componentInstance.date).toEqual({year: 2016, month: 9, day: 10}); }); it('should set only valid dates', fakeAsync(() => { const fixture = createTestCmpt(``); const input = fixture.nativeElement.querySelector('input'); fixture.componentInstance.date = {}; fixture.detectChanges(); tick(); expect(input.value).toBe(''); fixture.componentInstance.date = null; fixture.detectChanges(); tick(); expect(input.value).toBe(''); fixture.componentInstance.date = new Date(); fixture.detectChanges(); tick(); expect(input.value).toBe(''); fixture.componentInstance.date = undefined; fixture.detectChanges(); tick(); expect(input.value).toBe(''); fixture.componentInstance.date = new Ng2vDate(300000, 1, 1); fixture.detectChanges(); tick(); expect(input.value).toBe(''); fixture.componentInstance.date = new Ng2vDate(2017, 2, null); fixture.detectChanges(); tick(); expect(input.value).toBe(''); fixture.componentInstance.date = new Ng2vDate(2017, null, 5); fixture.detectChanges(); tick(); expect(input.value).toBe(''); fixture.componentInstance.date = new Ng2vDate(null, 2, 5); fixture.detectChanges(); tick(); expect(input.value).toBe(''); fixture.componentInstance.date = new Ng2vDate('2017', '03', '10'); fixture.detectChanges(); tick(); expect(input.value).toBe(''); })); it('should propagate disabled state', fakeAsync(() => { const fixture = createTestCmpt(` `); fixture.componentInstance.isDisabled = true; fixture.detectChanges(); const button = fixture.nativeElement.querySelector('button'); const input = fixture.nativeElement.querySelector('input'); button.click(); // open tick(); fixture.detectChanges(); const buttonInDatePicker = fixture.nativeElement.querySelector('ng2v-datepicker button'); expect(fixture.nativeElement.querySelector('ng2v-datepicker')).not.toBeNull(); expect(input.disabled).toBeTruthy(); expect(buttonInDatePicker.disabled).toBeTruthy(); fixture.componentInstance.isDisabled = false; fixture.detectChanges(); tick(); fixture.detectChanges(); expect(fixture.nativeElement.querySelector('ng2v-datepicker')).not.toBeNull(); expect(input.disabled).toBeFalsy(); expect(buttonInDatePicker.disabled).toBeFalsy(); })); it('should propagate touched state on (blur)', fakeAsync(() => { const fixture = createTestCmpt(``); const inputDebugEl = fixture.debugElement.query(By.css('input')); expect(inputDebugEl.classes['ng-touched']).toBeFalsy(); inputDebugEl.triggerEventHandler('blur', {}); tick(); fixture.detectChanges(); expect(inputDebugEl.classes['ng-touched']).toBeTruthy(); })); it('should propagate touched state when setting a date', fakeAsync(() => { const fixture = createTestCmpt(` `); const buttonDebugEl = fixture.debugElement.query(By.css('button')); const inputDebugEl = fixture.debugElement.query(By.css('input')); expect(inputDebugEl.classes['ng-touched']).toBeFalsy(); buttonDebugEl.triggerEventHandler('click', {}); // open inputDebugEl.triggerEventHandler('change', {target: {value: '2016-09-10'}}); tick(); fixture.detectChanges(); expect(inputDebugEl.classes['ng-touched']).toBeTruthy(); })); }); describe('validation', () => { describe('values set from model', () => { it('should not return errors for valid model', fakeAsync(() => { const fixture = createTestCmpt( `
`); const form = fixture.debugElement.query(By.directive(NgForm)).injector.get(NgForm); fixture.detectChanges(); tick(); expect(form.control.valid).toBeTruthy(); expect(form.control.hasError('ng2vDate', ['dp'])).toBeFalsy(); })); it('should not return errors for empty model', fakeAsync(() => { const fixture = createTestCmpt(`
`); const form = fixture.debugElement.query(By.directive(NgForm)).injector.get(NgForm); fixture.detectChanges(); tick(); expect(form.control.valid).toBeTruthy(); })); it('should return "invalid" errors for invalid model', fakeAsync(() => { const fixture = createTestCmpt(`
`); const form = fixture.debugElement.query(By.directive(NgForm)).injector.get(NgForm); fixture.detectChanges(); tick(); expect(form.control.invalid).toBeTruthy(); expect(form.control.getError('ng2vDate', ['dp']).invalid).toBe(5); })); it('should return "requiredBefore" errors for dates before minimal date', fakeAsync(() => { const fixture = createTestCmpt(`
`); const form = fixture.debugElement.query(By.directive(NgForm)).injector.get(NgForm); fixture.detectChanges(); tick(); expect(form.control.invalid).toBeTruthy(); expect(form.control.getError('ng2vDate', ['dp']).requiredBefore).toEqual({year: 2017, month: 6, day: 4}); })); it('should return "requiredAfter" errors for dates after maximal date', fakeAsync(() => { const fixture = createTestCmpt(`
`); const form = fixture.debugElement.query(By.directive(NgForm)).injector.get(NgForm); fixture.detectChanges(); tick(); expect(form.control.invalid).toBeTruthy(); expect(form.control.getError('ng2vDate', ['dp']).requiredAfter).toEqual({year: 2017, month: 2, day: 4}); })); it('should update validity status when model changes', fakeAsync(() => { const fixture = createTestCmpt(`
`); const form = fixture.debugElement.query(By.directive(NgForm)).injector.get(NgForm); fixture.componentRef.instance.date = 'invalid'; fixture.detectChanges(); tick(); expect(form.control.invalid).toBeTruthy(); fixture.componentRef.instance.date = {year: 2015, month: 7, day: 3}; fixture.detectChanges(); tick(); expect(form.control.valid).toBeTruthy(); })); it('should update validity status when minDate changes', fakeAsync(() => { const fixture = createTestCmpt(`
`); const form = fixture.debugElement.query(By.directive(NgForm)).injector.get(NgForm); fixture.detectChanges(); tick(); expect(form.control.valid).toBeTruthy(); fixture.componentRef.instance.date = {year: 2018, month: 7, day: 3}; fixture.detectChanges(); tick(); expect(form.control.invalid).toBeTruthy(); })); it('should update validity status when maxDate changes', fakeAsync(() => { const fixture = createTestCmpt(`
`); const form = fixture.debugElement.query(By.directive(NgForm)).injector.get(NgForm); fixture.detectChanges(); tick(); expect(form.control.valid).toBeTruthy(); fixture.componentRef.instance.date = {year: 2015, month: 7, day: 3}; fixture.detectChanges(); tick(); expect(form.control.invalid).toBeTruthy(); })); it('should update validity for manually entered dates', fakeAsync(() => { const fixture = createTestCmpt(`
`); const inputDebugEl = fixture.debugElement.query(By.css('input')); const form = fixture.debugElement.query(By.directive(NgForm)).injector.get(NgForm); inputDebugEl.triggerEventHandler('change', {target: {value: '2016-09-10'}}); fixture.detectChanges(); tick(); expect(form.control.valid).toBeTruthy(); inputDebugEl.triggerEventHandler('change', {target: {value: 'invalid'}}); fixture.detectChanges(); tick(); expect(form.control.invalid).toBeTruthy(); })); }); }); describe('options', () => { it('should propagate the "dayTemplate" option', () => { const fixture = createTestCmpt(``); const dpInput = fixture.debugElement.query(By.directive(Ng2vInputDatepicker)).injector.get(Ng2vInputDatepicker); dpInput.open(); fixture.detectChanges(); const dp = fixture.debugElement.query(By.css('ng2v-datepicker')).injector.get(Ng2vDatepicker); expect(dp.dayTemplate).toBeDefined(); }); it('should propagate the "displayMonths" option', () => { const fixture = createTestCmpt(``); const dpInput = fixture.debugElement.query(By.directive(Ng2vInputDatepicker)).injector.get(Ng2vInputDatepicker); dpInput.open(); fixture.detectChanges(); const dp = fixture.debugElement.query(By.css('ng2v-datepicker')).injector.get(Ng2vDatepicker); expect(dp.displayMonths).toBe(3); }); it('should propagate the "firstDayOfWeek" option', () => { const fixture = createTestCmpt(``); const dpInput = fixture.debugElement.query(By.directive(Ng2vInputDatepicker)).injector.get(Ng2vInputDatepicker); dpInput.open(); fixture.detectChanges(); const dp = fixture.debugElement.query(By.css('ng2v-datepicker')).injector.get(Ng2vDatepicker); expect(dp.firstDayOfWeek).toBe(5); }); it('should propagate the "markDisabled" option', () => { const fixture = createTestCmpt(``); const dpInput = fixture.debugElement.query(By.directive(Ng2vInputDatepicker)).injector.get(Ng2vInputDatepicker); dpInput.open(); fixture.detectChanges(); const dp = fixture.debugElement.query(By.css('ng2v-datepicker')).injector.get(Ng2vDatepicker); expect(dp.markDisabled).toBeDefined(); }); it('should propagate the "minDate" option', () => { const fixture = createTestCmpt(``); const dpInput = fixture.debugElement.query(By.directive(Ng2vInputDatepicker)).injector.get(Ng2vInputDatepicker); dpInput.open(); fixture.detectChanges(); const dp = fixture.debugElement.query(By.css('ng2v-datepicker')).injector.get(Ng2vDatepicker); expect(dp.minDate).toEqual({year: 2016, month: 9, day: 13}); }); it('should propagate the "maxDate" option', () => { const fixture = createTestCmpt(``); const dpInput = fixture.debugElement.query(By.directive(Ng2vInputDatepicker)).injector.get(Ng2vInputDatepicker); dpInput.open(); fixture.detectChanges(); const dp = fixture.debugElement.query(By.css('ng2v-datepicker')).injector.get(Ng2vDatepicker); expect(dp.maxDate).toEqual({year: 2016, month: 9, day: 13}); }); it('should propagate the "outsideDays" option', () => { const fixture = createTestCmpt(``); const dpInput = fixture.debugElement.query(By.directive(Ng2vInputDatepicker)).injector.get(Ng2vInputDatepicker); dpInput.open(); fixture.detectChanges(); const dp = fixture.debugElement.query(By.css('ng2v-datepicker')).injector.get(Ng2vDatepicker); expect(dp.outsideDays).toEqual('collapsed'); }); it('should propagate the "navigation" option', () => { const fixture = createTestCmpt(``); const dpInput = fixture.debugElement.query(By.directive(Ng2vInputDatepicker)).injector.get(Ng2vInputDatepicker); dpInput.open(); fixture.detectChanges(); const dp = fixture.debugElement.query(By.css('ng2v-datepicker')).injector.get(Ng2vDatepicker); expect(dp.navigation).toBe('none'); }); it('should propagate the "showWeekdays" option', () => { const fixture = createTestCmpt(``); const dpInput = fixture.debugElement.query(By.directive(Ng2vInputDatepicker)).injector.get(Ng2vInputDatepicker); dpInput.open(); fixture.detectChanges(); const dp = fixture.debugElement.query(By.css('ng2v-datepicker')).injector.get(Ng2vDatepicker); expect(dp.showWeekdays).toBeTruthy(); }); it('should propagate the "showWeekNumbers" option', () => { const fixture = createTestCmpt(``); const dpInput = fixture.debugElement.query(By.directive(Ng2vInputDatepicker)).injector.get(Ng2vInputDatepicker); dpInput.open(); fixture.detectChanges(); const dp = fixture.debugElement.query(By.css('ng2v-datepicker')).injector.get(Ng2vDatepicker); expect(dp.showWeekNumbers).toBeTruthy(); }); it('should propagate the "startDate" option', () => { const fixture = createTestCmpt(``); const dpInput = fixture.debugElement.query(By.directive(Ng2vInputDatepicker)).injector.get(Ng2vInputDatepicker); dpInput.open(); fixture.detectChanges(); const dp = fixture.debugElement.query(By.css('ng2v-datepicker')).injector.get(Ng2vDatepicker); expect(dp.startDate).toEqual({year: 2016, month: 9, day: 13}); }); it('should propagate model as "startDate" option when "startDate" not provided', fakeAsync(() => { const fixture = createTestCmpt(``); const dpInput = fixture.debugElement.query(By.directive(Ng2vInputDatepicker)).injector.get(Ng2vInputDatepicker); tick(); fixture.detectChanges(); dpInput.open(); fixture.detectChanges(); const dp = fixture.debugElement.query(By.css('ng2v-datepicker')).injector.get(Ng2vDatepicker); expect(dp.startDate).toEqual(Ng2vDate.from({year: 2016, month: 9, day: 13})); })); it('should relay the "navigate" event', () => { const fixture = createTestCmpt(``); const dpInput = fixture.debugElement.query(By.directive(Ng2vInputDatepicker)).injector.get(Ng2vInputDatepicker); spyOn(fixture.componentInstance, 'onNavigate'); dpInput.open(); fixture.detectChanges(); expect(fixture.componentInstance.onNavigate).toHaveBeenCalledWith({current: null, next: {year: 2016, month: 9}}); const dp = fixture.debugElement.query(By.css('ng2v-datepicker')).injector.get(Ng2vDatepicker); dp.navigateTo({year: 2018, month: 4}); expect(fixture.componentInstance.onNavigate) .toHaveBeenCalledWith({current: {year: 2016, month: 9}, next: {year: 2018, month: 4}}); }); }); }); @Component({selector: 'test-cmp', template: ''}) class TestComponent { date: Ng2vDateStruct; isDisabled; onNavigate() {} open(d: Ng2vInputDatepicker) { d.open(); } close(d: Ng2vInputDatepicker) { d.close(); } toggle(d: Ng2vInputDatepicker) { d.toggle(); } noop() {} }