@@ -23,6 +23,7 @@ class FakeBaseTreeKeyManagerItem {
23
23
_children : FakeBaseTreeKeyManagerItem [ ] = [ ] ;
24
24
25
25
isDisabled ?: boolean = false ;
26
+ skipItem ?: boolean = false ;
26
27
27
28
constructor ( private _label : string ) { }
28
29
@@ -263,13 +264,33 @@ describe('TreeKeyManager', () => {
263
264
expect ( keyManager . getActiveItemIndex ( ) ) . toBe ( 0 ) ;
264
265
} ) ;
265
266
267
+ it ( 'should focus the first non-disabled item when Home is pressed' , ( ) => {
268
+ itemList . get ( 0 ) ! . isDisabled = true ;
269
+ keyManager . onClick ( itemList . get ( 2 ) ! ) ;
270
+ expect ( keyManager . getActiveItemIndex ( ) ) . toBe ( 2 ) ;
271
+
272
+ keyManager . onKeydown ( fakeKeyEvents . home ) ;
273
+
274
+ expect ( keyManager . getActiveItemIndex ( ) ) . toBe ( 1 ) ;
275
+ } ) ;
276
+
266
277
it ( 'should focus the last item when End is pressed' , ( ) => {
267
278
keyManager . onClick ( itemList . get ( 0 ) ! ) ;
268
279
expect ( keyManager . getActiveItemIndex ( ) ) . toBe ( 0 ) ;
269
280
270
281
keyManager . onKeydown ( fakeKeyEvents . end ) ;
271
282
expect ( keyManager . getActiveItemIndex ( ) ) . toBe ( itemList . length - 1 ) ;
272
283
} ) ;
284
+
285
+ it ( 'should focus the last non-disabled item when End is pressed' , ( ) => {
286
+ itemList . get ( itemList . length - 1 ) ! . isDisabled = true ;
287
+ keyManager . onClick ( itemList . get ( 0 ) ! ) ;
288
+ expect ( keyManager . getActiveItemIndex ( ) ) . toBe ( 0 ) ;
289
+
290
+ keyManager . onKeydown ( fakeKeyEvents . end ) ;
291
+
292
+ expect ( keyManager . getActiveItemIndex ( ) ) . toBe ( itemList . length - 2 ) ;
293
+ } ) ;
273
294
} ) ;
274
295
275
296
describe ( 'up/down key events' , ( ) => {
@@ -946,6 +967,195 @@ describe('TreeKeyManager', () => {
946
967
expect ( keyManager . getActiveItemIndex ( ) ) . withContext ( 'active item index' ) . toBe ( - 1 ) ;
947
968
} ) ) ;
948
969
} ) ;
970
+
971
+ describe ( 'focusItem' , ( ) => {
972
+ beforeEach ( ( ) => {
973
+ keyManager . onInitialFocus ( ) ;
974
+ } ) ;
975
+
976
+ it ( 'should focus the provided index' , ( ) => {
977
+ expect ( keyManager . getActiveItemIndex ( ) ) . withContext ( 'active item index' ) . toBe ( 0 ) ;
978
+
979
+ keyManager . focusItem ( 1 ) ;
980
+ expect ( keyManager . getActiveItemIndex ( ) ) . withContext ( 'active item index' ) . toBe ( 1 ) ;
981
+ } ) ;
982
+
983
+ it ( 'should be able to set the active item by reference' , ( ) => {
984
+ expect ( keyManager . getActiveItemIndex ( ) ) . withContext ( 'active item index' ) . toBe ( 0 ) ;
985
+
986
+ keyManager . focusItem ( itemList . get ( 2 ) ! ) ;
987
+ expect ( keyManager . getActiveItemIndex ( ) ) . withContext ( 'active item index' ) . toBe ( 2 ) ;
988
+ } ) ;
989
+
990
+ it ( 'should be able to set the active item without emitting an event' , ( ) => {
991
+ const spy = jasmine . createSpy ( 'change spy' ) ;
992
+ const subscription = keyManager . change . subscribe ( spy ) ;
993
+
994
+ expect ( keyManager . getActiveItemIndex ( ) ) . toBe ( 0 ) ;
995
+
996
+ keyManager . focusItem ( 2 , { emitChangeEvent : false } ) ;
997
+
998
+ expect ( keyManager . getActiveItemIndex ( ) ) . toBe ( 2 ) ;
999
+ expect ( spy ) . not . toHaveBeenCalled ( ) ;
1000
+
1001
+ subscription . unsubscribe ( ) ;
1002
+ } ) ;
1003
+
1004
+ it ( 'should not emit an event if the item did not change' , ( ) => {
1005
+ const spy = jasmine . createSpy ( 'change spy' ) ;
1006
+ const subscription = keyManager . change . subscribe ( spy ) ;
1007
+
1008
+ keyManager . focusItem ( 2 ) ;
1009
+ keyManager . focusItem ( 2 ) ;
1010
+
1011
+ expect ( spy ) . toHaveBeenCalledTimes ( 1 ) ;
1012
+
1013
+ subscription . unsubscribe ( ) ;
1014
+ } ) ;
1015
+ } ) ;
1016
+
1017
+ describe ( 'focusFirstItem' , ( ) => {
1018
+ beforeEach ( ( ) => {
1019
+ keyManager . onInitialFocus ( ) ;
1020
+ } ) ;
1021
+
1022
+ it ( 'should focus the first item' , ( ) => {
1023
+ keyManager . onKeydown ( fakeKeyEvents . downArrow ) ;
1024
+ keyManager . onKeydown ( fakeKeyEvents . downArrow ) ;
1025
+ expect ( keyManager . getActiveItemIndex ( ) ) . withContext ( 'active item index' ) . toBe ( 2 ) ;
1026
+
1027
+ keyManager . focusFirstItem ( ) ;
1028
+ expect ( keyManager . getActiveItemIndex ( ) ) . withContext ( 'active item index' ) . toBe ( 0 ) ;
1029
+ } ) ;
1030
+
1031
+ it ( 'should set the active item to the second item if the first one is disabled' , ( ) => {
1032
+ itemList . get ( 0 ) ! . isDisabled = true ;
1033
+
1034
+ keyManager . focusFirstItem ( ) ;
1035
+ expect ( keyManager . getActiveItemIndex ( ) ) . withContext ( 'active item index' ) . toBe ( 1 ) ;
1036
+ } ) ;
1037
+ } ) ;
1038
+
1039
+ describe ( 'focusLastItem' , ( ) => {
1040
+ beforeEach ( ( ) => {
1041
+ keyManager . onInitialFocus ( ) ;
1042
+ } ) ;
1043
+
1044
+ it ( 'should focus the last item' , ( ) => {
1045
+ expect ( keyManager . getActiveItemIndex ( ) ) . withContext ( 'active item index' ) . toBe ( 0 ) ;
1046
+
1047
+ keyManager . focusLastItem ( ) ;
1048
+ expect ( keyManager . getActiveItemIndex ( ) )
1049
+ . withContext ( 'active item index' )
1050
+ . toBe ( itemList . length - 1 ) ;
1051
+ } ) ;
1052
+
1053
+ it ( 'should set the active item to the second-to-last item if the last is disabled' , ( ) => {
1054
+ itemList . get ( itemList . length - 1 ) ! . isDisabled = true ;
1055
+
1056
+ keyManager . focusLastItem ( ) ;
1057
+ expect ( keyManager . getActiveItemIndex ( ) )
1058
+ . withContext ( 'active item index' )
1059
+ . toBe ( itemList . length - 2 ) ;
1060
+ } ) ;
1061
+ } ) ;
1062
+
1063
+ describe ( 'focusNextItem' , ( ) => {
1064
+ beforeEach ( ( ) => {
1065
+ keyManager . onInitialFocus ( ) ;
1066
+ } ) ;
1067
+
1068
+ it ( 'should focus the next item' , ( ) => {
1069
+ expect ( keyManager . getActiveItemIndex ( ) ) . withContext ( 'active item index' ) . toBe ( 0 ) ;
1070
+
1071
+ keyManager . focusNextItem ( ) ;
1072
+ expect ( keyManager . getActiveItemIndex ( ) ) . withContext ( 'active item index' ) . toBe ( 1 ) ;
1073
+ } ) ;
1074
+
1075
+ it ( 'should skip disabled items' , ( ) => {
1076
+ itemList . get ( 1 ) ! . isDisabled = true ;
1077
+
1078
+ keyManager . focusNextItem ( ) ;
1079
+ expect ( keyManager . getActiveItemIndex ( ) ) . withContext ( 'active item index' ) . toBe ( 2 ) ;
1080
+ } ) ;
1081
+ } ) ;
1082
+
1083
+ describe ( 'focusPreviousItem' , ( ) => {
1084
+ beforeEach ( ( ) => {
1085
+ keyManager . onInitialFocus ( ) ;
1086
+ } ) ;
1087
+
1088
+ it ( 'should focus the previous item' , ( ) => {
1089
+ keyManager . onKeydown ( fakeKeyEvents . downArrow ) ;
1090
+ expect ( keyManager . getActiveItemIndex ( ) ) . withContext ( 'active item index' ) . toBe ( 1 ) ;
1091
+
1092
+ keyManager . focusPreviousItem ( ) ;
1093
+ expect ( keyManager . getActiveItemIndex ( ) ) . withContext ( 'active item index' ) . toBe ( 0 ) ;
1094
+ } ) ;
1095
+
1096
+ it ( 'should skip disabled items' , ( ) => {
1097
+ itemList . get ( 1 ) ! . isDisabled = true ;
1098
+ keyManager . onKeydown ( fakeKeyEvents . downArrow ) ;
1099
+ expect ( keyManager . getActiveItemIndex ( ) ) . withContext ( 'active item index' ) . toBe ( 2 ) ;
1100
+
1101
+ keyManager . focusPreviousItem ( ) ;
1102
+ expect ( keyManager . getActiveItemIndex ( ) ) . withContext ( 'active item index' ) . toBe ( 0 ) ;
1103
+ } ) ;
1104
+ } ) ;
1105
+
1106
+ describe ( 'skip predicate' , ( ) => {
1107
+ beforeEach ( ( ) => {
1108
+ keyManager = new TreeKeyManager ( {
1109
+ items : itemList ,
1110
+ skipPredicate : item => item . skipItem ?? false ,
1111
+ } ) ;
1112
+ keyManager . onInitialFocus ( ) ;
1113
+ } ) ;
1114
+
1115
+ it ( 'should be able to skip items with a custom predicate' , ( ) => {
1116
+ itemList . get ( 1 ) ! . skipItem = true ;
1117
+ expect ( keyManager . getActiveItemIndex ( ) ) . toBe ( 0 ) ;
1118
+
1119
+ keyManager . onKeydown ( fakeKeyEvents . downArrow ) ;
1120
+
1121
+ expect ( keyManager . getActiveItemIndex ( ) ) . toBe ( 2 ) ;
1122
+ } ) ;
1123
+ } ) ;
1124
+
1125
+ describe ( 'focus' , ( ) => {
1126
+ beforeEach ( ( ) => {
1127
+ keyManager . onInitialFocus ( ) ;
1128
+
1129
+ for ( const item of itemList ) {
1130
+ spyOn ( item , 'focus' ) ;
1131
+ }
1132
+ } ) ;
1133
+
1134
+ it ( 'calls .focus() on focused items' , ( ) => {
1135
+ keyManager . onKeydown ( fakeKeyEvents . downArrow ) ;
1136
+
1137
+ expect ( itemList . get ( 0 ) ! . focus ) . not . toHaveBeenCalled ( ) ;
1138
+ expect ( itemList . get ( 1 ) ! . focus ) . toHaveBeenCalledTimes ( 1 ) ;
1139
+ expect ( itemList . get ( 2 ) ! . focus ) . not . toHaveBeenCalled ( ) ;
1140
+
1141
+ keyManager . onKeydown ( fakeKeyEvents . downArrow ) ;
1142
+ expect ( itemList . get ( 0 ) ! . focus ) . not . toHaveBeenCalled ( ) ;
1143
+ expect ( itemList . get ( 1 ) ! . focus ) . toHaveBeenCalledTimes ( 1 ) ;
1144
+ expect ( itemList . get ( 2 ) ! . focus ) . toHaveBeenCalledTimes ( 1 ) ;
1145
+ } ) ;
1146
+
1147
+ it ( 'calls .focus() on focused items, when pressing up key' , ( ) => {
1148
+ keyManager . onKeydown ( fakeKeyEvents . downArrow ) ;
1149
+
1150
+ expect ( itemList . get ( 0 ) ! . focus ) . not . toHaveBeenCalled ( ) ;
1151
+ expect ( itemList . get ( 1 ) ! . focus ) . toHaveBeenCalledTimes ( 1 ) ;
1152
+
1153
+ keyManager . onKeydown ( fakeKeyEvents . upArrow ) ;
1154
+
1155
+ expect ( itemList . get ( 0 ) ! . focus ) . toHaveBeenCalledTimes ( 1 ) ;
1156
+ expect ( itemList . get ( 1 ) ! . focus ) . toHaveBeenCalledTimes ( 1 ) ;
1157
+ } ) ;
1158
+ } ) ;
949
1159
} ) ;
950
1160
}
951
1161
} ) ;
0 commit comments