diff --git a/src/framework/date-fns/services/date-fns-date.service.spec.ts b/src/framework/date-fns/services/date-fns-date.service.spec.ts index c1348f6bb1..b4a886d5e9 100644 --- a/src/framework/date-fns/services/date-fns-date.service.spec.ts +++ b/src/framework/date-fns/services/date-fns-date.service.spec.ts @@ -24,6 +24,11 @@ describe('date-fns-date-service', () => { expect(dateService.parse(date, 'MM.dd.yyyy')).toEqual(new Date(2018, 5, 15)); }); + it('should not format if date isn\'t passed', () => { + expect(() => dateService.format(undefined, 'DD.MM.YYYY')).not.toThrow(); + expect(dateService.format(undefined, 'DD.MM.YYYY')).toEqual(''); + }); + describe('service global config', () => { const SEPARATOR = '_'; const FORMAT = `MM${SEPARATOR}dd${SEPARATOR}yyyy`; diff --git a/src/framework/date-fns/services/date-fns-date.service.ts b/src/framework/date-fns/services/date-fns-date.service.ts index 02bb3a573b..3f0f479911 100644 --- a/src/framework/date-fns/services/date-fns-date.service.ts +++ b/src/framework/date-fns/services/date-fns-date.service.ts @@ -38,7 +38,11 @@ export class NbDateFnsDateService extends NbNativeDateService { } format(date: Date, format: string): string { - return formatDate(date, format || this.options.format, this.options.formatOptions); + if (date) { + return formatDate(date, format || this.options.format, this.options.formatOptions); + } + + return ''; } parse(date: string, format: string): Date { diff --git a/src/framework/moment/services/moment-date.service.spec.ts b/src/framework/moment/services/moment-date.service.spec.ts index 485dc21a8f..84d880e252 100644 --- a/src/framework/moment/services/moment-date.service.spec.ts +++ b/src/framework/moment/services/moment-date.service.spec.ts @@ -101,6 +101,11 @@ describe('moment-date-service', () => { expect(parsed.date()).toEqual(15); }); + it('should not format if date isn\'t passed', () => { + expect(() => dateService.format(undefined, 'DD.MM.YYYY')).not.toThrow(); + expect(dateService.format(undefined, 'DD.MM.YYYY')).toEqual(''); + }); + it('should get year end', () => { const date = moment().year(2018).month(5).date(15); const yearEnd = dateService.getYearEnd(date); diff --git a/src/framework/moment/services/moment-date.service.ts b/src/framework/moment/services/moment-date.service.ts index 9c783168e2..aa3d419d51 100644 --- a/src/framework/moment/services/moment-date.service.ts +++ b/src/framework/moment/services/moment-date.service.ts @@ -62,7 +62,11 @@ export class NbMomentDateService extends NbDateService { } format(date: Moment, format: string): string { - return date.format(format || this.localeData.defaultFormat); + if (date) { + return date.format(format || this.localeData.defaultFormat); + } + + return ''; } getDate(date: Moment): number { diff --git a/src/framework/theme/components/datepicker/datepicker-adapter.spec.ts b/src/framework/theme/components/datepicker/datepicker-adapter.spec.ts new file mode 100644 index 0000000000..714b039585 --- /dev/null +++ b/src/framework/theme/components/datepicker/datepicker-adapter.spec.ts @@ -0,0 +1,151 @@ +import { TestBed } from '@angular/core/testing'; +import { NbCalendarRange, NbDateService } from '@nebular/theme'; + +import { NbDateAdapterService, NbRangeAdapterService } from './datepicker-adapter'; + +describe('Date Adapters', () => { + beforeEach(() => { + const mockDateService = { + parse() {}, + format() {}, + isValidDateString() {}, + }; + + TestBed.configureTestingModule({ + providers: [ + { provide: NbDateService, useValue: mockDateService }, + NbDateAdapterService, + NbRangeAdapterService, + ], + }); + }); + + describe('NbDateAdapterService', () => { + let dateService: NbDateService; + let adapterService: NbDateAdapterService; + beforeEach(() => { + adapterService = TestBed.get(NbDateAdapterService); + dateService = TestBed.get(NbDateService); + }); + + it('should be created', () => { + expect(adapterService).toBeTruthy(); + }); + + it('should use date service to parse date', () => { + const date = '11/11/11'; + const format = 'mm/dd/yy'; + const parsed = new Date(); + const spy = spyOn(dateService, 'parse').and.returnValue(parsed); + + expect(adapterService.parse(date, format)).toEqual(parsed); + expect(spy).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledWith(date, format); + }); + + it('should use date service to format date', () => { + const date = new Date(); + const format = 'mm/dd/yyyy'; + const formatted = 'formatted'; + const spy = spyOn(dateService, 'format').and.returnValue(formatted); + + expect(adapterService.format(date, format)).toEqual(formatted); + expect(spy).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledWith(date, format); + }); + + it('should use date service to validate date string', () => { + const date = '11/11/11'; + const format = 'mm/dd/yy'; + const results = [true, false]; + const spy = spyOn(dateService, 'isValidDateString').and.returnValues(...results); + + for (let i = 0, callsCount = 0; i < results.length; i++) { + expect(adapterService.isValid(date, format)).toEqual(results[i]); + callsCount++; + expect(spy).toHaveBeenCalledTimes(callsCount); + expect(spy).toHaveBeenCalledWith(date, format); + } + }); + }); + + describe('NbRangeAdapterService', () => { + let dateService: NbDateService; + let adapterService: NbRangeAdapterService; + beforeEach(() => { + dateService = TestBed.get(NbDateService); + adapterService = TestBed.get(NbRangeAdapterService); + }); + + it('should be created', () => { + expect(adapterService).toBeTruthy(); + }); + + it('should use date service to parse date', () => { + const startDate = '11/11/11'; + const endDate = '12/11/11'; + const date = `${startDate}-${endDate}`; + const format = 'mm/dd/yy'; + const expectedStart = new Date(); + const expectedEnd = new Date(); + const spy = spyOn(dateService, 'parse').and.returnValues(expectedStart, expectedEnd); + + const { start: actualStart, end: actualEnd }: NbCalendarRange = adapterService.parse(date, format); + expect(actualStart).toEqual(expectedStart); + expect(actualEnd).toEqual(expectedEnd); + expect(spy).toHaveBeenCalledTimes(2); + expect(spy.calls.argsFor(0)).toEqual([ startDate, format ]); + expect(spy.calls.argsFor(1)).toEqual([ endDate, format ]); + }); + + it('should format valid date range', () => { + const range: NbCalendarRange = { start: new Date(), end: new Date() }; + const format = 'mm/dd/yyyy'; + const spy = spyOn(dateService, 'isValidDateString').and.returnValues(true, true); + + expect(adapterService.format(range, format)).toEqual('undefined - undefined'); + expect(spy).toHaveBeenCalledTimes(2); + }); + + it('should not format if range isn\'t passed', () => { + const spy = spyOn(dateService, 'isValidDateString').and.returnValues(false, false); + + expect(adapterService.format(null, '')).toEqual(''); + expect(spy).not.toHaveBeenCalled(); + }); + + it('should not format if start date is invalid', () => { + const range: NbCalendarRange = { start: new Date(), end: new Date() }; + const spy = spyOn(dateService, 'isValidDateString').and.returnValue(false); + + expect(adapterService.format(range, '')).toEqual(''); + expect(spy).toHaveBeenCalledTimes(1); + }); + + it('should return only start date if end is invalid', () => { + const range: NbCalendarRange = { start: new Date(), end: new Date() }; + const spy = spyOn(dateService, 'isValidDateString').and.returnValues(true, false); + + expect(adapterService.format(range, '')).toEqual(undefined); + expect(spy).toHaveBeenCalledTimes(2); + }); + + it('should use date service to validate date string', () => { + const startDate = '11/11/11'; + const endDate = '12/11/11'; + const date = `${startDate}-${endDate}`; + const format = 'mm/dd/yy'; + const results = [ true, false, true, true ]; + const spy = spyOn(dateService, 'isValidDateString').and.returnValues(...results); + + for (let i = 0, callsCount = 0; i < results.length - 1; i += 2) { + expect(adapterService.isValid(date, format)).toEqual(results[i] && results[i + 1]); + callsCount += 2; + + expect(spy).toHaveBeenCalledTimes(callsCount); + expect(spy.calls.argsFor(i)).toEqual([ startDate, format ]); + expect(spy.calls.argsFor(i + 1)).toEqual([ endDate, format ]); + } + }); + }); +}); diff --git a/src/framework/theme/components/datepicker/datepicker-adapter.ts b/src/framework/theme/components/datepicker/datepicker-adapter.ts index e368d3777c..2e99a97b85 100644 --- a/src/framework/theme/components/datepicker/datepicker-adapter.ts +++ b/src/framework/theme/components/datepicker/datepicker-adapter.ts @@ -55,9 +55,16 @@ export class NbRangeAdapterService extends NbDatepickerAdapter