summaryrefslogtreecommitdiff
path: root/tests/todo.vader
blob: 8a43129035a125afe79862ae2d0c2e985569b171 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
" File:        tests/todo.vader
" Description: Vader tests for todo.txt-vim plugin
" Author:      Peter (fretep) <githib.5678@9ox.net>
" Licence:     Vim licence
" Website:     http://github.com/dbeniamine/todo.txt.vim

" [Vader](https://github.com/junegunn/vader.vim) is a simple unit testing
" plugin for VIM.

Include: include/setup.vader

" file: syntax/todo.vim {{{1

" syntax match {{{2

Given todo (todo items active and done);
x   .    1    .    2    .    3    .    4    .    5    .    6    .    7    .    8  L01
x 345678901234567890123456789012345678901234567890123456789012345678901234567890  L02
x (A) Done  due:2000-01-01 due:2050-01-01 2017-09-10 +Project @Context key:value  L03
Active      due:2000-01-01 due:2050-01-01 2017-09-10 +Project @Context key:value  L04
x 345678901234567890123456789012345678901234567890123456789012345678901234567890  L05
x   .    1    .    2    .    3    .    4    .    5    .    6    .    7    .    8  L06
Execute (Syntax for done task):
  AssertEqual 'TodoDone',         SyntaxAt( 3,  1)
  AssertEqual 'TodoDone',         SyntaxAt( 3,  4)
  AssertEqual 'TodoDone',         SyntaxAt( 3,  7)
  AssertEqual 'TodoDone',         SyntaxAt( 3, 13)
  AssertEqual 'TodoDone',         SyntaxAt( 3, 28)
  AssertEqual 'TodoDone',         SyntaxAt( 3, 72)
  AssertEqual 'TodoDone',         SyntaxAt( 3, 17)
  AssertEqual 'TodoDone',         SyntaxAt( 3, 32)
  AssertEqual 'TodoDone',         SyntaxAt( 3, 43)
  AssertEqual 'TodoDone',         SyntaxAt( 3, 54)
  AssertEqual 'TodoDone',         SyntaxAt( 3, 63)
Execute (Syntax for active task):
  AssertEqual 'TodoTodo',         SyntaxAt( 4,  1)
  AssertEqual 'TodoOverDueDate',  SyntaxAt( 4, 13)
  AssertEqual 'TodoKey',          SyntaxAt( 4, 28)
  AssertEqual 'TodoKey',          SyntaxAt( 4, 72)
  AssertEqual 'TodoOverDueDate',  SyntaxAt( 4, 17)
  AssertEqual 'TodoDate',         SyntaxAt( 4, 32)
  AssertEqual 'TodoDate',         SyntaxAt( 4, 43)
  AssertEqual 'TodoProject',      SyntaxAt( 4, 54)
  AssertEqual 'TodoContext',      SyntaxAt( 4, 63)
Given todo (todo items with priority);
x   .    1    .    2    .    3    .    4    .    5    .    6    .    7    .    8  L01
x 345678901234567890123456789012345678901234567890123456789012345678901234567890  L02
(A) Priorit due:2000-01-01 due:2050-01-01 2017-09-10 +Project @Context key:value  L03
(B) Priorit due:2000-01-01 due:2050-01-01 2017-09-10 +Project @Context key:value  L04
(C) Priorit due:2000-01-01 due:2050-01-01 2017-09-10 +Project @Context key:value  L05
(D) Priorit due:2000-01-01 due:2050-01-01 2017-09-10 +Project @Context key:value  L06
(E) Priorit due:2000-01-01 due:2050-01-01 2017-09-10 +Project @Context key:value  L07
(F) Priorit due:2000-01-01 due:2050-01-01 2017-09-10 +Project @Context key:value  L08
(G) Priorit due:2000-01-01 due:2050-01-01 2017-09-10 +Project @Context key:value  L09
(H) Priorit due:2000-01-01 due:2050-01-01 2017-09-10 +Project @Context key:value  L10
(I) Priorit due:2000-01-01 due:2050-01-01 2017-09-10 +Project @Context key:value  L11
(J) Priorit due:2000-01-01 due:2050-01-01 2017-09-10 +Project @Context key:value  L12
(K) Priorit due:2000-01-01 due:2050-01-01 2017-09-10 +Project @Context key:value  L13
(L) Priorit due:2000-01-01 due:2050-01-01 2017-09-10 +Project @Context key:value  L14
(M) Priorit due:2000-01-01 due:2050-01-01 2017-09-10 +Project @Context key:value  L15
(N) Priorit due:2000-01-01 due:2050-01-01 2017-09-10 +Project @Context key:value  L16
(O) Priorit due:2000-01-01 due:2050-01-01 2017-09-10 +Project @Context key:value  L17
(P) Priorit due:2000-01-01 due:2050-01-01 2017-09-10 +Project @Context key:value  L18
(Q) Priorit due:2000-01-01 due:2050-01-01 2017-09-10 +Project @Context key:value  L19
(R) Priorit due:2000-01-01 due:2050-01-01 2017-09-10 +Project @Context key:value  L20
(S) Priorit due:2000-01-01 due:2050-01-01 2017-09-10 +Project @Context key:value  L21
(T) Priorit due:2000-01-01 due:2050-01-01 2017-09-10 +Project @Context key:value  L22
(U) Priorit due:2000-01-01 due:2050-01-01 2017-09-10 +Project @Context key:value  L23
(V) Priorit due:2000-01-01 due:2050-01-01 2017-09-10 +Project @Context key:value  L24
(W) Priorit due:2000-01-01 due:2050-01-01 2017-09-10 +Project @Context key:value  L25
(X) Priorit due:2000-01-01 due:2050-01-01 2017-09-10 +Project @Context key:value  L26
(Y) Priorit due:2000-01-01 due:2050-01-01 2017-09-10 +Project @Context key:value  L27
(Z) Priorit due:2000-01-01 due:2050-01-01 2017-09-10 +Project @Context key:value  L28
x 345678901234567890123456789012345678901234567890123456789012345678901234567890  L29
x   .    1    .    2    .    3    .    4    .    5    .    6    .    7    .    8  L30
Execute (Syntax for priority task):
  AssertEqual 'TodoPriorityA',    SyntaxAt( 3,  2)
  AssertEqual 'TodoPriorityA',    SyntaxAt( 3,  5)
  AssertEqual 'TodoPriorityB',    SyntaxAt( 4,  2)
  AssertEqual 'TodoPriorityB',    SyntaxAt( 4,  5)
  AssertEqual 'TodoPriorityC',    SyntaxAt( 5,  2)
  AssertEqual 'TodoPriorityC',    SyntaxAt( 5,  5)
  AssertEqual 'TodoPriorityD',    SyntaxAt( 6,  2)
  AssertEqual 'TodoPriorityD',    SyntaxAt( 6,  5)
  AssertEqual 'TodoPriorityE',    SyntaxAt( 7,  2)
  AssertEqual 'TodoPriorityE',    SyntaxAt( 7,  5)
  AssertEqual 'TodoPriorityF',    SyntaxAt( 8,  2)
  AssertEqual 'TodoPriorityF',    SyntaxAt( 8,  5)
  AssertEqual 'TodoPriorityG',    SyntaxAt( 9,  2)
  AssertEqual 'TodoPriorityG',    SyntaxAt( 9,  5)
  AssertEqual 'TodoPriorityH',    SyntaxAt(10,  2)
  AssertEqual 'TodoPriorityH',    SyntaxAt(10,  5)
  AssertEqual 'TodoPriorityI',    SyntaxAt(11,  2)
  AssertEqual 'TodoPriorityI',    SyntaxAt(11,  5)
  AssertEqual 'TodoPriorityJ',    SyntaxAt(12,  2)
  AssertEqual 'TodoPriorityJ',    SyntaxAt(12,  5)
  AssertEqual 'TodoPriorityK',    SyntaxAt(13,  2)
  AssertEqual 'TodoPriorityK',    SyntaxAt(13,  5)
  AssertEqual 'TodoPriorityL',    SyntaxAt(14,  2)
  AssertEqual 'TodoPriorityL',    SyntaxAt(14,  5)
  AssertEqual 'TodoPriorityM',    SyntaxAt(15,  2)
  AssertEqual 'TodoPriorityM',    SyntaxAt(15,  5)
  AssertEqual 'TodoPriorityN',    SyntaxAt(16,  2)
  AssertEqual 'TodoPriorityN',    SyntaxAt(16,  5)
  AssertEqual 'TodoPriorityO',    SyntaxAt(17,  2)
  AssertEqual 'TodoPriorityO',    SyntaxAt(17,  5)
  AssertEqual 'TodoPriorityP',    SyntaxAt(18,  2)
  AssertEqual 'TodoPriorityP',    SyntaxAt(18,  5)
  AssertEqual 'TodoPriorityQ',    SyntaxAt(19,  2)
  AssertEqual 'TodoPriorityQ',    SyntaxAt(19,  5)
  AssertEqual 'TodoPriorityR',    SyntaxAt(20,  2)
  AssertEqual 'TodoPriorityR',    SyntaxAt(20,  5)
  AssertEqual 'TodoPriorityS',    SyntaxAt(21,  2)
  AssertEqual 'TodoPriorityS',    SyntaxAt(21,  5)
  AssertEqual 'TodoPriorityT',    SyntaxAt(22,  2)
  AssertEqual 'TodoPriorityT',    SyntaxAt(22,  5)
  AssertEqual 'TodoPriorityU',    SyntaxAt(23,  2)
  AssertEqual 'TodoPriorityU',    SyntaxAt(23,  5)
  AssertEqual 'TodoPriorityV',    SyntaxAt(24,  2)
  AssertEqual 'TodoPriorityV',    SyntaxAt(24,  5)
  AssertEqual 'TodoPriorityW',    SyntaxAt(25,  2)
  AssertEqual 'TodoPriorityW',    SyntaxAt(25,  5)
  AssertEqual 'TodoPriorityX',    SyntaxAt(26,  2)
  AssertEqual 'TodoPriorityX',    SyntaxAt(26,  5)
  AssertEqual 'TodoPriorityY',    SyntaxAt(27,  2)
  AssertEqual 'TodoPriorityY',    SyntaxAt(27,  5)
Given todo (todo items with invalid or misleading syntax);
x   .    1    .    2    .    3    .    4    .    5    .    6    .    7    .    8  L01
x 345678901234567890123456789012345678901234567890123456789012345678901234567890  L02
X Done tasks must start with a lowercase x then space                             L03
xDone tasks must start with a lowercase x then space                              L04
XDone tasks must start with a lowercase x then space                              L05
(a) Priority must start with an uppercase letter in rounds followed by space      L06
(A)Priority must start with an uppercase letter in rounds followed by space       L07
A  Priority must start with an uppercase letter in rounds followed by space       L08
a  Priority must start with an uppercase letter in rounds followed by space       L09
Priority (A) must start with an uppercase letter in rounds followed by space      L10
due:2050-01-01 keys are valid on the start of the line                            L11
due:2010-01-01 overdue dates are valid on the start of the line                   L12
2010-01-01 dates are valid on the start of the line                               L13
x   .    1    .    2    .    3    .    4    .    5    .    6    .    7    .    8  L14
x 345678901234567890123456789012345678901234567890123456789012345678901234567890  L15
Invalid dates 17-10-05 20100101 01-01-2010 2010/01/01 10/01/01 2010-01-01-2010    L16
@Contexts are valid on the start of the line                                      L17
+Projects are valid on the start of the line                                      L18
The key: syntax must be followed by a value, same for due:                        L19
due: syntax must be a whole word notdue:2010-01-01 pro@jects and con+texts also   L20
x 345678901234567890123456789012345678901234567890123456789012345678901234567890  L21
x   .    1    .    2    .    3    .    4    .    5    .    6    .    7    .    8  L22
Execute (Syntax for invalid or misleading tasks):
  " Invalid done or priority
  AssertEqual 'TodoTodo',         SyntaxAt( 3,  1)
  AssertEqual 'TodoTodo',         SyntaxAt( 4,  1)
  AssertEqual 'TodoTodo',         SyntaxAt( 5,  1)
  AssertEqual 'TodoTodo',         SyntaxAt( 6,  1)
  AssertEqual 'TodoTodo',         SyntaxAt( 7,  1)
  AssertEqual 'TodoTodo',         SyntaxAt( 8,  1)
  AssertEqual 'TodoTodo',         SyntaxAt( 9,  1)
  AssertEqual 'TodoTodo',         SyntaxAt(10,  1)
  " Valid keys and dates at start of line
  AssertEqual 'TodoKey',          SyntaxAt(11,  1)
  AssertEqual 'TodoDate',         SyntaxAt(11,  5)
  AssertEqual 'TodoOverDueDate',  SyntaxAt(12,  1)
  AssertEqual 'TodoDate',         SyntaxAt(13,  1)
  " Invalid date formats.
  " FIXME: Not all cases are tested, not sure how strict to be
  " AssertEqual '',                 SyntaxAt(16, 15)  " FIXME
  AssertEqual 'TodoTodo',         SyntaxAt(16, 24)
  " AssertEqual '',                 SyntaxAt(16, 33)  " FIXME
  AssertEqual 'TodoTodo',         SyntaxAt(16, 42)
  AssertEqual 'TodoTodo',         SyntaxAt(16, 44)
  AssertEqual 'TodoTodo',         SyntaxAt(16, 55)
  " AssertEqual '',                 SyntaxAt(16, 64)  " FIXME
  AssertEqual 'TodoTodo',         SyntaxAt(16, 78)
  " Contexts and projects on the start of a line (valid)
  AssertEqual 'TodoContext',      SyntaxAt(17,  1)
  AssertEqual 'TodoProject',      SyntaxAt(18,  1)
  " Invalid keys, etc
  AssertEqual 'TodoTodo',         SyntaxAt(19,  5)
  AssertEqual 'TodoTodo',         SyntaxAt(19, 55)
  AssertEqual 'TodoTodo',         SyntaxAt(20,  1)
  AssertEqual 'TodoKey',          SyntaxAt(20, 34)
  AssertEqual 'TodoDate',         SyntaxAt(20, 41)
  AssertEqual 'TodoTodo',         SyntaxAt(20, 55)
  AssertEqual 'TodoTodo',         SyntaxAt(20, 69)
Do (Insert a task due today):
  OTask due-\<BS>:\<C-R>=strftime("%Y-%m-%d")\<CR> today\<C-O>
Then (Syntax for task due today):
  Log getline(1)
  AssertEqual 'TodoDueToday', SyntaxAt(1, 12)

" function todo#GetDateRegexForPastDates() {{{2

Before:
  let b:rex = todo#GetDateRegexForPastDates(2017,09,07)
Given todo (Some test todo items):
  Active      due:2000-01-01 due:2050-01-01 2017-09-10 +Project @Context key:value  L04
Execute (Log generated RegExp):
  Log b:rex
Execute (0000-00-00 should match with reference 2017-09-07):
  Assert '0000-00-00' =~ '^' . b:rex . '$'
Execute (0000-12-31 should match with reference 2017-09-07):
  Assert '0000-12-31' =~ '^' . b:rex . '$'
Execute (1999-12-31 should match with reference 2017-09-07):
  Assert '1999-12-31' =~ '^' . b:rex . '$'
Execute (2000-01-01 should match with reference 2017-09-07):
  Assert '2000-01-01' =~ '^' . b:rex . '$'
Execute (2001-01-01 should match with reference 2017-09-07):
  Assert '2001-01-01' =~ '^' . b:rex . '$'
Execute (2002-01-01 should match with reference 2017-09-07):
  Assert '2002-01-01' =~ '^' . b:rex . '$'
Execute (2003-01-01 should match with reference 2017-09-07):
  Assert '2003-01-01' =~ '^' . b:rex . '$'
Execute (2004-01-01 should match with reference 2017-09-07):
  Assert '2004-01-01' =~ '^' . b:rex . '$'
Execute (2005-01-01 should match with reference 2017-09-07):
  Assert '2005-01-01' =~ '^' . b:rex . '$'
Execute (2006-01-01 should match with reference 2017-09-07):
  Assert '2006-01-01' =~ '^' . b:rex . '$'
Execute (2007-01-01 should match with reference 2017-09-07):
  Assert '2007-01-01' =~ '^' . b:rex . '$'
Execute (2008-01-01 should match with reference 2017-09-07):
  Assert '2008-01-01' =~ '^' . b:rex . '$'
Execute (2009-01-01 should match with reference 2017-09-07):
  Assert '2009-01-01' =~ '^' . b:rex . '$'
Execute (2010-01-01 should match with reference 2017-09-07):
  Assert '2010-01-01' =~ '^' . b:rex . '$'
Execute (2011-01-01 should match with reference 2017-09-07):
  Assert '2011-01-01' =~ '^' . b:rex . '$'
Execute (2012-01-01 should match with reference 2017-09-07):
  Assert '2012-01-01' =~ '^' . b:rex . '$'
Execute (2013-01-01 should match with reference 2017-09-07):
  Assert '2013-01-01' =~ '^' . b:rex . '$'
Execute (2014-01-01 should match with reference 2017-09-07):
  Assert '2014-01-01' =~ '^' . b:rex . '$'
Execute (2015-01-01 should match with reference 2017-09-07):
  Assert '2015-01-01' =~ '^' . b:rex . '$'
Execute (2016-01-01 should match with reference 2017-09-07):
  Assert '2016-01-01' =~ '^' . b:rex . '$'
Execute (2016-02-29 should match with reference 2017-09-07):
  Assert '2016-02-29' =~ '^' . b:rex . '$'
Execute (2016-09-07 should match with reference 2017-09-07):
  Assert '2016-09-07' =~ '^' . b:rex . '$'
Execute (2017-01-01 should match with reference 2017-09-07):
  Assert '2017-01-01' =~ '^' . b:rex . '$'
Execute (2017-01-31 should match with reference 2017-09-07):
  Assert '2017-01-31' =~ '^' . b:rex . '$'
Execute (2017-02-01 should match with reference 2017-09-07):
  Assert '2017-02-01' =~ '^' . b:rex . '$'
Execute (2017-02-28 should match with reference 2017-09-07):
  Assert '2017-02-28' =~ '^' . b:rex . '$'
Execute (2017-03-01 should match with reference 2017-09-07):
  Assert '2017-03-01' =~ '^' . b:rex . '$'
Execute (2017-03-31 should match with reference 2017-09-07):
  Assert '2017-03-31' =~ '^' . b:rex . '$'
Execute (2017-04-01 should match with reference 2017-09-07):
  Assert '2017-04-01' =~ '^' . b:rex . '$'
Execute (2017-04-30 should match with reference 2017-09-07):
  Assert '2017-04-30' =~ '^' . b:rex . '$'
Execute (2017-05-01 should match with reference 2017-09-07):
  Assert '2017-05-01' =~ '^' . b:rex . '$'
Execute (2017-05-31 should match with reference 2017-09-07):
  Assert '2017-05-31' =~ '^' . b:rex . '$'
Execute (2017-06-01 should match with reference 2017-09-07):
  Assert '2017-06-01' =~ '^' . b:rex . '$'
Execute (2017-06-30 should match with reference 2017-09-07):
  Assert '2017-06-30' =~ '^' . b:rex . '$'
Execute (2017-07-01 should match with reference 2017-09-07):
  Assert '2017-07-01' =~ '^' . b:rex . '$'
Execute (2017-07-31 should match with reference 2017-09-07):
  Assert '2017-07-31' =~ '^' . b:rex . '$'
Execute (2017-08-01 should match with reference 2017-09-07):
  Assert '2017-08-01' =~ '^' . b:rex . '$'
Execute (2017-08-31 should match with reference 2017-09-07):
  Assert '2017-08-31' =~ '^' . b:rex . '$'
Execute (2017-09-01 should match with reference 2017-09-07):
  Assert '2017-09-01' =~ '^' . b:rex . '$'
Execute (2017-09-02 should match with reference 2017-09-07):
  Assert '2017-09-02' =~ '^' . b:rex . '$'
Execute (2017-09-03 should match with reference 2017-09-07):
  Assert '2017-09-03' =~ '^' . b:rex . '$'
Execute (2017-09-03 should match with reference 2017-09-07):
  Assert '2017-09-03' =~ '^' . b:rex . '$'
Execute (2017-09-04 should match with reference 2017-09-07):
  Assert '2017-09-04' =~ '^' . b:rex . '$'
Execute (2017-09-05 should match with reference 2017-09-07):
  Assert '2017-09-05' =~ '^' . b:rex . '$'
Execute (2017-09-06 should match with reference 2017-09-07):
  Assert '2017-09-06' =~ '^' . b:rex . '$'
Execute (2017-09-07 should NOT match with reference 2017-09-07):
  Assert '2017-09-07' !~ b:rex
Execute (2017-09-08 should NOT match with reference 2017-09-07):
  Assert '2017-09-08' !~ b:rex
Execute (2017-09-09 should NOT match with reference 2017-09-07):
  Assert '2017-09-09' !~ b:rex
Execute (2017-09-10 should NOT match with reference 2017-09-07):
  Assert '2017-09-10' !~ b:rex
Execute (2017-09-30 should NOT match with reference 2017-09-07):
  Assert '2017-09-30' !~ b:rex
Execute (2017-10-01 should NOT match with reference 2017-09-07):
  Assert '2017-10-01' !~ b:rex
Execute (2017-10-31 should NOT match with reference 2017-09-07):
  Assert '2017-10-31' !~ b:rex
Execute (2017-11-01 should NOT match with reference 2017-09-07):
  Assert '2017-11-01' !~ b:rex
Execute (2017-11-30 should NOT match with reference 2017-09-07):
  Assert '2017-11-30' !~ b:rex
Execute (2017-12-01 should NOT match with reference 2017-09-07):
  Assert '2017-12-01' !~ b:rex
Execute (2017-12-31 should NOT match with reference 2017-09-07):
  Assert '2017-12-31' !~ b:rex
Execute (2018-01-01 should NOT match with reference 2017-09-07):
  Assert '2018-01-01' !~ b:rex
Execute (2018-09-08 should NOT match with reference 2017-09-07):
  Assert '2018-09-08' !~ b:rex
Execute (2018-12-31 should NOT match with reference 2017-09-07):
  Assert '2018-12-31' !~ b:rex
Execute (2020-12-31 should NOT match with reference 2017-09-07):
  Assert '2020-12-31' !~ b:rex
Execute (2025-12-31 should NOT match with reference 2017-09-07):
  Assert '2025-12-31' !~ b:rex
Execute (2032-09-06 should NOT match with reference 2017-09-07):
  Assert '2032-09-06' !~ b:rex
Execute (2032-09-07 should NOT match with reference 2017-09-07):
  Assert '2032-09-07' !~ b:rex
Execute (2099-12-31 should NOT match with reference 2017-09-07):
  Assert '2099-12-31' !~ b:rex
Execute (2100-01-01 should NOT match with reference 2017-09-07):
  Assert '2100-01-01' !~ b:rex

" Test a high day/month
Before:
  let b:rex = todo#GetDateRegexForPastDates(2017,11,27)
Execute (Log generated RegExp):
  Log b:rex
Execute (2017-09-09 should match with reference 2017-11-27):
  Assert '2017-09-09' =~ '^' . b:rex . '$'
Execute (2017-11-01 should match with reference 2017-11-27):
  Assert '2017-11-01' =~ '^' . b:rex . '$'
Execute (2017-11-09 should match with reference 2017-11-27):
  Assert '2017-11-09' =~ '^' . b:rex . '$'
Execute (2017-11-19 should match with reference 2017-11-27):
  Assert '2017-11-19' =~ '^' . b:rex . '$'
Execute (2017-11-26 should match with reference 2017-11-27):
  Assert '2017-11-26' =~ '^' . b:rex . '$'
Execute (2017-11-27 should NOT match with reference 2017-11-27):
  Assert '2017-11-27' !~ b:rex
Execute (2017-11-28 should NOT match with reference 2017-11-27):
  Assert '2017-11-28' !~ b:rex

Before:
  let b:rex = todo#GetDateRegexForPastDates(2017,12,31)
Execute (Log generated RegExp):
  Log b:rex
Execute (2017-12-30 should match with reference 2017-12-31):
  Assert '2017-12-30' =~ '^' . b:rex . '$'
Execute (2017-12-31 should NOT match with reference 2017-12-31):
  Assert '2017-12-31' !~ b:rex

" Tests for a future date 2032-01-07
Before:
  let b:rex = todo#GetDateRegexForPastDates(2032,01,07)
Execute (Log generated RegExp):
  Log b:rex
Execute (1999-09-06 should match with reference 2032-01-07):
  Assert '1999-09-06' =~ '^' . b:rex . '$'
Execute (2000-09-06 should match with reference 2032-01-07):
  Assert '2000-09-06' =~ '^' . b:rex . '$'
Execute (2018-09-06 should match with reference 2032-01-07):
  Assert '2018-09-06' =~ '^' . b:rex . '$'
Execute (2031-09-06 should match with reference 2032-01-07):
  Assert '2031-09-06' =~ '^' . b:rex . '$'
Execute (2032-01-01 should match with reference 2032-01-07):
  Assert '2032-01-01' =~ '^' . b:rex . '$'
Execute (2032-01-02 should match with reference 2032-01-07):
  Assert '2032-01-02' =~ '^' . b:rex . '$'
Execute (2032-01-03 should match with reference 2032-01-07):
  Assert '2032-01-03' =~ '^' . b:rex . '$'
Execute (2032-01-04 should match with reference 2032-01-07):
  Assert '2032-01-04' =~ '^' . b:rex . '$'
Execute (2032-01-05 should match with reference 2032-01-07):
  Assert '2032-01-05' =~ '^' . b:rex . '$'
Execute (2032-01-06 should match with reference 2032-01-07):
  Assert '2032-01-06' =~ '^' . b:rex . '$'
Execute (2032-01-07 should NOT match with reference 2032-01-07):
  Assert '2032-01-07' !~ b:rex
Execute (2032-01-08 should NOT match with reference 2032-01-07):
  Assert '2032-01-08' !~ b:rex

" Should work from 2000 onwards
Before:
  let b:rex = todo#GetDateRegexForPastDates(2000,01,01)
Execute (Log generated RegExp):
  Log b:rex
Execute (1999-12-31 should match with reference 2000-01-01):
  Assert '1999-12-31' =~ '^' . b:rex . '$'
Execute (2000-01-01 should NOT match with reference 2000-01-01):
  Assert '2000-01-01' !~ b:rex

" Should work out to 2099
Before:
  let b:rex = todo#GetDateRegexForPastDates(2099,12,31)
Execute (Log generated RegExp):
  Log b:rex
Execute (2099-12-30 should match with reference 2099-12-31):
  Assert '2099-12-30' =~ '^' . b:rex . '$'
Execute (2099-12-31 should NOT match with reference 2099-12-31):
  Assert '2099-12-31' !~ b:rex

" Two digit year is not valid
Before:
  let b:rex = todo#GetDateRegexForPastDates(17,12,31)
Execute (Log generated RegExp):
  Log b:rex
Execute (16-12-31 should NOT match with reference 17-12-31):
  Assert '16-12-31' !~ b:rex
Execute (2016-12-31 should NOT match with reference 17-12-31):
  Assert '2016-12-31' !~ b:rex

" Make sure current date doesn't match
Before:
  let b:rex = todo#GetDateRegexForPastDates(strftime("%Y"), strftime("%m"), strftime("%d"))
Execute (Log generated RegExp):
  Log b:rex
Execute (Current date should not match):
  Assert strftime("%Y-%m-%d") !~ b:rex

" Incorrectly matching current date, some breakpoints that previously were found
" to be an issue
Before:
  let b:rex = todo#GetDateRegexForPastDates(2017,09,20)
Execute (Log generated RegExp):
  Log b:rex
Execute (2017-09-19 should match with reference 2017-09-20):
  Assert '2017-09-19' =~ b:rex
Execute (2017-09-20 should NOT match with reference 2017-09-20):
  Assert '2017-09-20' !~ b:rex
Before:
  let b:rex = todo#GetDateRegexForPastDates(2017,09,30)
Execute (Log generated RegExp):
  Log b:rex
Execute (2017-09-29 should match with reference 2017-09-30):
  Assert '2017-09-29' =~ b:rex
Execute (2017-09-30 should NOT match with reference 2017-09-30):
  Assert '2017-09-30' !~ b:rex
Before:
  let b:rex = todo#GetDateRegexForPastDates(2017,10,01)
Execute (Log generated RegExp):
  Log b:rex
Execute (2017-09-30 should match with reference 2017-10-01):
  Assert '2017-09-30' =~ b:rex
Execute (2017-10-01 should NOT match with reference 2017-10-01):
  Assert '2017-10-01' !~ b:rex

" file: autoload/todo.vim {{{1

" function! todo#ToggleMarkAsDone(status) {{{2

Given todo (Tasks):
  x 2017-09-18 Complete task
  x 2017-09-18 2017-09-01 Completed task with a created date
  x 2017-09-18 Completed priority pri:A task
  x 2017-09-18 2017-09-01 Completed priority task with a created date pri:A
  X 2017-09-18 Not to be confused for a complete task
  Active task
  2017-09-01 Active task with a created date
  (A) Active priority task
  (C) 2017-09-01 Active priority task with a created date
  X 2017-09-18 Not to be confused for a complete task
  XNot to be confused for a complete task
   x 2017-09-18 Leading whitespace is not valid
  Tricky incomplete task x 2017-09-18
Execute (Toggle completed):
  :global/./call todo#ToggleMarkAsDone('')
  :call ReplaceCurrentDates('')
Expect todo (Toggled tasks with today as **TODAY**):
  Complete task
  2017-09-01 Completed task with a created date
  (A) Completed priority task
  (A) 2017-09-01 Completed priority task with a created date
  x **TODAY** X 2017-09-18 Not to be confused for a complete task
  x **TODAY** Active task
  x **TODAY** 2017-09-01 Active task with a created date
  x **TODAY** Active priority task pri:A
  x **TODAY** 2017-09-01 Active priority task with a created date pri:C
  x **TODAY** X 2017-09-18 Not to be confused for a complete task
  x **TODAY** XNot to be confused for a complete task
  x **TODAY** x 2017-09-18 Leading whitespace is not valid
  x **TODAY** Tricky incomplete task x 2017-09-18
Execute (Toggle twice):
  :global/./call todo#ToggleMarkAsDone('')
  :global/./call todo#ToggleMarkAsDone('')
  :call ReplaceCurrentDates('')
Expect todo (Tasks, completed on today):
  x **TODAY** Complete task
  x **TODAY** 2017-09-01 Completed task with a created date
  x **TODAY** Completed priority task pri:A
  x **TODAY** 2017-09-01 Completed priority task with a created date pri:A
  X 2017-09-18 Not to be confused for a complete task
  Active task
  2017-09-01 Active task with a created date
  (A) Active priority task
  (C) 2017-09-01 Active priority task with a created date
  X 2017-09-18 Not to be confused for a complete task
  XNot to be confused for a complete task
  x 2017-09-18 Leading whitespace is not valid
  Tricky incomplete task x 2017-09-18
" The tests above use :global/ to run todo#ToggleMarkAsDone on every line, this
" is because Vader seems to have an issue with updating the line using %,
" however, using global avoids catching exceptions, whereas % gets them.
Execute (Check todo#ToggleMarkAsDone for exceptions):
  :%call todo#ToggleMarkAsDone('')

" function! todo#ToggleMarkAsDone('Cancelled') {{{2

Given todo (Tasks):
  x 2017-09-18 Cancelled Cancelled task
  x 2017-09-18 Cancelled 2017-09-01 Cancelledd task with a created date
  x 2017-09-18 Cancelled Cancelledd priority pri:A task
  x 2017-09-18 Cancelled 2017-09-01 Cancelledd priority task with a created date pri:A
  X 2017-09-18 Cancelled Not to be confused for a cancelle task
  Active task
  2017-09-01 Active task with a created date
  (A) Active priority task
  (C) 2017-09-01 Active priority task with a created date
  X 2017-09-18 Not to be confused for a cancelle task
  XNot to be confused for a cancelle task
   x 2017-09-18 Leading whitespace is not valid
  Tricky incancelle task x 2017-09-18
Execute (Toggle cancelled):
  :global/./call todo#ToggleMarkAsDone('Cancelled')
  :call ReplaceCurrentDates('')
Expect todo (Toggled tasks with today as **TODAY**):
  Cancelled task
  2017-09-01 Cancelledd task with a created date
  (A) Cancelledd priority task
  (A) 2017-09-01 Cancelledd priority task with a created date
  x **TODAY** Cancelled X 2017-09-18 Cancelled Not to be confused for a cancelle task
  x **TODAY** Cancelled Active task
  x **TODAY** Cancelled 2017-09-01 Active task with a created date
  x **TODAY** Cancelled Active priority task pri:A
  x **TODAY** Cancelled 2017-09-01 Active priority task with a created date pri:C
  x **TODAY** Cancelled X 2017-09-18 Not to be confused for a cancelle task
  x **TODAY** Cancelled XNot to be confused for a cancelle task
  x **TODAY** Cancelled x 2017-09-18 Leading whitespace is not valid
  x **TODAY** Cancelled Tricky incancelle task x 2017-09-18
Execute (Toggle twice):
  :global/./call todo#ToggleMarkAsDone('Cancelled')
  :global/./call todo#ToggleMarkAsDone('Cancelled')
  :call ReplaceCurrentDates('')
Expect todo (Tasks, cancelled on today):
  x **TODAY** Cancelled Cancelled task
  x **TODAY** Cancelled 2017-09-01 Cancelledd task with a created date
  x **TODAY** Cancelled Cancelledd priority task pri:A
  x **TODAY** Cancelled 2017-09-01 Cancelledd priority task with a created date pri:A
  X 2017-09-18 Cancelled Not to be confused for a cancelle task
  Active task
  2017-09-01 Active task with a created date
  (A) Active priority task
  (C) 2017-09-01 Active priority task with a created date
  X 2017-09-18 Not to be confused for a cancelle task
  XNot to be confused for a cancelle task
  x 2017-09-18 Leading whitespace is not valid
  Tricky incancelle task x 2017-09-18
" The tests above use :global/ to run todo#ToggleMarkAsDone on every line, this
" is because Vader seems to have an issue with updating the line using %,
" however, using global avoids catching exceptions, whereas % gets them.
Execute (Check todo#ToggleMarkAsDone for exceptions):
  :%call todo#ToggleMarkAsDone('Cancelled')

" function: todo#SortDue() {{{2

Before:
    let g:TodoTxtSortDueDateCursorPos = "top"
After:
  if exists("g:TodoTxtSortDueDateCursorPos")
    unlet g:TodoTxtSortDueDateCursorPos
  endif
" In given/expected lists:
"     GIV:xx is the order the task is given
"     EXP:xx is the order the task is expected to be sorted into
" Use :sort n /GIV:/   or  :sort n /EXP:/   to sort by given/expected order
" All invalid dates (i.e. that should not be sorted) are in 2011.
Given todo (Tasks for sorting with a bit of everything):
  active  dUE:2051-01-01 cAsE                                     EXP:24 GIV:01
  overdue due:2001-01-01                                          EXP:02 GIV:02
  notdue  overdue:2011-11-11 invalid key                          EXP:34 GIV:03
  overdue duE:2009-01-01 cAsE                                     EXP:18 GIV:04
  xoverdue due:2001-02-01 This is not done (must be lower x)      EXP:03 GIV:05
  overdue due:2012-01-01 \|| no tasks the between bars ||/        EXP:21 GIV:06
  x done  due:2011-11-11 topmost done task                        EXP:46 GIV:07
  notdue  due: 2011-11-11 space invalidates due:                  EXP:35 GIV:08
  overdue due:2005-01-01 +Project @Context                        EXP:10 GIV:09
  overdue due:2002-01-01 @Context                                 EXP:04 GIV:10
  overdue due:2004-02-01                                          EXP:09 GIV:11
  notdue  due: due:2011-MM-DD                                     EXP:36 GIV:12
  overdue due:2000-01-01 cursor here for top, most overdue        EXP:01 GIV:13
  notdue  due:2011-11-1                                           EXP:37 GIV:14
  active  due:2059-01-01 bottommost active task                   EXP:33 GIV:15
  overdue due:2006-01-01                                          EXP:12 GIV:16
  overdue due:2007-02-01 +Project                                 EXP:15 GIV:17
  active  due:2056-01-01                                          EXP:29 GIV:18
  notdue  due:2011-1-11                                           EXP:38 GIV:19
  x done  due:2011-11-11                                          EXP:47 GIV:20
  overdue dUe:2008-02-01 cAsE                                     EXP:17 GIV:21
  X overdue due:2002-02-01 This is not done (must be lower x)     EXP:05 GIV:22
  +Project overdue due:2003-02-01 project at start of line        EXP:07 GIV:23
  notdue  due:2011                                                EXP:39 GIV:24
  active  DUe:2052-01-01 cAsE                                     EXP:25 GIV:25
  overdue due:2007-01-01                                          EXP:14 GIV:26
  overdue Due:2008-01-01 cAsE                                     EXP:16 GIV:27
  notdue  @Project                                                EXP:40 GIV:28
  active  due:2055-01-01                                          EXP:28 GIV:29
  active  due:2057-01-01                                          EXP:30 GIV:30
  overdue DuE:2009-02-01 cAsE                                     EXP:19 GIV:31
  notdue  @Context                                                EXP:41 GIV:32
  x done  due:2011-11-11 bottommost done task cursor here bottom  EXP:48 GIV:33
  active  DUE:2053-01-01 cAsE                                     EXP:26 GIV:34
  active  key:value due:2054-01-01 leading key:value              EXP:27 GIV:35
  active  due:2058-01-01                                          EXP:31 GIV:36
  notdue  key:value                                               EXP:42 GIV:37
  overdue due:2017-01-01 Last overdue task when sorted            EXP:22 GIV:38
  overdue due:2010-12-31 /|| no tasks the between bars ||\        EXP:20 GIV:39
  active  due:2050-01-01 cursor here with "notoverdue" setting    EXP:23 GIV:40
  notdue  due:invalid    invalid due date                         EXP:43 GIV:41
  overdue 2011-11-11 due:2005-02-01 leading date                  EXP:11 GIV:42
  due:2004-01-01 overdue due: at start of line                    EXP:08 GIV:43
  notdue  notdue:2011-11-11 invalid key                           EXP:44 GIV:44
  overdue due:2006-02-01 due:2011-11-11 two dates, choose first   EXP:13 GIV:45
  @Context overdue due:2003-01-01 context at start of line        EXP:06 GIV:46
  active  due date at very end of line                            EXP:32 GIV:47 due:2058-02-01
"FIXME:  notdue  due:2011-11-11- trailing - invalidates the date         EXP:45 GIV:48
Do (Sort by due date):
  :call todo#SortDue()\<CR>
Expect todo (Sorted list):
  overdue due:2000-01-01 cursor here for top, most overdue        EXP:01 GIV:13
  overdue due:2001-01-01                                          EXP:02 GIV:02
  xoverdue due:2001-02-01 This is not done (must be lower x)      EXP:03 GIV:05
  overdue due:2002-01-01 @Context                                 EXP:04 GIV:10
  X overdue due:2002-02-01 This is not done (must be lower x)     EXP:05 GIV:22
  @Context overdue due:2003-01-01 context at start of line        EXP:06 GIV:46
  +Project overdue due:2003-02-01 project at start of line        EXP:07 GIV:23
  due:2004-01-01 overdue due: at start of line                    EXP:08 GIV:43
  overdue due:2004-02-01                                          EXP:09 GIV:11
  overdue due:2005-01-01 +Project @Context                        EXP:10 GIV:09
  overdue 2011-11-11 due:2005-02-01 leading date                  EXP:11 GIV:42
  overdue due:2006-01-01                                          EXP:12 GIV:16
  overdue due:2006-02-01 due:2011-11-11 two dates, choose first   EXP:13 GIV:45
  overdue due:2007-01-01                                          EXP:14 GIV:26
  overdue due:2007-02-01 +Project                                 EXP:15 GIV:17
  overdue Due:2008-01-01 cAsE                                     EXP:16 GIV:27
  overdue dUe:2008-02-01 cAsE                                     EXP:17 GIV:21
  overdue duE:2009-01-01 cAsE                                     EXP:18 GIV:04
  overdue DuE:2009-02-01 cAsE                                     EXP:19 GIV:31
  overdue due:2010-12-31 /|| no tasks the between bars ||\        EXP:20 GIV:39
  overdue due:2012-01-01 \|| no tasks the between bars ||/        EXP:21 GIV:06
  overdue due:2017-01-01 Last overdue task when sorted            EXP:22 GIV:38
  active  due:2050-01-01 cursor here with "notoverdue" setting    EXP:23 GIV:40
  active  dUE:2051-01-01 cAsE                                     EXP:24 GIV:01
  active  DUe:2052-01-01 cAsE                                     EXP:25 GIV:25
  active  DUE:2053-01-01 cAsE                                     EXP:26 GIV:34
  active  key:value due:2054-01-01 leading key:value              EXP:27 GIV:35
  active  due:2055-01-01                                          EXP:28 GIV:29
  active  due:2056-01-01                                          EXP:29 GIV:18
  active  due:2057-01-01                                          EXP:30 GIV:30
  active  due:2058-01-01                                          EXP:31 GIV:36
  active  due date at very end of line                            EXP:32 GIV:47 due:2058-02-01
  active  due:2059-01-01 bottommost active task                   EXP:33 GIV:15
  notdue  overdue:2011-11-11 invalid key                          EXP:34 GIV:03
  notdue  due: 2011-11-11 space invalidates due:                  EXP:35 GIV:08
  notdue  due: due:2011-MM-DD                                     EXP:36 GIV:12
  notdue  due:2011-11-1                                           EXP:37 GIV:14
  notdue  due:2011-1-11                                           EXP:38 GIV:19
  notdue  due:2011                                                EXP:39 GIV:24
  notdue  @Project                                                EXP:40 GIV:28
  notdue  @Context                                                EXP:41 GIV:32
  notdue  key:value                                               EXP:42 GIV:37
  notdue  due:invalid    invalid due date                         EXP:43 GIV:41
  notdue  notdue:2011-11-11 invalid key                           EXP:44 GIV:44
  x done  due:2011-11-11 topmost done task                        EXP:46 GIV:07
  x done  due:2011-11-11                                          EXP:47 GIV:20
  x done  due:2011-11-11 bottommost done task cursor here bottom  EXP:48 GIV:33
Do (Sort by due date):
  :call todo#SortDue()\<CR>
Then (Check post sort cursor position: top):
  AssertEqual 1, line('.')
Do (Sort and check cursor position: not set):
  :unlet g:TodoTxtSortDueDateCursorPos | call todo#SortDue()\<CR>
Then (Is cursor at top):
  AssertEqual 1, line('.')
Do (Sort and check cursor position: lastdue):
  :let g:TodoTxtSortDueDateCursorPos="lastdue" | call todo#SortDue()\<CR>
Then (Is the cursor on the last task with a due:date?):
  AssertEqual 33, line('.')
Do (Sort and check cursor position: notoverdue):
  :let g:TodoTxtSortDueDateCursorPos="notoverdue" | call todo#SortDue()\<CR>
Then (Is cursor on first non-overdue task?):
  AssertEqual 23, line('.')
Do (Sort and check cursor position: bottom):
  :let g:TodoTxtSortDueDateCursorPos="bottom" | call todo#SortDue()\<CR>
Then (Is cursor on the last line of the buffer?):
  AssertEqual line('$'), line('.')

Given todo (Tasks for sorting with no done tasks):
  overdue due:2000-01-01 cursor here for top, most overdue        EXP:01
  overdue due:2001-01-01                                          EXP:02
  overdue due:2002-01-01                                          EXP:03
  active  due:2050-01-01 cursor here with "notoverdue" setting    EXP:04
  active  due:2055-01-01                                          EXP:05
  active  due:2059-01-01 bottommost active task                   EXP:06
  notdue                                                          EXP:07
  notdue                                                          EXP:08
  notdue                                                          EXP:09
Do (Sort and check cursor position: lastdue):
  :let g:TodoTxtSortDueDateCursorPos="lastdue" | call todo#SortDue()\<CR>
Then (Is cursor on the last task with a due:date set?):
  AssertEqual 6, line('.')
Do (Sort and check cursor position: notoverdue):
  :let g:TodoTxtSortDueDateCursorPos="notoverdue" | call todo#SortDue()\<CR>
Then (Is cursor on first non-overdue task?):
  AssertEqual 4, line('.')

Given todo (Tasks for sorting with no overdue tasks):
  active  due:2050-01-01 cursor here with "notoverdue" setting    EXP:01
  active  due:2055-01-01                                          EXP:02
  active  due:2059-01-01 bottommost active task                   EXP:03
  notdue                                                          EXP:04
  notdue                                                          EXP:05
  notdue                                                          EXP:06
  x done  due:2011-11-11 topmost done task                        EXP:07
  x done  due:2011-11-11                                          EXP:08
  x done  due:2011-11-11 bottommost done task cursor here bottom  EXP:09
Do (Sort and check cursor position: lastdue):
  :let g:TodoTxtSortDueDateCursorPos="lastdue" | call todo#SortDue()\<CR>
Then (Is cursor on the last task with a due:date set?):
  AssertEqual 3, line('.')
Do (Sort and check cursor position: notoverdue):
  :let g:TodoTxtSortDueDateCursorPos="notoverdue" | call todo#SortDue()\<CR>
Then (Is cursor on first non-overdue task?):
  AssertEqual 1, line('.')

Given todo (Tasks for sorting with no active tasks):
  overdue due:2000-01-01 cursor here for top, most overdue        EXP:01
  overdue due:2001-01-01                                          EXP:02
  overdue due:2002-01-01                                          EXP:03
  notdue                                                          EXP:04
  notdue                                                          EXP:05
  notdue                                                          EXP:06
  x done  due:2011-11-11 topmost done task                        EXP:07
  x done  due:2011-11-11                                          EXP:08
  x done  due:2011-11-11 bottommost done task cursor here bottom  EXP:09
Do (Sort and check cursor position: lastdue):
  :let g:TodoTxtSortDueDateCursorPos="lastdue" | call todo#SortDue()\<CR>
Then (Is cursor on the last task with a due:date set?):
  AssertEqual 3, line('.')
Do (Sort and check cursor position: notoverdue):
  :let g:TodoTxtSortDueDateCursorPos="notoverdue" | call todo#SortDue()\<CR>
Then (Is cursor on first non-overdue task?):
  AssertEqual 4, line('.')

Given todo (Tasks for sorting with no active or done tasks):
  overdue due:2000-01-01 cursor here for top, most overdue        EXP:01
  overdue due:2001-01-01                                          EXP:02
  overdue due:2002-01-01                                          EXP:03
  notdue                                                          EXP:04
  notdue                                                          EXP:05
  notdue                                                          EXP:06
Do (Sort and check cursor position: lastdue):
  :let g:TodoTxtSortDueDateCursorPos="lastdue" | call todo#SortDue()\<CR>
Then (Is cursor on the last task with a due:date set?):
  AssertEqual 3, line('.')
Do (Sort and check cursor position: notoverdue):
  :let g:TodoTxtSortDueDateCursorPos="notoverdue" | call todo#SortDue()\<CR>
Then (Is cursor on first non-overdue task?):
  AssertEqual 4, line('.')

Given todo (Tasks for sorting with no overdue or done tasks):
  active  due:2050-01-01 cursor here with "notoverdue" setting    EXP:01
  active  due:2055-01-01                                          EXP:02
  active  due:2059-01-01 bottommost active task                   EXP:03
  notdue                                                          EXP:04
  notdue                                                          EXP:05
  notdue                                                          EXP:06
Do (Sort and check cursor position: lastdue):
  :let g:TodoTxtSortDueDateCursorPos="lastdue" | call todo#SortDue()\<CR>
Then (Is cursor on the last task with a due:date set?):
  AssertEqual 3, line('.')
Do (Sort and check cursor position: notoverdue):
  :let g:TodoTxtSortDueDateCursorPos="notoverdue" | call todo#SortDue()\<CR>
Then (Is cursor on first non-overdue task?):
  AssertEqual 1, line('.')

Given todo (Tasks for sorting with no overdue or active tasks):
  notdue                                                          EXP:01
  notdue                                                          EXP:02
  notdue                                                          EXP:03
  x done  due:2011-11-11 topmost done task                        EXP:04
  x done  due:2011-11-11                                          EXP:05
  x done  due:2011-11-11 bottommost done task cursor here bottom  EXP:06
Do (Sort and check cursor position: lastdue):
  :let g:TodoTxtSortDueDateCursorPos="lastdue" | call todo#SortDue()\<CR>
Then (Is cursor on the last task with a due:date set?):
  AssertEqual 1, line('.')
Do (Sort and check cursor position: notoverdue):
  :let g:TodoTxtSortDueDateCursorPos="notoverdue" | call todo#SortDue()\<CR>
Then (Is cursor on first non-overdue task?):
  AssertEqual 1, line('.')

Given todo (Tasks for sorting with only not due tasks):
  notdue                                                          EXP:01
  notdue                                                          EXP:02
  notdue                                                          EXP:03
Do (Sort and check cursor position: lastdue):
  :let g:TodoTxtSortDueDateCursorPos="lastdue" | call todo#SortDue()\<CR>
Then (Is cursor on the last task with a due:date set?):
  AssertEqual 1, line('.')
Do (Sort and check cursor position: notoverdue):
  :let g:TodoTxtSortDueDateCursorPos="notoverdue" | call todo#SortDue()\<CR>
Then (Is cursor on first non-overdue task?):
  AssertEqual 1, line('.')

Given todo (Tasks for sorting with only due tasks):
  active  due:2050-01-01 cursor here with "notoverdue" setting    EXP:01
  active  due:2055-01-01                                          EXP:02
  active  due:2059-01-01 bottommost active task                   EXP:03
Do (Sort and check cursor position: lastdue):
  :let g:TodoTxtSortDueDateCursorPos="lastdue" | call todo#SortDue()\<CR>
Then (Is cursor on the last task with a due:date set?):
  AssertEqual 3, line('.')
Do (Sort and check cursor position: notoverdue):
  :let g:TodoTxtSortDueDateCursorPos="notoverdue" | call todo#SortDue()\<CR>
Then (Is cursor on first non-overdue task?):
  AssertEqual 1, line('.')


" function todo#Complete(findstart, base) {{{2
Before:
After:
Given todo (Tasks):
  2017-09-23 Test task +SecretProject @Work due:2017-09-26
  Tricky lowercase @wrongCaseSelected +selectedWrongCase
  Project without a context +SecretProject
Do (Complete context W):
  Go@W\<C-X>\<C-O>
Expect todo (Context Work):
  2017-09-23 Test task +SecretProject @Work due:2017-09-26
  Tricky lowercase @wrongCaseSelected +selectedWrongCase
  Project without a context +SecretProject
  @Work
Do (Complete project S):
  Go+S\<C-X>\<C-O>
Expect todo (Project SecretProject):
  2017-09-23 Test task +SecretProject @Work due:2017-09-26
  Tricky lowercase @wrongCaseSelected +selectedWrongCase
  Project without a context +SecretProject
  +SecretProject
" FIXME: It seems the omnicomplete preview window tests are being run from the
" .vader file rather than the Given block, weird.
" Execute (Complete project and switch to preview):
"   :execute "normal Go+\<C-X>\<C-O>\<ESC>"
"   :blast!
" Expect (FIXME Project SecretProject):
"   Contexts: @Context
"   Buffers: tests/todo.vader
"   

" function todo#GetDaysInMonth(month, year) {{{2
Before:
After:
Given:
Execute (todo#GetDaysInMonth):
  AssertEqual todo#GetDaysInMonth( 1, 2017), 31, "Days in January not correct"
  AssertEqual todo#GetDaysInMonth( 2, 2000), 29, "Days in February 2000 not correct"
  AssertEqual todo#GetDaysInMonth( 2, 2100), 28, "Days in February 2100 not correct"
  AssertEqual todo#GetDaysInMonth( 2, 2200), 28, "Days in February 2200 not correct"
  AssertEqual todo#GetDaysInMonth( 2, 2300), 28, "Days in February 2300 not correct"
  AssertEqual todo#GetDaysInMonth( 2, 2400), 29, "Days in February 2400 not correct"
  AssertEqual todo#GetDaysInMonth( 2, 2001), 28, "Days in February 2001 not correct"
  AssertEqual todo#GetDaysInMonth( 2, 2002), 28, "Days in February 2002 not correct"
  AssertEqual todo#GetDaysInMonth( 2, 2003), 28, "Days in February 2003 not correct"
  AssertEqual todo#GetDaysInMonth( 2, 2004), 29, "Days in February 2004 not correct"
  AssertEqual todo#GetDaysInMonth( 2, 2008), 29, "Days in February 2008 not correct"
  AssertEqual todo#GetDaysInMonth( 2, 2010), 28, "Days in February 2010 not correct"
  AssertEqual todo#GetDaysInMonth( 2, 2020), 29, "Days in February 2020 not correct"
  AssertEqual todo#GetDaysInMonth( 2, 2017), 28, "Days in February 2017 not correct"
  AssertEqual todo#GetDaysInMonth( 3, 2017), 31, "Days in March not correct"
  AssertEqual todo#GetDaysInMonth( 4, 2017), 30, "Days in April not correct"
  AssertEqual todo#GetDaysInMonth( 5, 2017), 31, "Days in May not correct"
  AssertEqual todo#GetDaysInMonth( 6, 2017), 30, "Days in June not correct"
  AssertEqual todo#GetDaysInMonth( 7, 2017), 31, "Days in July not correct"
  AssertEqual todo#GetDaysInMonth( 8, 2017), 31, "Days in August not correct"
  AssertEqual todo#GetDaysInMonth( 9, 2017), 30, "Days in September not correct"
  AssertEqual todo#GetDaysInMonth(10, 2017), 31, "Days in October not correct"
  AssertEqual todo#GetDaysInMonth(11, 2017), 30, "Days in November not correct"
  AssertEqual todo#GetDaysInMonth(12, 2017), 31, "Days in December not correct"

" function todo#ParseDate(datestring) {{{2
Before:
After:
Given:
Execute (todo#ParseDate):
  AssertEqual todo#ParseDate('2017-01-02'), [2017, 01, 02]
  AssertEqual todo#ParseDate('2017-02-01'), [2017, 02, 01]
  AssertEqual todo#ParseDate('2017-10-01'), [2017, 10, 01]
  AssertEqual todo#ParseDate('2017-11-01'), [2017, 11, 01]
  AssertEqual todo#ParseDate('2017-12-01'), [2017, 12, 01]
  AssertThrows call todo#ParseDate('17-02-01')
  AssertThrows call todo#ParseDate('2017-02-01 ')
  AssertThrows call todo#ParseDate(' 2017-02-01')

" function todo#DateAdd(year, month, day, units, unit_type) {{{2
Before:
After:
Given:
Execute (todo#DateAdd, days):
  AssertEqual todo#DateAdd(2000,  01,   01,   -1, 'd'), [1999, 12, 31]
  AssertEqual todo#DateAdd(1999,  12,   31,    1, 'd'), [2000, 01, 01]
  AssertEqual todo#DateAdd('2000','01', '01',  1, 'd'), [2000, 01, 02]
  AssertEqual todo#DateAdd(2000,  01,   04,   -1, 'd'), [2000, 01, 03]
  AssertEqual todo#DateAdd(2000,  01,   06,   -2, 'd'), [2000, 01, 04]
  AssertEqual todo#DateAdd(2000,  01,   03,    2, 'd'), [2000, 01, 05]
  AssertEqual todo#DateAdd(1999,  12,   06,   31, 'd'), [2000, 01, 06]
  AssertEqual todo#DateAdd(2000,  02,   07,  -31, 'd'), [2000, 01, 07]
  AssertEqual todo#DateAdd(2001,  01,   08, -366, 'd'), [2000, 01, 08]
  AssertEqual todo#DateAdd(1999,  01,   09,  365, 'd'), [2000, 01, 09]
  AssertEqual todo#DateAdd(2000,  02,   28,    2, 'd'), [2000, 03, 01]
  AssertEqual todo#DateAdd(2000,  02,   28,    1, 'd'), [2000, 02, 29]
  AssertEqual todo#DateAdd(2000,  12,   31,    1, 'd'), [2001, 01, 01]
  AssertEqual todo#DateAdd(2004,  03,   01,   -1, 'd'), [2004, 02, 29]
  AssertEqual todo#DateAdd(2010,  03,   31,    1, 'd'), [2010, 04, 01]
  AssertEqual todo#DateAdd(2010,  04,   30,    1, 'd'), [2010, 05, 01]
  AssertEqual todo#DateAdd(2010,  05,   31,    1, 'd'), [2010, 06, 01]
  AssertEqual todo#DateAdd(2010,  06,   30,    1, 'd'), [2010, 07, 01]
  AssertEqual todo#DateAdd(2010,  07,   31,    1, 'd'), [2010, 08, 01]
  AssertEqual todo#DateAdd(2010,  08,   31,    1, 'd'), [2010, 09, 01]
  AssertEqual todo#DateAdd(2010,  09,   30,    1, 'd'), [2010, 10, 01]
  AssertEqual todo#DateAdd(2010,  10,   31,    1, 'd'), [2010, 11, 01]
  AssertEqual todo#DateAdd(2010,  11,   30,    1, 'd'), [2010, 12, 01]
  AssertEqual todo#DateAdd(2010,  12,   31,    1, 'd'), [2011, 01, 01]
  AssertEqual todo#DateAdd(2016,  02,   01,   -1, 'd'), [2016, 01, 31]
  AssertEqual todo#DateAdd(2016,  03,   01,   -1, 'd'), [2016, 02, 29]
  AssertEqual todo#DateAdd(2016,  04,   01,   -1, 'd'), [2016, 03, 31]
  AssertEqual todo#DateAdd(2016,  05,   01,   -1, 'd'), [2016, 04, 30]
  AssertEqual todo#DateAdd(2016,  06,   01,   -1, 'd'), [2016, 05, 31]
  AssertEqual todo#DateAdd(2016,  07,   01,   -1, 'd'), [2016, 06, 30]
  AssertEqual todo#DateAdd(2016,  08,   01,   -1, 'd'), [2016, 07, 31]
  AssertEqual todo#DateAdd(2016,  09,   01,   -1, 'd'), [2016, 08, 31]
  AssertEqual todo#DateAdd(2016,  10,   01,   -1, 'd'), [2016, 09, 30]
  AssertEqual todo#DateAdd(2016,  11,   01,   -1, 'd'), [2016, 10, 31]
  AssertEqual todo#DateAdd(2016,  12,   01,   -1, 'd'), [2016, 11, 30]
  AssertEqual todo#DateAdd(2017,  01,   01,   -1, 'd'), [2016, 12, 31]
  AssertEqual todo#DateAdd(2016,  01,   01,   -1, 'd'), [2015, 12, 31]
  AssertEqual todo#DateAdd(2017,  03,   01,   -1, 'd'), [2017, 02, 28]
  AssertEqual todo#DateAdd(2017,  02,   28,    1, 'd'), [2017, 03, 01]
  AssertEqual todo#DateAdd(2017,  04,   01,   30, 'd'), [2017, 05, 01]
  AssertEqual todo#DateAdd(1900,  01,   01, 1520, 'd'), [1904, 03, 01]
  AssertEqual todo#DateAdd(2304,  03,   01,-1520, 'd'), [2300, 01, 01]
Execute (todo#DateAdd, weeks):
  AssertEqual todo#DateAdd(2014,  08,   07,    1, 'w'), [2014, 08, 14]
  AssertEqual todo#DateAdd(2014,  08,   07,    2, 'w'), [2014, 08, 21]
  AssertEqual todo#DateAdd(2014,  08,   04,   -3, 'w'), [2014, 07, 14]
  AssertEqual todo#DateAdd(2014,  08,   04,   -2, 'w'), [2014, 07, 21]
Execute (todo#DateAdd, months):
  " Add one month to a date in the middle of the month should keep day of month
  AssertEqual todo#DateAdd(2016,  12,   27,    1, 'm'), [2017, 01, 27]
  AssertEqual todo#DateAdd(2017,  01,   27,    1, 'm'), [2017, 02, 27]
  AssertEqual todo#DateAdd(2017,  02,   27,    1, 'm'), [2017, 03, 27]
  AssertEqual todo#DateAdd(2017,  03,   27,    1, 'm'), [2017, 04, 27]
  AssertEqual todo#DateAdd(2017,  04,   27,    1, 'm'), [2017, 05, 27]
  AssertEqual todo#DateAdd(2017,  05,   27,    1, 'm'), [2017, 06, 27]
  AssertEqual todo#DateAdd(2017,  06,   27,    1, 'm'), [2017, 07, 27]
  AssertEqual todo#DateAdd(2017,  07,   27,    1, 'm'), [2017, 08, 27]
  AssertEqual todo#DateAdd(2017,  08,   27,    1, 'm'), [2017, 09, 27]
  AssertEqual todo#DateAdd(2017,  09,   27,    1, 'm'), [2017, 10, 27]
  AssertEqual todo#DateAdd(2017,  10,   27,    1, 'm'), [2017, 11, 27]
  AssertEqual todo#DateAdd(2017,  11,   27,    1, 'm'), [2017, 12, 27]
  AssertEqual todo#DateAdd(2017,  12,   27,    1, 'm'), [2018, 01, 27]
  " Sub one month to a date in the middle of the month should keep day of month
  AssertEqual todo#DateAdd(2017,  02,   26,   -1, 'm'), [2017, 01, 26]
  AssertEqual todo#DateAdd(2017,  03,   26,   -1, 'm'), [2017, 02, 26]
  AssertEqual todo#DateAdd(2017,  04,   26,   -1, 'm'), [2017, 03, 26]
  AssertEqual todo#DateAdd(2017,  05,   26,   -1, 'm'), [2017, 04, 26]
  AssertEqual todo#DateAdd(2017,  06,   26,   -1, 'm'), [2017, 05, 26]
  AssertEqual todo#DateAdd(2017,  07,   26,   -1, 'm'), [2017, 06, 26]
  AssertEqual todo#DateAdd(2017,  08,   26,   -1, 'm'), [2017, 07, 26]
  AssertEqual todo#DateAdd(2017,  09,   26,   -1, 'm'), [2017, 08, 26]
  AssertEqual todo#DateAdd(2017,  10,   26,   -1, 'm'), [2017, 09, 26]
  AssertEqual todo#DateAdd(2017,  11,   26,   -1, 'm'), [2017, 10, 26]
  AssertEqual todo#DateAdd(2017,  12,   26,   -1, 'm'), [2017, 11, 26]
  AssertEqual todo#DateAdd(2018,  01,   26,   -1, 'm'), [2017, 12, 26]
  AssertEqual todo#DateAdd(2018,  02,   26,   -1, 'm'), [2018, 01, 26]
  " End of month should be sticky
  AssertEqual todo#DateAdd(2010,  01,   31,    1, 'm'), [2010, 02, 28]
  AssertEqual todo#DateAdd(2010,  02,   28,    1, 'm'), [2010, 03, 31]
  AssertEqual todo#DateAdd(2010,  03,   31,    1, 'm'), [2010, 04, 30]
  AssertEqual todo#DateAdd(2010,  04,   30,    1, 'm'), [2010, 05, 31]
  AssertEqual todo#DateAdd(2010,  05,   31,    1, 'm'), [2010, 06, 30]
  AssertEqual todo#DateAdd(2010,  06,   30,    1, 'm'), [2010, 07, 31]
  AssertEqual todo#DateAdd(2010,  07,   31,    1, 'm'), [2010, 08, 31]
  AssertEqual todo#DateAdd(2010,  08,   31,    1, 'm'), [2010, 09, 30]
  AssertEqual todo#DateAdd(2010,  09,   30,    1, 'm'), [2010, 10, 31]
  AssertEqual todo#DateAdd(2010,  10,   31,    1, 'm'), [2010, 11, 30]
  AssertEqual todo#DateAdd(2010,  11,   30,    1, 'm'), [2010, 12, 31]
  AssertEqual todo#DateAdd(2010,  12,   31,    1, 'm'), [2011, 01, 31]
  " End of month should be sticky
  AssertEqual todo#DateAdd(2012,  01,   31,   -1, 'm'), [2011, 12, 31]
  AssertEqual todo#DateAdd(2012,  02,   29,   -1, 'm'), [2012, 01, 31]
  AssertEqual todo#DateAdd(2012,  03,   31,   -1, 'm'), [2012, 02, 29]
  AssertEqual todo#DateAdd(2012,  04,   30,   -1, 'm'), [2012, 03, 31]
  AssertEqual todo#DateAdd(2012,  05,   31,   -1, 'm'), [2012, 04, 30]
  AssertEqual todo#DateAdd(2012,  06,   30,   -1, 'm'), [2012, 05, 31]
  AssertEqual todo#DateAdd(2012,  07,   31,   -1, 'm'), [2012, 06, 30]
  AssertEqual todo#DateAdd(2012,  08,   31,   -1, 'm'), [2012, 07, 31]
  AssertEqual todo#DateAdd(2012,  09,   30,   -1, 'm'), [2012, 08, 31]
  AssertEqual todo#DateAdd(2012,  10,   31,   -1, 'm'), [2012, 09, 30]
  AssertEqual todo#DateAdd(2012,  11,   30,   -1, 'm'), [2012, 10, 31]
  AssertEqual todo#DateAdd(2012,  12,   31,   -1, 'm'), [2012, 11, 30]
  " When adding more than one month, the intermediate months should not impact
  " EOM calculations.
  AssertEqual todo#DateAdd(2000,  01,   30,   11, 'm'), [2000, 12, 30]
  AssertEqual todo#DateAdd(2000,  01,   31,    9, 'm'), [2000, 10, 31]
  AssertEqual todo#DateAdd(2001,  12,   30,  -11, 'm'), [2001, 01, 30]
  AssertEqual todo#DateAdd(2001,  10,   31,   -9, 'm'), [2001, 01, 31]
Execute (todo#DateAdd, years):
  AssertEqual todo#DateAdd(1900,  11,   30,    1, 'y'), [1901, 11, 30]
  AssertEqual todo#DateAdd(1900,  11,   30,    2, 'y'), [1902, 11, 30]
  AssertEqual todo#DateAdd(1900,  11,   30,    5, 'y'), [1905, 11, 30]
  AssertEqual todo#DateAdd(1915,  11,   30,   -1, 'y'), [1914, 11, 30]
  AssertEqual todo#DateAdd(1915,  11,   30,   -2, 'y'), [1913, 11, 30]
  AssertEqual todo#DateAdd(1915,  11,   30,   -5, 'y'), [1910, 11, 30]
  " 2012 is a leap year
  AssertEqual todo#DateAdd(2011,  02,   05,    3, 'y'), [2014, 02, 05]
Execute (todo#DateAdd, boundaries, variations and validity):
  AssertEqual todo#DateAdd(1800,  01,   01,    1, 'd'), [1900, 01, 02]
  AssertEqual todo#DateAdd(1800,  01,   01,   -1, 'd'), [1900, 01, 01]
  AssertEqual todo#DateAdd(2017,  30,   01,    1, 'd'), [2017, 12, 02]
  AssertEqual todo#DateAdd(2017,  30,   01,   -1, 'd'), [2017, 11, 30]
  AssertEqual todo#DateAdd(2017,  04,   80,    1, 'd'), [2017, 05, 01]
  AssertEqual todo#DateAdd(2017,  04,   80,   -1, 'd'), [2017, 04, 30]
  AssertEqual todo#DateAdd(2017,  07,   80,   -1, 'd'), [2017, 07, 31]
  AssertEqual todo#DateAdd(1800,  01,   03,    1, 'm'), [1900, 02, 03]
  AssertEqual todo#DateAdd(1800,  01,   03,   -1, 'm'), [1900, 01, 03]
  AssertEqual todo#DateAdd(2017,  30,   03,    1, 'm'), [2018, 01, 03]
  AssertEqual todo#DateAdd(2017,  30,   03,   -1, 'm'), [2017, 12, 03]
  AssertEqual todo#DateAdd(2017,  04,   80,    1, 'm'), [2017, 05, 31]
  AssertEqual todo#DateAdd(2017,  04,   80,   -1, 'm'), [2017, 03, 31]
  AssertEqual todo#DateAdd(-1,    -1,   -1,    1, 'd'), [1900, 01, 02]
  " Case
  AssertEqual todo#DateAdd(1950,  10,   10,    2, 'D'), [1950, 10, 12]
  AssertEqual todo#DateAdd(1950,  10,   10,   -2, 'D'), [1950, 10, 08]
  AssertEqual todo#DateAdd(1950,  10,   10,    2, 'W'), [1950, 10, 24]
  AssertEqual todo#DateAdd(1950,  10,   10,   -2, 'W'), [1950, 09, 26]
  AssertEqual todo#DateAdd(1950,  10,   10,    2, 'M'), [1950, 12, 10]
  AssertEqual todo#DateAdd(1950,  10,   10,   -2, 'M'), [1950, 08, 10]
  AssertEqual todo#DateAdd(1950,  10,   10,    2, 'Y'), [1952, 10, 10]
  AssertEqual todo#DateAdd(1950,  10,   10,   -2, 'Y'), [1948, 10, 10]
  " People may well use the behaviours below to their advantage, it could be
  " useful, we should try to keep this consistent.
  AssertEqual todo#DateAdd(0,      0,    0,    1, 'd'), [str2nr(strftime('%Y')), str2nr(strftime('%m')), str2nr(strftime('%d')) + 1]
  AssertEqual todo#DateAdd(0,     08,   05,    1, 'd'), [str2nr(strftime('%Y')), 08, 06]
  AssertEqual todo#DateAdd(2016,   0,   06,    1, 'd'), [2016, str2nr(strftime('%m')), 07]
  AssertEqual todo#DateAdd(2015,  07,    0,    1, 'd'), [2015, 07, str2nr(strftime('%d')) + 1]
  AssertEqual todo#DateAdd(2015,  08,   08,    0, 'd'), [2015, 08, 08]
  AssertEqual todo#DateAdd(2016,  09,   09,    0, 'm'), [2016, 09, 09]
  AssertEqual todo#DateAdd(1600,  50,   50,    0, 'd'), [1900, 12, 31]
  AssertEqual todo#DateAdd(0,     50,   50,    0, 'd'), [str2nr(strftime('%Y')), 12, 31]

" function todo#ChangeDueDate(units, unit_type, from_reference) {{{2
Before:
After:
Given todo (Tasks with a bit of everything):
  active  dUE:2051-01-01 cAsE                                               L01
  notdue  overdue:2011-11-11 invalid key                                    L02
  xoverdue due:2001-02-01 This is not done (must be lower x)                L03
  x done  due:2011-11-11 completed task                                     L04
  notdue  due: 2011-11-11 space invalidates due:                            L05
  overdue due:2005-02-28 +Project @Context                                  L06
  notdue  due: due:2011-MM-DD                                               L07
  notdue  due:2011-11-1                                                     L08
  overdue dUe:2008-02-01 cAsE                                               L09
  X overdue due:2002-02-01 This is not done (must be lower x)               L10
  +Project overdue due:2003-02-01 project at start of line                  L11
  notdue  due:2011                                                          L12
  active  DUe:2052-01-01 cAsE                                               L13
  notdue  @Project                                                          L14
  active  key:value due:2054-01-01 leading key:value                        L15
  overdue due:2010-12-31                                                    L16
  notdue  due:invalid    invalid due date                                   L17
  overdue 2011-11-11 due:2005-02-01 leading date                            L18
  due:2004-01-01 overdue due: at start of line                              L19
  overdue due:2006-02-01 due:2011-11-11 two dates, choose first             L20
  overdue due:2011-11-11- trailing - invalidates the date                   L21
  active  due date at very end of line                                      L22 due:2058-02-01
Execute (todo#ChangeDueDate):
  :%call todo#ChangeDueDate(1, 'd', '')
  :let [s:year, s:month, s:day] = todo#ParseDate(strftime("%Y-%m-%d"))
  :let [s:year, s:month, s:day] = todo#DateAdd(s:year, s:month, s:day, 1, 'd')
  :let s:duedate = printf('%04d', s:year) . '-' . printf('%02d', s:month) . '-' . printf('%02d', s:day)
  :call ReplaceCurrentDates(s:duedate)
Expect todo (Tasks with due date incremented):
  active  dUE:2051-01-02 cAsE                                               L01
  notdue  overdue:2011-11-11 invalid key                                    L02 due:**EXPECTED**
  xoverdue due:2001-02-02 This is not done (must be lower x)                L03
  x done  due:2011-11-11 completed task                                     L04
  notdue  due: 2011-11-11 space invalidates due:                            L05
  overdue due:2005-03-01 +Project @Context                                  L06
  notdue  due: due:2011-MM-DD                                               L07
  notdue  due:2011-11-1                                                     L08
  overdue dUe:2008-02-02 cAsE                                               L09
  X overdue due:2002-02-02 This is not done (must be lower x)               L10
  +Project overdue due:2003-02-02 project at start of line                  L11
  notdue  due:2011                                                          L12
  active  DUe:2052-01-02 cAsE                                               L13
  notdue  @Project                                                          L14 due:**EXPECTED**
  active  key:value due:2054-01-02 leading key:value                        L15
  overdue due:2011-01-01                                                    L16
  notdue  due:invalid    invalid due date                                   L17
  overdue 2011-11-11 due:2005-02-02 leading date                            L18
  due:2004-01-02 overdue due: at start of line                              L19
  overdue due:2006-02-02 due:2011-11-11 two dates, choose first             L20
  overdue due:2011-11-11- trailing - invalidates the date                   L21
  active  due date at very end of line                                      L22 due:2058-02-02

" function todo#CreateNewRecurrence(triggerOnNonStrict) {{{2
Before:
After:
Given todo (Recurring tasks - strict):
  L01 unrelated task 1
  L02 due:2020-01-02 strict recurring task rec:+5d should be 2020-01-07 after
  L03 dUE:2020-01-03 cAsE rEc:+5M should be 2020-06-03 after
  rec:+1y L04 task starting with a recur keyword due:2020-01-04 should be 2021-01-04 after
  L05 due:2020-01-05 recur at end of line, should be 2020-01-19 after rec:+2w
  L06 due:2020-01-06 REC:+1D REC:+1W REC:+1Y select first rec: and then chain should be 2020-01-07, 2020-01-13, 2021-01-06 after
  L07 unrelated task 2
Execute (todo#CreateNewRecurrence 1):
  :01call todo#CreateNewRecurrence(1)
  :AssertEqual 1, line('.')
  :02call todo#CreateNewRecurrence(1)
  :AssertEqual 2, line('.')
  :04call todo#CreateNewRecurrence(1)
  :AssertEqual 4, line('.')
  :06call todo#CreateNewRecurrence(1)
  :AssertEqual 6, line('.')
  :08call todo#CreateNewRecurrence(1)
  :AssertEqual 8, line('.')
  :10call todo#CreateNewRecurrence(1)
  :10call todo#CreateNewRecurrence(1)
  :10call todo#CreateNewRecurrence(1)
  :AssertEqual 10, line('.')
Expect todo (New task and recurrence due date extended):
  L01 unrelated task 1
  L02 due:2020-01-02 strict recurring task should be 2020-01-07 after
  L02 due:2020-01-07 strict recurring task rec:+5d should be 2020-01-07 after
  L03 dUE:2020-01-03 cAsE should be 2020-06-03 after
  L03 dUE:2020-06-03 cAsE rEc:+5M should be 2020-06-03 after
  L04 task starting with a recur keyword due:2020-01-04 should be 2021-01-04 after
  rec:+1y L04 task starting with a recur keyword due:2021-01-04 should be 2021-01-04 after
  L05 due:2020-01-05 recur at end of line, should be 2020-01-19 after
  L05 due:2020-01-19 recur at end of line, should be 2020-01-19 after rec:+2w
  L06 due:2020-01-06 select first rec: and then chain should be 2020-01-07, 2020-01-13, 2021-01-06 after
  L06 due:2021-01-06 REC:+1Y select first rec: and then chain should be 2020-01-07, 2020-01-13, 2021-01-06 after
  L06 due:2020-01-13 REC:+1W REC:+1Y select first rec: and then chain should be 2020-01-07, 2020-01-13, 2021-01-06 after
  L06 due:2020-01-07 REC:+1D REC:+1W REC:+1Y select first rec: and then chain should be 2020-01-07, 2020-01-13, 2021-01-06 after
  L07 unrelated task 2
Execute (todo#CreateNewRecurrence 0):
" Calling with 0 or 1 for strict recurrence should yield the same results
  :01call todo#CreateNewRecurrence(0)
  :AssertEqual 1, line('.')
  :02call todo#CreateNewRecurrence(0)
  :AssertEqual 2, line('.')
  :04call todo#CreateNewRecurrence(0)
  :AssertEqual 4, line('.')
  :06call todo#CreateNewRecurrence(0)
  :AssertEqual 6, line('.')
  :08call todo#CreateNewRecurrence(0)
  :AssertEqual 8, line('.')
  :10call todo#CreateNewRecurrence(0)
  :10call todo#CreateNewRecurrence(0)
  :10call todo#CreateNewRecurrence(0)
  :AssertEqual 10, line('.')
Expect todo (New task and recurrence due date extended):
  L01 unrelated task 1
  L02 due:2020-01-02 strict recurring task should be 2020-01-07 after
  L02 due:2020-01-07 strict recurring task rec:+5d should be 2020-01-07 after
  L03 dUE:2020-01-03 cAsE should be 2020-06-03 after
  L03 dUE:2020-06-03 cAsE rEc:+5M should be 2020-06-03 after
  L04 task starting with a recur keyword due:2020-01-04 should be 2021-01-04 after
  rec:+1y L04 task starting with a recur keyword due:2021-01-04 should be 2021-01-04 after
  L05 due:2020-01-05 recur at end of line, should be 2020-01-19 after
  L05 due:2020-01-19 recur at end of line, should be 2020-01-19 after rec:+2w
  L06 due:2020-01-06 select first rec: and then chain should be 2020-01-07, 2020-01-13, 2021-01-06 after
  L06 due:2021-01-06 REC:+1Y select first rec: and then chain should be 2020-01-07, 2020-01-13, 2021-01-06 after
  L06 due:2020-01-13 REC:+1W REC:+1Y select first rec: and then chain should be 2020-01-07, 2020-01-13, 2021-01-06 after
  L06 due:2020-01-07 REC:+1D REC:+1W REC:+1Y select first rec: and then chain should be 2020-01-07, 2020-01-13, 2021-01-06 after
  L07 unrelated task 2

Given todo (Recurring tasks - non-strict):
  L01 unrelated task 1
  L02 due:2020-01-02 strict recurring task rec:2d
  L03 dUE:2020-01-03 cAsE rEc:2M
  rec:2y L04 task starting with a recur keyword due:2020-01-04
  L05 due:2020-01-05 recur at end of line rec:2w
  L06 due:2020-01-06 REC:2D REC:2W REC:2Y select first rec: and then chain
  L07 unrelated task 2
Execute (todo#CreateNewRecurrence 1):
" Calling with 1 on non-strict should trigger recurrence
  :01call todo#CreateNewRecurrence(1)
  :AssertEqual 1, line('.')
  :02call todo#CreateNewRecurrence(1)
  :AssertEqual 2, line('.')
  :04call todo#CreateNewRecurrence(1)
  :AssertEqual 4, line('.')
  :06call todo#CreateNewRecurrence(1)
  :AssertEqual 6, line('.')
  :08call todo#CreateNewRecurrence(1)
  :AssertEqual 8, line('.')
  :10call todo#CreateNewRecurrence(1)
  :10call todo#CreateNewRecurrence(1)
  :10call todo#CreateNewRecurrence(1)
  :AssertEqual 10, line('.')
  :call ReplaceCurrentDates('')
Expect todo (New task and recurrence due date extended):
  L01 unrelated task 1
  L02 due:2020-01-02 strict recurring task
  L02 due:**TODAY+2D** strict recurring task rec:2d
  L03 dUE:2020-01-03 cAsE
  L03 dUE:**TODAY+2M** cAsE rEc:2M
  L04 task starting with a recur keyword due:2020-01-04
  rec:2y L04 task starting with a recur keyword due:**TODAY+2Y**
  L05 due:2020-01-05 recur at end of line
  L05 due:**TODAY+2W** recur at end of line rec:2w
  L06 due:2020-01-06 select first rec: and then chain
  L06 due:**TODAY+2Y** REC:2Y select first rec: and then chain
  L06 due:**TODAY+2W** REC:2W REC:2Y select first rec: and then chain
  L06 due:**TODAY+2D** REC:2D REC:2W REC:2Y select first rec: and then chain
  L07 unrelated task 2
Execute (todo#CreateNewRecurrence 0):
" Calling with 0 on non-strict should not make any changes
  :1call todo#CreateNewRecurrence(0)
  :AssertEqual 1, line('.')
  :2call todo#CreateNewRecurrence(0)
  :AssertEqual 2, line('.')
  :3call todo#CreateNewRecurrence(0)
  :AssertEqual 3, line('.')
  :4call todo#CreateNewRecurrence(0)
  :AssertEqual 4, line('.')
  :5call todo#CreateNewRecurrence(0)
  :AssertEqual 5, line('.')
  :6call todo#CreateNewRecurrence(0)
  :AssertEqual 6, line('.')
Expect todo (Recurring tasks - non-strict, not modified):
  L01 unrelated task 1
  L02 due:2020-01-02 strict recurring task rec:2d
  L03 dUE:2020-01-03 cAsE rEc:2M
  rec:2y L04 task starting with a recur keyword due:2020-01-04
  L05 due:2020-01-05 recur at end of line rec:2w
  L06 due:2020-01-06 REC:2D REC:2W REC:2Y select first rec: and then chain
  L07 unrelated task 2

" file: ftplugin/todo.vim {{{1

" Mappings {{{2

" Mappings: <LocalLeader>x {{{3
Before:
After:
Given todo (Tasks):
  Active task
  x 2015-01-01 Complete task
  Strict recurring task due:2016-01-01 rec:+1m
  Non-strict recurring task due:2017-01-01 rec:2d
Do:
  \xj\xj\xjj\x
Then:
  call ReplaceCurrentDates('')
Expect todo (Tasks toggled complete):
  x **TODAY** Active task
  Complete task
  x **TODAY** Strict recurring task due:2016-01-01
  Strict recurring task due:2016-02-01 rec:+1m
  x **TODAY** Non-strict recurring task due:2017-01-01
  Non-strict recurring task due:**TODAY+2D** rec:2d


" Mappings: <LocalLeader>p / <LocalLeader>P {{{3
Before:
After:
Given todo (Tasks):
  First task, postpone 1 day, should result in 2017-01-02 due:2017-01-01
  Second task, postpone 5 days, should result in 2017-01-06 due:2017-01-01
  Third task, postpone -1 day, should result in 2017-02-19 due:2017-02-20
  Forth task, postpone -5 day, should result in 2017-02-15 due:2017-02-20
  Fifth task, should not be changed from 2017-03-01 due:2017-03-01
  Strict recurring task due:2017-01-01 rec:+2d should result in 2017-01-02 and 2017-01-03
  Non-strict recurring task due:2017-02-01 rec:1d should result in 2017-02-02
Do (Postpone tasks - normal mode):
  \p j
  5\p j
  \P j
  5\P j
  j
  \p j
  j
  \p
Expect todo (Postponed tasks):
  First task, postpone 1 day, should result in 2017-01-02 due:2017-01-02
  Second task, postpone 5 days, should result in 2017-01-06 due:2017-01-06
  Third task, postpone -1 day, should result in 2017-02-19 due:2017-02-19
  Forth task, postpone -5 day, should result in 2017-02-15 due:2017-02-15
  Fifth task, should not be changed from 2017-03-01 due:2017-03-01
  Strict recurring task due:2017-01-02 should result in 2017-01-02 and 2017-01-03
  Strict recurring task due:2017-01-03 rec:+2d should result in 2017-01-02 and 2017-01-03
  Non-strict recurring task due:2017-02-02 rec:1d should result in 2017-02-02

Given todo (Tasks):
  Task visual block 1, should result in 2017-01-02 due:2017-01-01           L01
  Task visual block 1, should result in 2017-01-02 due:2017-01-01           L02
  Task visual block 2, should result in 2017-01-06 due:2017-01-01           L03
  Task visual block 2, should result in 2017-01-06 due:2017-01-01           L04
  Task visual block 3, should result in 2017-02-19 due:2017-02-20           L05
  Task visual block 3, should result in 2017-02-19 due:2017-02-20           L06
  Task visual block 4, should result in 2017-02-15 due:2017-02-20           L07
  Task visual block 4, should result in 2017-02-15 due:2017-02-20           L08
  Fifth task, should not be changed from 2017-03-01 due:2017-03-01          L09
Do (Postpone tasks - visual mode):
  Vj\pjVj5\pjVj\PjVj5\P
Expect todo (Postponed tasks):
  Task visual block 1, should result in 2017-01-02 due:2017-01-02           L01
  Task visual block 1, should result in 2017-01-02 due:2017-01-02           L02
  Task visual block 2, should result in 2017-01-06 due:2017-01-06           L03
  Task visual block 2, should result in 2017-01-06 due:2017-01-06           L04
  Task visual block 3, should result in 2017-02-19 due:2017-02-19           L05
  Task visual block 3, should result in 2017-02-19 due:2017-02-19           L06
  Task visual block 4, should result in 2017-02-15 due:2017-02-15           L07
  Task visual block 4, should result in 2017-02-15 due:2017-02-15           L08
  Fifth task, should not be changed from 2017-03-01 due:2017-03-01          L09

" Mappings: o, O, <Enter> {{{3
Before:
  let g:Todo_txt_prefix_creation_date=0
After:
  unlet g:Todo_txt_prefix_creation_date
Given todo (Empty buffer):
Do (Open a new line - o):
  oNew task
Expect todo (New task with no creation date):
  
  New task
Before:
  let g:Todo_txt_prefix_creation_date=1
  unlet g:Todo_txt_loaded
  source ftplugin/todo.vim
After:
  unlet g:Todo_txt_prefix_creation_date
  nunmap <buffer> o
  nunmap <buffer> O
  iunmap <buffer> <CR>
Given todo (Empty buffer):
Execute (Open some new lines):
  :normal oNew task o
  :normal ONew task O
  :normal A
New task CR
  :call ReplaceCurrentDates('')
Expect todo (New task with no creation date):
  
  **TODAY** New task O
  **TODAY** New task CR
  **TODAY** New task o
Before:
After:


" function: TodoFoldLevel(lnum) {{{2

Before:
After:
Given todo (Tasks):
  active  due:2050-01-01 task                                     L:01
  x 2017-09-01 complete task 1                                    L:02
  x 2017-09-01 complete task 2                                    L:03
  x 2017-09-01 complete task 3                                    L:04
  X 2017-09-01 complete task 3                                    L:05
  active  due:2055-01-01                                          L:06
  x 2017-09-01 complete task 4                                    L:07
  active  due:2059-01-01                                          L:08
  xinvalid due:2059-01-01                                         L:09
  Xinvalid due:2059-01-01                                         L:10
  active  due:2059-01-01                                          L:11
Execute (Check folding level):
  AssertEqual foldlevel(1),       0, 'L:01'
  AssertEqual foldlevel(2),       1, 'L:02'
  AssertEqual foldlevel(3),       1, 'L:03'
  AssertEqual foldlevel(4),       1, 'L:04'
  AssertEqual foldlevel(5),       0, 'L:05'
  AssertEqual foldlevel(6),       0, 'L:06'
  AssertEqual foldlevel(7),       1, 'L:07'
  AssertEqual foldlevel(8),       0, 'L:08'
  AssertEqual foldlevel(9),       0, 'L:09'
  AssertEqual foldlevel(10),      0, 'L:10'
  AssertEqual foldlevel(11),      0, 'L:11'
Execute (Check folding text):
  AssertEqual foldtextresult(2),  '+- 3 Completed tasks '
  AssertEqual foldtextresult(4),  '+- 1 Completed tasks '

"}}}

Include: include/teardown.vader

" vim: tabstop=2 shiftwidth=2 softtabstop=2 expandtab foldmethod=marker