@@ -55,6 +55,11 @@ describe('PoCalendarMonthYearComponent:', () => {
5555 component . locale = 'pt' ;
5656 expect ( component [ 'setupMonths' ] ) . toHaveBeenCalled ( ) ;
5757 } ) ;
58+
59+ it ( 'locale: getter should return the current locale value' , ( ) => {
60+ component . locale = 'en' ;
61+ expect ( component . locale ) . toBe ( 'en' ) ;
62+ } ) ;
5863 } ) ;
5964
6065 describe ( 'Methods:' , ( ) => {
@@ -827,6 +832,244 @@ describe('PoCalendarMonthYearComponent:', () => {
827832
828833 expect ( mockSelectedEl . scrollIntoView ) . toHaveBeenCalledWith ( { block : 'center' , behavior : 'smooth' } ) ;
829834 } ) ) ;
835+
836+ it ( 'should scroll to current year when no selected element' , fakeAsync ( ( ) => {
837+ const currentYear = new Date ( ) . getFullYear ( ) ;
838+ const currentYearIndex = component . displayYears . indexOf ( currentYear ) ;
839+ const mockCurrentYearEl = { scrollIntoView : jasmine . createSpy ( 'scrollIntoView' ) } ;
840+ const mockItems = [ ] ;
841+ for ( let i = 0 ; i <= currentYearIndex ; i ++ ) {
842+ mockItems . push ( i === currentYearIndex ? mockCurrentYearEl : { } ) ;
843+ }
844+
845+ const mockContainer = {
846+ querySelector : jasmine . createSpy ( 'querySelector' ) . and . returnValue ( null ) ,
847+ querySelectorAll : jasmine . createSpy ( 'querySelectorAll' ) . and . returnValue ( mockItems )
848+ } ;
849+ spyOn ( component [ 'elementRef' ] . nativeElement , 'querySelector' ) . and . returnValue ( mockContainer ) ;
850+
851+ component . scrollToSelectedYear ( ) ;
852+ tick ( 200 ) ;
853+
854+ expect ( mockCurrentYearEl . scrollIntoView ) . toHaveBeenCalledWith ( { block : 'center' , behavior : 'smooth' } ) ;
855+ } ) ) ;
856+
857+ it ( 'should do nothing when container is null' , fakeAsync ( ( ) => {
858+ spyOn ( component [ 'elementRef' ] . nativeElement , 'querySelector' ) . and . returnValue ( null ) ;
859+
860+ component . scrollToSelectedYear ( ) ;
861+ tick ( 200 ) ;
862+ } ) ) ;
863+
864+ it ( 'should do nothing when no selected element and currentYear not in display' , fakeAsync ( ( ) => {
865+ component . minDate = new Date ( 2060 , 0 , 1 ) ;
866+ component . maxDate = new Date ( 2065 , 11 , 31 ) ;
867+ component [ 'setupYears' ] ( ) ;
868+
869+ const mockContainer = {
870+ querySelector : jasmine . createSpy ( 'querySelector' ) . and . returnValue ( null ) ,
871+ querySelectorAll : jasmine . createSpy ( 'querySelectorAll' ) . and . returnValue ( [ ] )
872+ } ;
873+ spyOn ( component [ 'elementRef' ] . nativeElement , 'querySelector' ) . and . returnValue ( mockContainer ) ;
874+
875+ component . scrollToSelectedYear ( ) ;
876+ tick ( 200 ) ;
877+ } ) ) ;
878+ } ) ;
879+
880+ describe ( 'focusMonthButton:' , ( ) => {
881+ it ( 'should call focus on the button at the given index' , fakeAsync ( ( ) => {
882+ const mockBtn = { focus : jasmine . createSpy ( 'focus' ) } ;
883+ const mockPoButton = { querySelector : jasmine . createSpy ( 'querySelector' ) . and . returnValue ( mockBtn ) } ;
884+ const mockButtons = [ mockPoButton ] ;
885+
886+ spyOn ( component [ 'elementRef' ] . nativeElement , 'querySelectorAll' ) . and . returnValue ( mockButtons ) ;
887+
888+ component [ 'focusMonthButton' ] ( 0 ) ;
889+ tick ( 10 ) ;
890+
891+ expect ( mockBtn . focus ) . toHaveBeenCalled ( ) ;
892+ } ) ) ;
893+
894+ it ( 'should handle case when button element not found' , fakeAsync ( ( ) => {
895+ spyOn ( component [ 'elementRef' ] . nativeElement , 'querySelectorAll' ) . and . returnValue ( [ ] ) ;
896+
897+ component [ 'focusMonthButton' ] ( 5 ) ;
898+ tick ( 10 ) ;
899+ } ) ) ;
900+
901+ it ( 'should handle case when inner button is null' , fakeAsync ( ( ) => {
902+ const mockPoButton = { querySelector : jasmine . createSpy ( 'querySelector' ) . and . returnValue ( null ) } ;
903+ spyOn ( component [ 'elementRef' ] . nativeElement , 'querySelectorAll' ) . and . returnValue ( [ mockPoButton ] ) ;
904+
905+ component [ 'focusMonthButton' ] ( 0 ) ;
906+ tick ( 10 ) ;
907+ } ) ) ;
908+ } ) ;
909+
910+ describe ( 'focusYearButton:' , ( ) => {
911+ it ( 'should call focus and scrollIntoView on the year button' , fakeAsync ( ( ) => {
912+ const mockBtn = {
913+ focus : jasmine . createSpy ( 'focus' ) ,
914+ scrollIntoView : jasmine . createSpy ( 'scrollIntoView' )
915+ } ;
916+ const mockPoButton = { querySelector : jasmine . createSpy ( 'querySelector' ) . and . returnValue ( mockBtn ) } ;
917+ const mockContainer = {
918+ querySelectorAll : jasmine . createSpy ( 'querySelectorAll' ) . and . returnValue ( [ mockPoButton ] )
919+ } ;
920+
921+ spyOn ( component [ 'elementRef' ] . nativeElement , 'querySelector' ) . and . returnValue ( mockContainer ) ;
922+
923+ component [ 'focusYearButton' ] ( 0 ) ;
924+ tick ( 10 ) ;
925+
926+ expect ( mockBtn . focus ) . toHaveBeenCalled ( ) ;
927+ expect ( mockBtn . scrollIntoView ) . toHaveBeenCalledWith ( { block : 'nearest' , behavior : 'smooth' } ) ;
928+ } ) ) ;
929+
930+ it ( 'should handle case when container is null' , fakeAsync ( ( ) => {
931+ spyOn ( component [ 'elementRef' ] . nativeElement , 'querySelector' ) . and . returnValue ( null ) ;
932+
933+ component [ 'focusYearButton' ] ( 0 ) ;
934+ tick ( 10 ) ;
935+ } ) ) ;
936+
937+ it ( 'should handle case when buttons array is empty' , fakeAsync ( ( ) => {
938+ const mockContainer = {
939+ querySelectorAll : jasmine . createSpy ( 'querySelectorAll' ) . and . returnValue ( [ ] )
940+ } ;
941+
942+ spyOn ( component [ 'elementRef' ] . nativeElement , 'querySelector' ) . and . returnValue ( mockContainer ) ;
943+
944+ component [ 'focusYearButton' ] ( 5 ) ;
945+ tick ( 10 ) ;
946+ } ) ) ;
947+
948+ it ( 'should handle case when inner button is null' , fakeAsync ( ( ) => {
949+ const mockPoButton = { querySelector : jasmine . createSpy ( 'querySelector' ) . and . returnValue ( null ) } ;
950+ const mockContainer = {
951+ querySelectorAll : jasmine . createSpy ( 'querySelectorAll' ) . and . returnValue ( [ mockPoButton ] )
952+ } ;
953+
954+ spyOn ( component [ 'elementRef' ] . nativeElement , 'querySelector' ) . and . returnValue ( mockContainer ) ;
955+
956+ component [ 'focusYearButton' ] ( 0 ) ;
957+ tick ( 10 ) ;
958+ } ) ) ;
959+ } ) ;
960+
961+ describe ( 'setupMonths:' , ( ) => {
962+ it ( 'should populate displayMonths without setting language when locale is not set' , ( ) => {
963+ component [ '_locale' ] = undefined ;
964+ component [ 'setupMonths' ] ( ) ;
965+ expect ( component . displayMonths . length ) . toBe ( 12 ) ;
966+ } ) ;
967+ } ) ;
968+
969+ describe ( 'setupYears with string minDate/maxDate:' , ( ) => {
970+ it ( 'should handle string minDate by converting to Date' , ( ) => {
971+ const currentYear = new Date ( ) . getFullYear ( ) ;
972+ component . minDate = new Date ( currentYear - 5 , 0 , 1 ) ;
973+ component [ 'setupYears' ] ( ) ;
974+ expect ( component . displayYears [ 0 ] ) . toBe ( currentYear - 5 ) ;
975+ } ) ;
976+
977+ it ( 'should handle string maxDate by converting to Date' , ( ) => {
978+ const currentYear = new Date ( ) . getFullYear ( ) ;
979+ component . maxDate = new Date ( currentYear + 3 , 11 , 31 ) ;
980+ component [ 'setupYears' ] ( ) ;
981+ expect ( component . displayYears [ component . displayYears . length - 1 ] ) . toBe ( currentYear + 3 ) ;
982+ } ) ;
983+
984+ it ( 'should handle non-Date minDate by converting via new Date()' , ( ) => {
985+ const currentYear = new Date ( ) . getFullYear ( ) ;
986+ component . minDate = `${ currentYear - 3 } -01-01` as any ;
987+ component [ 'setupYears' ] ( ) ;
988+ expect ( component . displayYears [ 0 ] ) . toBe ( currentYear - 3 ) ;
989+ } ) ;
990+
991+ it ( 'should handle non-Date maxDate by converting via new Date()' , ( ) => {
992+ const currentYear = new Date ( ) . getFullYear ( ) ;
993+ component . maxDate = `${ currentYear + 2 } -12-31` as any ;
994+ component [ 'setupYears' ] ( ) ;
995+ expect ( component . displayYears [ component . displayYears . length - 1 ] ) . toBe ( currentYear + 2 ) ;
996+ } ) ;
997+ } ) ;
998+
999+ describe ( 'emitSelection edge cases:' , ( ) => {
1000+ it ( 'should not emit in year mode when selectedYear is null' , ( ) => {
1001+ component . mode = 'year' ;
1002+ component . selectedYear = null ;
1003+ spyOn ( component . select , 'emit' ) ;
1004+ component [ 'emitSelection' ] ( ) ;
1005+ expect ( component . select . emit ) . not . toHaveBeenCalled ( ) ;
1006+ } ) ;
1007+
1008+ it ( 'should not emit in year mode when selectedYear is undefined' , ( ) => {
1009+ component . mode = 'year' ;
1010+ component . selectedYear = undefined ;
1011+ spyOn ( component . select , 'emit' ) ;
1012+ component [ 'emitSelection' ] ( ) ;
1013+ expect ( component . select . emit ) . not . toHaveBeenCalled ( ) ;
1014+ } ) ;
1015+ } ) ;
1016+
1017+ describe ( 'navigateMonth edge cases:' , ( ) => {
1018+ it ( 'should skip all disabled months and not navigate if all are disabled' , ( ) => {
1019+ spyOn ( component , 'isMonthDisabled' ) . and . returnValue ( true ) ;
1020+ spyOn ( component as any , 'focusMonthButton' ) ;
1021+ component . focusedMonthIndex = 5 ;
1022+
1023+ component [ 'navigateMonth' ] ( 5 , 1 ) ;
1024+
1025+ expect ( component [ 'focusMonthButton' ] ) . not . toHaveBeenCalled ( ) ;
1026+ } ) ;
1027+ } ) ;
1028+
1029+ describe ( 'navigateYear edge cases:' , ( ) => {
1030+ it ( 'should skip all disabled years and not navigate if all are disabled' , ( ) => {
1031+ spyOn ( component , 'isYearDisabled' ) . and . returnValue ( true ) ;
1032+ spyOn ( component as any , 'focusYearButton' ) ;
1033+ component . focusedYearIndex = 5 ;
1034+
1035+ component [ 'navigateYear' ] ( 5 , 1 ) ;
1036+
1037+ expect ( component [ 'focusYearButton' ] ) . not . toHaveBeenCalled ( ) ;
1038+ } ) ;
1039+ } ) ;
1040+
1041+ describe ( 'onYearKeydown edge cases:' , ( ) => {
1042+ it ( 'should not select year on Space when year is disabled' , ( ) => {
1043+ spyOn ( component , 'isYearDisabled' ) . and . returnValue ( true ) ;
1044+ spyOn ( component , 'onSelectYear' ) ;
1045+ const event = new KeyboardEvent ( 'keydown' , { key : ' ' } ) ;
1046+
1047+ component . onYearKeydown ( event , 5 ) ;
1048+
1049+ expect ( component . onSelectYear ) . not . toHaveBeenCalled ( ) ;
1050+ } ) ;
1051+ } ) ;
1052+
1053+ describe ( 'setInitialFocus edge cases:' , ( ) => {
1054+ it ( 'should handle selectedMonth as negative number' , ( ) => {
1055+ component . selectedMonth = - 1 ;
1056+ component [ 'setInitialFocus' ] ( ) ;
1057+ expect ( component . focusedMonthIndex ) . toBe ( 0 ) ;
1058+ } ) ;
1059+
1060+ it ( 'should handle selectedMonth as 12 (out of range)' , ( ) => {
1061+ component . selectedMonth = 12 ;
1062+ component [ 'setInitialFocus' ] ( ) ;
1063+ expect ( component . focusedMonthIndex ) . toBe ( 0 ) ;
1064+ } ) ;
1065+
1066+ it ( 'should handle selectedYear not in displayYears but currentYear is' , ( ) => {
1067+ const currentYear = new Date ( ) . getFullYear ( ) ;
1068+ component . selectedYear = 1800 ;
1069+ component [ 'setInitialFocus' ] ( ) ;
1070+ const expectedIndex = component . displayYears . indexOf ( currentYear ) ;
1071+ expect ( component . focusedYearIndex ) . toBe ( expectedIndex ) ;
1072+ } ) ;
8301073 } ) ;
8311074 } ) ;
8321075} ) ;
0 commit comments