@@ -11,7 +11,7 @@ import {
11
11
import { NgbDate } from './ngb-date' ;
12
12
import { NgbCalendar , NgbCalendarGregorian } from './ngb-calendar' ;
13
13
import { TestBed } from '@angular/core/testing' ;
14
- import { DatepickerViewModel , NgbMarkDisabled } from './datepicker-view-model' ;
14
+ import { DatepickerViewModel , NgbMarkDisabled , MonthViewModel } from './datepicker-view-model' ;
15
15
import { NgbDatepickerI18n , NgbDatepickerI18nDefault } from './datepicker-i18n' ;
16
16
import { DatePipe } from '@angular/common' ;
17
17
@@ -248,92 +248,199 @@ describe(`datepicker-tools`, () => {
248
248
expect ( months . length ) . toBe ( 2 ) ;
249
249
} ) ;
250
250
251
- it ( `should not rebuild existing months by default` , ( ) => {
252
- const may = new NgbDate ( 2017 , 5 , 5 ) ;
253
- const june = new NgbDate ( 2017 , 6 , 5 ) ;
251
+ const storeMonthsDataStructure = ( months : MonthViewModel [ ] ) => {
252
+ return months . map ( month => {
253
+ const storage = { weeks : month . weeks , weekdays : month . weekdays } ;
254
+ const weeks = month . weeks ;
255
+ for ( let weekIndex = 0 , weeksLength = weeks . length ; weekIndex < weeksLength ; weekIndex ++ ) {
256
+ const currentWeek = weeks [ weekIndex ] ;
257
+ storage [ `weeks[${ weekIndex } ]` ] = currentWeek ;
258
+ const days = currentWeek . days ;
259
+ storage [ `weeks[${ weekIndex } ].days` ] = days ;
260
+ for ( let dayIndex = 0 , daysLength = days . length ; dayIndex < daysLength ; dayIndex ++ ) {
261
+ const currentDay = days [ dayIndex ] ;
262
+ storage [ `weeks[${ weekIndex } ].days[${ dayIndex } ]` ] = currentDay ;
263
+ }
264
+ }
265
+ return storage ;
266
+ } ) ;
267
+ } ;
268
+
269
+ const customMatchers : jasmine . CustomMatcherFactories = {
270
+ toHaveTheSameMonthDataStructureAs : function ( util , customEqualityTesters ) {
271
+ return {
272
+ compare ( actualMonthsStorage , expectedMonthsStorage ) {
273
+ try {
274
+ const monthsNumber = actualMonthsStorage . length ;
275
+ if ( expectedMonthsStorage . length !== monthsNumber ) {
276
+ throw 'the number of months' ;
277
+ } ;
278
+ for ( let i = 0 ; i < monthsNumber ; i ++ ) {
279
+ const storage1 = actualMonthsStorage [ i ] ;
280
+ const storage2 = expectedMonthsStorage [ i ] ;
281
+ const keys1 = Object . keys ( storage1 ) ;
282
+ const keys2 = Object . keys ( storage2 ) ;
283
+ if ( ! util . equals ( keys2 , keys1 , customEqualityTesters ) ) {
284
+ throw `the set of keys in months[${ i } ]: ${ keys1 } != ${ keys2 } ` ;
285
+ }
286
+ for ( const key of keys1 ) {
287
+ if ( storage1 [ key ] !== storage2 [ key ] ) {
288
+ throw `months[${ i } ].${ key } ` ;
289
+ }
290
+ }
291
+ }
292
+ return {
293
+ pass : true , message : 'Expected different months data structures, but the same data structure was found.'
294
+ }
295
+ } catch ( e ) {
296
+ return {
297
+ pass : false ,
298
+ message : typeof e === 'string' ?
299
+ `Expected the same months data structure, but a difference was found in ${ e } ` :
300
+ `${ e } `
301
+ } ;
302
+ }
303
+ }
304
+ } ;
305
+ }
306
+ } ;
307
+
308
+ beforeEach ( function ( ) { jasmine . addMatchers ( customMatchers ) ; } ) ;
254
309
255
- // one same month
310
+ it ( `should reuse the same data structure (force = false)` , ( ) => {
256
311
let state = { displayMonths : 1 , firstDayOfWeek : 1 , months : [ ] } as DatepickerViewModel ;
257
- state . months = buildMonths ( calendar , may , state , i18n , false ) ;
258
- let newMonths = buildMonths ( calendar , may , state , i18n , false ) ;
259
-
260
- expect ( state . months . length ) . toBe ( 1 ) ;
261
- expect ( newMonths . length ) . toBe ( 1 ) ;
262
- expect ( state . months [ 0 ] ) . toBe ( newMonths [ 0 ] ) ;
263
-
264
- // one new month
265
- state = { displayMonths : 1 , firstDayOfWeek : 1 , months : [ ] } as DatepickerViewModel ;
266
- state . months = buildMonths ( calendar , may , state , i18n , false ) ;
267
- newMonths = buildMonths ( calendar , june , state , i18n , false ) ;
268
-
269
- expect ( state . months . length ) . toBe ( 1 ) ;
270
- expect ( newMonths . length ) . toBe ( 1 ) ;
271
- expect ( state . months [ 0 ] ) . not . toBe ( newMonths [ 0 ] ) ;
272
-
273
- // two same months
274
- state = { displayMonths : 2 , firstDayOfWeek : 1 , months : [ ] } as DatepickerViewModel ;
275
- state . months = buildMonths ( calendar , may , state , i18n , false ) ;
276
- newMonths = buildMonths ( calendar , may , state , i18n , false ) ;
277
-
278
- expect ( state . months . length ) . toBe ( 2 ) ;
279
- expect ( newMonths . length ) . toBe ( 2 ) ;
280
- expect ( state . months [ 0 ] ) . toBe ( newMonths [ 0 ] ) ;
281
- expect ( state . months [ 1 ] ) . toBe ( newMonths [ 1 ] ) ;
282
-
283
- // two months, one overlaps
284
- state = { displayMonths : 2 , firstDayOfWeek : 1 , months : [ ] } as DatepickerViewModel ;
285
- state . months = buildMonths ( calendar , may , state , i18n , false ) ;
286
- newMonths = buildMonths ( calendar , june , state , i18n , false ) ;
287
-
288
- expect ( state . months . length ) . toBe ( 2 ) ;
289
- expect ( newMonths . length ) . toBe ( 2 ) ;
290
- expect ( state . months [ 0 ] ) . not . toBe ( newMonths [ 0 ] ) ;
291
- expect ( state . months [ 1 ] ) . not . toBe ( newMonths [ 1 ] ) ;
292
- expect ( state . months [ 1 ] ) . toBe ( newMonths [ 0 ] ) ; // june reused
293
- } ) ;
312
+ let months = buildMonths ( calendar , new NgbDate ( 2017 , 5 , 5 ) , state , i18n , false ) ;
313
+ expect ( months ) . toBe ( state . months ) ;
314
+ expect ( months . length ) . toBe ( 1 ) ;
315
+ let monthsStructure = storeMonthsDataStructure ( months ) ;
316
+
317
+ months = buildMonths ( calendar , new NgbDate ( 2018 , 5 , 5 ) , state , i18n , false ) ;
318
+ expect ( months ) . toBe ( state . months ) ;
319
+ expect ( months . length ) . toBe ( 1 ) ;
320
+ expect ( storeMonthsDataStructure ( months ) ) [ 'toHaveTheSameMonthDataStructureAs' ] ( monthsStructure ) ;
321
+
322
+ state . displayMonths = 2 ;
323
+ months = buildMonths ( calendar , new NgbDate ( 2018 , 5 , 5 ) , state , i18n , false ) ;
324
+ expect ( months ) . toBe ( state . months ) ;
325
+ expect ( months . length ) . toBe ( 2 ) ;
326
+ monthsStructure . push ( ...storeMonthsDataStructure ( [ months [ 1 ] ] ) ) ;
327
+ expect ( storeMonthsDataStructure ( months ) ) [ 'toHaveTheSameMonthDataStructureAs' ] ( monthsStructure ) ;
328
+
329
+ // next month
330
+ months = buildMonths ( calendar , new NgbDate ( 2018 , 6 , 5 ) , state , i18n , false ) ;
331
+ expect ( months ) . toBe ( state . months ) ;
332
+ expect ( months . length ) . toBe ( 2 ) ;
333
+ // the structures should be swapped:
334
+ monthsStructure . push ( monthsStructure . shift ( ) ) ;
335
+ expect ( storeMonthsDataStructure ( months ) ) [ 'toHaveTheSameMonthDataStructureAs' ] ( monthsStructure ) ;
294
336
295
- it ( `should rebuild existing months with 'rebuild=false'` , ( ) => {
296
- const may = new NgbDate ( 2017 , 5 , 5 ) ;
297
- const june = new NgbDate ( 2017 , 6 , 5 ) ;
337
+ // previous month
338
+ months = buildMonths ( calendar , new NgbDate ( 2018 , 5 , 5 ) , state , i18n , false ) ;
339
+ expect ( months ) . toBe ( state . months ) ;
340
+ expect ( months . length ) . toBe ( 2 ) ;
341
+ // the structures should be swapped (again):
342
+ monthsStructure . push ( monthsStructure . shift ( ) ) ;
343
+ expect ( storeMonthsDataStructure ( months ) ) [ 'toHaveTheSameMonthDataStructureAs' ] ( monthsStructure ) ;
344
+
345
+ state . displayMonths = 5 ;
346
+ months = buildMonths ( calendar , new NgbDate ( 2018 , 5 , 5 ) , state , i18n , false ) ;
347
+ expect ( months ) . toBe ( state . months ) ;
348
+ expect ( months . length ) . toBe ( 5 ) ;
349
+ monthsStructure . push ( ...storeMonthsDataStructure ( months . slice ( 2 ) ) ) ;
350
+ expect ( storeMonthsDataStructure ( months ) ) [ 'toHaveTheSameMonthDataStructureAs' ] ( monthsStructure ) ;
351
+
352
+ // go to two months after, the 3 last months are reused as is
353
+ months = buildMonths ( calendar , new NgbDate ( 2018 , 7 , 5 ) , state , i18n , false ) ;
354
+ expect ( months ) . toBe ( state . months ) ;
355
+ expect ( months . length ) . toBe ( 5 ) ;
356
+ monthsStructure . unshift ( ...monthsStructure . splice ( 2 , 3 ) ) ;
357
+ expect ( storeMonthsDataStructure ( months ) ) [ 'toHaveTheSameMonthDataStructureAs' ] ( monthsStructure ) ;
358
+
359
+ // go to two months before, the 3 first months are reused as is
360
+ months = buildMonths ( calendar , new NgbDate ( 2018 , 5 , 5 ) , state , i18n , false ) ;
361
+ expect ( months ) . toBe ( state . months ) ;
362
+ expect ( months . length ) . toBe ( 5 ) ;
363
+ monthsStructure . push ( ...monthsStructure . splice ( 0 , 3 ) ) ;
364
+ expect ( storeMonthsDataStructure ( months ) ) [ 'toHaveTheSameMonthDataStructureAs' ] ( monthsStructure ) ;
365
+
366
+ // completely change the dates, nothing is shifted in monthsStructure
367
+ months = buildMonths ( calendar , new NgbDate ( 2018 , 10 , 5 ) , state , i18n , false ) ;
368
+ expect ( months ) . toBe ( state . months ) ;
369
+ expect ( months . length ) . toBe ( 5 ) ;
370
+ expect ( storeMonthsDataStructure ( months ) ) [ 'toHaveTheSameMonthDataStructureAs' ] ( monthsStructure ) ;
371
+
372
+ // keep 2 months
373
+ state . displayMonths = 2 ;
374
+ months = buildMonths ( calendar , new NgbDate ( 2018 , 11 , 5 ) , state , i18n , false ) ;
375
+ expect ( months ) . toBe ( state . months ) ;
376
+ expect ( months . length ) . toBe ( 2 ) ;
377
+ monthsStructure = monthsStructure . slice ( 1 , 3 ) ;
378
+ expect ( storeMonthsDataStructure ( months ) ) [ 'toHaveTheSameMonthDataStructureAs' ] ( monthsStructure ) ;
379
+ } ) ;
298
380
299
- // one same month
381
+ it ( `should reuse the same data structure (force = true)` , ( ) => {
300
382
let state = { displayMonths : 1 , firstDayOfWeek : 1 , months : [ ] } as DatepickerViewModel ;
301
- state . months = buildMonths ( calendar , may , state , i18n , true ) ;
302
- let newMonths = buildMonths ( calendar , may , state , i18n , true ) ;
303
-
304
- expect ( state . months . length ) . toBe ( 1 ) ;
305
- expect ( newMonths . length ) . toBe ( 1 ) ;
306
- expect ( state . months [ 0 ] ) . not . toBe ( newMonths [ 0 ] ) ;
307
-
308
- // one new month
309
- state = { displayMonths : 1 , firstDayOfWeek : 1 , months : [ ] } as DatepickerViewModel ;
310
- state . months = buildMonths ( calendar , may , state , i18n , true ) ;
311
- newMonths = buildMonths ( calendar , june , state , i18n , true ) ;
312
-
313
- expect ( state . months . length ) . toBe ( 1 ) ;
314
- expect ( newMonths . length ) . toBe ( 1 ) ;
315
- expect ( state . months [ 0 ] ) . not . toBe ( newMonths [ 0 ] ) ;
316
-
317
- // two same months
318
- state = { displayMonths : 2 , firstDayOfWeek : 1 , months : [ ] } as DatepickerViewModel ;
319
- state . months = buildMonths ( calendar , may , state , i18n , true ) ;
320
- newMonths = buildMonths ( calendar , may , state , i18n , true ) ;
321
-
322
- expect ( state . months . length ) . toBe ( 2 ) ;
323
- expect ( newMonths . length ) . toBe ( 2 ) ;
324
- expect ( state . months [ 0 ] ) . not . toBe ( newMonths [ 0 ] ) ;
325
- expect ( state . months [ 1 ] ) . not . toBe ( newMonths [ 1 ] ) ;
326
-
327
- // two months, one overlaps
328
- state = { displayMonths : 2 , firstDayOfWeek : 1 , months : [ ] } as DatepickerViewModel ;
329
- state . months = buildMonths ( calendar , may , state , i18n , true ) ;
330
- newMonths = buildMonths ( calendar , june , state , i18n , true ) ;
331
-
332
- expect ( state . months . length ) . toBe ( 2 ) ;
333
- expect ( newMonths . length ) . toBe ( 2 ) ;
334
- expect ( state . months [ 0 ] ) . not . toBe ( newMonths [ 0 ] ) ;
335
- expect ( state . months [ 1 ] ) . not . toBe ( newMonths [ 1 ] ) ;
336
- expect ( state . months [ 1 ] ) . not . toBe ( newMonths [ 0 ] ) ;
383
+ let months = buildMonths ( calendar , new NgbDate ( 2017 , 5 , 5 ) , state , i18n , true ) ;
384
+ expect ( months ) . toBe ( state . months ) ;
385
+ expect ( months . length ) . toBe ( 1 ) ;
386
+ let monthsStructure = storeMonthsDataStructure ( months ) ;
387
+
388
+ months = buildMonths ( calendar , new NgbDate ( 2018 , 5 , 5 ) , state , i18n , true ) ;
389
+ expect ( months ) . toBe ( state . months ) ;
390
+ expect ( months . length ) . toBe ( 1 ) ;
391
+ expect ( storeMonthsDataStructure ( months ) ) [ 'toHaveTheSameMonthDataStructureAs' ] ( monthsStructure ) ;
392
+
393
+ state . displayMonths = 2 ;
394
+ months = buildMonths ( calendar , new NgbDate ( 2018 , 5 , 5 ) , state , i18n , true ) ;
395
+ expect ( months ) . toBe ( state . months ) ;
396
+ expect ( months . length ) . toBe ( 2 ) ;
397
+ monthsStructure . push ( ...storeMonthsDataStructure ( [ months [ 1 ] ] ) ) ;
398
+ expect ( storeMonthsDataStructure ( months ) ) [ 'toHaveTheSameMonthDataStructureAs' ] ( monthsStructure ) ;
399
+
400
+ // next month
401
+ months = buildMonths ( calendar , new NgbDate ( 2018 , 6 , 5 ) , state , i18n , true ) ;
402
+ expect ( months ) . toBe ( state . months ) ;
403
+ expect ( months . length ) . toBe ( 2 ) ;
404
+ expect ( storeMonthsDataStructure ( months ) ) [ 'toHaveTheSameMonthDataStructureAs' ] ( monthsStructure ) ;
405
+
406
+ // previous month
407
+ months = buildMonths ( calendar , new NgbDate ( 2018 , 5 , 5 ) , state , i18n , true ) ;
408
+ expect ( months ) . toBe ( state . months ) ;
409
+ expect ( months . length ) . toBe ( 2 ) ;
410
+ expect ( storeMonthsDataStructure ( months ) ) [ 'toHaveTheSameMonthDataStructureAs' ] ( monthsStructure ) ;
411
+
412
+ state . displayMonths = 5 ;
413
+ months = buildMonths ( calendar , new NgbDate ( 2018 , 5 , 5 ) , state , i18n , true ) ;
414
+ expect ( months ) . toBe ( state . months ) ;
415
+ expect ( months . length ) . toBe ( 5 ) ;
416
+ monthsStructure . push ( ...storeMonthsDataStructure ( months . slice ( 2 ) ) ) ;
417
+ expect ( storeMonthsDataStructure ( months ) ) [ 'toHaveTheSameMonthDataStructureAs' ] ( monthsStructure ) ;
418
+
419
+ // go to two months after
420
+ months = buildMonths ( calendar , new NgbDate ( 2018 , 7 , 5 ) , state , i18n , true ) ;
421
+ expect ( months ) . toBe ( state . months ) ;
422
+ expect ( months . length ) . toBe ( 5 ) ;
423
+ expect ( storeMonthsDataStructure ( months ) ) [ 'toHaveTheSameMonthDataStructureAs' ] ( monthsStructure ) ;
424
+
425
+ // go to two months before
426
+ months = buildMonths ( calendar , new NgbDate ( 2018 , 5 , 5 ) , state , i18n , true ) ;
427
+ expect ( months ) . toBe ( state . months ) ;
428
+ expect ( months . length ) . toBe ( 5 ) ;
429
+ expect ( storeMonthsDataStructure ( months ) ) [ 'toHaveTheSameMonthDataStructureAs' ] ( monthsStructure ) ;
430
+
431
+ // completely change the dates
432
+ months = buildMonths ( calendar , new NgbDate ( 2018 , 10 , 5 ) , state , i18n , true ) ;
433
+ expect ( months ) . toBe ( state . months ) ;
434
+ expect ( months . length ) . toBe ( 5 ) ;
435
+ expect ( storeMonthsDataStructure ( months ) ) [ 'toHaveTheSameMonthDataStructureAs' ] ( monthsStructure ) ;
436
+
437
+ // keep 2 months
438
+ state . displayMonths = 2 ;
439
+ months = buildMonths ( calendar , new NgbDate ( 2018 , 11 , 5 ) , state , i18n , true ) ;
440
+ expect ( months ) . toBe ( state . months ) ;
441
+ expect ( months . length ) . toBe ( 2 ) ;
442
+ monthsStructure = monthsStructure . slice ( 0 , 2 ) ;
443
+ expect ( storeMonthsDataStructure ( months ) ) [ 'toHaveTheSameMonthDataStructureAs' ] ( monthsStructure ) ;
337
444
} ) ;
338
445
} ) ;
339
446
0 commit comments