@@ -514,11 +514,223 @@ describe('NavOverflow', () => {
514514
515515 it ( 'should have correct DefaultType' , ( ) => {
516516 expect ( NavOverflow . DefaultType ) . toEqual ( jasmine . objectContaining ( {
517+ collapseBelow : '(number|string)' ,
518+ iconPlacement : 'string' ,
519+ menuPlacement : 'string' ,
517520 moreText : 'string' ,
518521 moreIcon : 'string' ,
519522 threshold : 'number'
520523 } ) )
521524 } )
525+
526+ it ( 'should respect custom menuPlacement option' , ( ) => {
527+ fixtureEl . innerHTML = [
528+ '<ul class="nav" data-bs-toggle="nav-overflow">' ,
529+ ' <li class="nav-item"><a class="nav-link" href="#">Link 1</a></li>' ,
530+ '</ul>'
531+ ] . join ( '' )
532+
533+ const navEl = fixtureEl . querySelector ( '[data-bs-toggle="nav-overflow"]' )
534+ const navOverflow = new NavOverflow ( navEl , {
535+ menuPlacement : 'bottom-start'
536+ } )
537+
538+ const toggle = navEl . querySelector ( '.nav-overflow-toggle' )
539+ expect ( toggle . getAttribute ( 'data-bs-placement' ) ) . toEqual ( 'bottom-start' )
540+
541+ navOverflow . dispose ( )
542+ } )
543+
544+ it ( 'should use a child element with [data-bs-overflow-icon] as the icon' , ( ) => {
545+ fixtureEl . innerHTML = [
546+ '<ul class="nav" data-bs-toggle="nav-overflow">' ,
547+ ' <li class="nav-item"><a class="nav-link" href="#">Link 1</a></li>' ,
548+ ' <svg data-bs-overflow-icon class="bi-chevron" width="16" height="16"><circle cx="8" cy="8" r="8"/></svg>' ,
549+ '</ul>'
550+ ] . join ( '' )
551+
552+ const navEl = fixtureEl . querySelector ( '[data-bs-toggle="nav-overflow"]' )
553+ const navOverflow = new NavOverflow ( navEl )
554+
555+ const iconContainer = navEl . querySelector ( '.nav-overflow-icon' )
556+ const svg = iconContainer . querySelector ( 'svg' )
557+ expect ( svg ) . not . toBeNull ( )
558+ expect ( svg ) . toHaveClass ( 'bi-chevron' )
559+ expect ( svg . hasAttribute ( 'data-bs-overflow-icon' ) ) . toBeFalse ( )
560+
561+ // Original element should be removed from the nav
562+ expect ( navEl . querySelector ( '[data-bs-overflow-icon]' ) ) . toBeNull ( )
563+
564+ navOverflow . dispose ( )
565+ } )
566+
567+ it ( 'should prefer child [data-bs-overflow-icon] over moreIcon config' , ( ) => {
568+ fixtureEl . innerHTML = [
569+ '<ul class="nav" data-bs-toggle="nav-overflow">' ,
570+ ' <li class="nav-item"><a class="nav-link" href="#">Link 1</a></li>' ,
571+ ' <svg data-bs-overflow-icon class="from-markup" width="16" height="16"><circle cx="8" cy="8" r="8"/></svg>' ,
572+ '</ul>'
573+ ] . join ( '' )
574+
575+ const navEl = fixtureEl . querySelector ( '[data-bs-toggle="nav-overflow"]' )
576+ const navOverflow = new NavOverflow ( navEl , {
577+ moreIcon : '<span class="from-config">X</span>'
578+ } )
579+
580+ const iconContainer = navEl . querySelector ( '.nav-overflow-icon' )
581+ expect ( iconContainer . querySelector ( '.from-markup' ) ) . not . toBeNull ( )
582+ expect ( iconContainer . querySelector ( '.from-config' ) ) . toBeNull ( )
583+
584+ navOverflow . dispose ( )
585+ } )
586+
587+ it ( 'should place icon after text when iconPlacement is "end"' , ( ) => {
588+ fixtureEl . innerHTML = [
589+ '<ul class="nav" data-bs-toggle="nav-overflow">' ,
590+ ' <li class="nav-item"><a class="nav-link" href="#">Link 1</a></li>' ,
591+ '</ul>'
592+ ] . join ( '' )
593+
594+ const navEl = fixtureEl . querySelector ( '[data-bs-toggle="nav-overflow"]' )
595+ const navOverflow = new NavOverflow ( navEl , {
596+ iconPlacement : 'end'
597+ } )
598+
599+ const toggle = navEl . querySelector ( '.nav-overflow-toggle' )
600+ const children = [ ...toggle . children ]
601+ const textIndex = children . findIndex ( el => el . classList . contains ( 'nav-overflow-text' ) )
602+ const iconIndex = children . findIndex ( el => el . classList . contains ( 'nav-overflow-icon' ) )
603+
604+ expect ( textIndex ) . toBeLessThan ( iconIndex )
605+
606+ navOverflow . dispose ( )
607+ } )
608+
609+ it ( 'should place icon before text by default (iconPlacement "start")' , ( ) => {
610+ fixtureEl . innerHTML = [
611+ '<ul class="nav" data-bs-toggle="nav-overflow">' ,
612+ ' <li class="nav-item"><a class="nav-link" href="#">Link 1</a></li>' ,
613+ '</ul>'
614+ ] . join ( '' )
615+
616+ const navEl = fixtureEl . querySelector ( '[data-bs-toggle="nav-overflow"]' )
617+ const navOverflow = new NavOverflow ( navEl )
618+
619+ const toggle = navEl . querySelector ( '.nav-overflow-toggle' )
620+ const children = [ ...toggle . children ]
621+ const textIndex = children . findIndex ( el => el . classList . contains ( 'nav-overflow-text' ) )
622+ const iconIndex = children . findIndex ( el => el . classList . contains ( 'nav-overflow-icon' ) )
623+
624+ expect ( iconIndex ) . toBeLessThan ( textIndex )
625+
626+ navOverflow . dispose ( )
627+ } )
628+ } )
629+
630+ describe ( 'collapseBelow' , ( ) => {
631+ it ( 'should collapse all items when nav width is below collapseBelow (number)' , ( ) => {
632+ fixtureEl . innerHTML = [
633+ '<ul class="nav" style="display: flex; width: 400px;" data-bs-toggle="nav-overflow">' ,
634+ ' <li class="nav-item" style="flex: 0 0 50px; width: 50px;"><a class="nav-link" href="#">Link 1</a></li>' ,
635+ ' <li class="nav-item" style="flex: 0 0 50px; width: 50px;"><a class="nav-link" href="#">Link 2</a></li>' ,
636+ ' <li class="nav-item" style="flex: 0 0 50px; width: 50px;"><a class="nav-link" href="#">Link 3</a></li>' ,
637+ '</ul>'
638+ ] . join ( '' )
639+
640+ const navEl = fixtureEl . querySelector ( '[data-bs-toggle="nav-overflow"]' )
641+ const navOverflow = new NavOverflow ( navEl , {
642+ collapseBelow : 500
643+ } )
644+
645+ const hiddenItems = navEl . querySelectorAll ( '.nav-item[data-bs-nav-overflow="true"]' )
646+ expect ( hiddenItems . length ) . toEqual ( 3 )
647+
648+ navOverflow . dispose ( )
649+ } )
650+
651+ it ( 'should not collapse items when nav width is above collapseBelow (number)' , ( ) => {
652+ fixtureEl . innerHTML = [
653+ '<ul class="nav" style="display: flex; width: 5000px;" data-bs-toggle="nav-overflow">' ,
654+ ' <li class="nav-item" style="flex: 0 0 50px; width: 50px;"><a class="nav-link" href="#">Link 1</a></li>' ,
655+ ' <li class="nav-item" style="flex: 0 0 50px; width: 50px;"><a class="nav-link" href="#">Link 2</a></li>' ,
656+ ' <li class="nav-item" style="flex: 0 0 50px; width: 50px;"><a class="nav-link" href="#">Link 3</a></li>' ,
657+ '</ul>'
658+ ] . join ( '' )
659+
660+ const navEl = fixtureEl . querySelector ( '[data-bs-toggle="nav-overflow"]' )
661+ const navOverflow = new NavOverflow ( navEl , {
662+ collapseBelow : 500
663+ } )
664+
665+ const hiddenItems = navEl . querySelectorAll ( '.nav-item[data-bs-nav-overflow="true"]' )
666+ expect ( hiddenItems . length ) . toEqual ( 0 )
667+
668+ navOverflow . dispose ( )
669+ } )
670+
671+ it ( 'should resolve a breakpoint string via --bs-breakpoint-{name} CSS variable' , ( ) => {
672+ document . documentElement . style . setProperty ( '--bs-breakpoint-md' , '768px' )
673+
674+ fixtureEl . innerHTML = [
675+ '<ul class="nav" style="display: flex; width: 400px;" data-bs-toggle="nav-overflow">' ,
676+ ' <li class="nav-item" style="flex: 0 0 50px; width: 50px;"><a class="nav-link" href="#">Link 1</a></li>' ,
677+ ' <li class="nav-item" style="flex: 0 0 50px; width: 50px;"><a class="nav-link" href="#">Link 2</a></li>' ,
678+ '</ul>'
679+ ] . join ( '' )
680+
681+ const navEl = fixtureEl . querySelector ( '[data-bs-toggle="nav-overflow"]' )
682+ const navOverflow = new NavOverflow ( navEl , {
683+ collapseBelow : 'md'
684+ } )
685+
686+ const hiddenItems = navEl . querySelectorAll ( '.nav-item[data-bs-nav-overflow="true"]' )
687+ expect ( hiddenItems . length ) . toEqual ( 2 )
688+
689+ navOverflow . dispose ( )
690+ document . documentElement . style . removeProperty ( '--bs-breakpoint-md' )
691+ } )
692+
693+ it ( 'should respect nav-overflow-keep items when collapsing all' , ( ) => {
694+ fixtureEl . innerHTML = [
695+ '<ul class="nav" style="display: flex; width: 400px;" data-bs-toggle="nav-overflow">' ,
696+ ' <li class="nav-item nav-overflow-keep" style="flex: 0 0 50px; width: 50px;"><a class="nav-link" href="#">Keep</a></li>' ,
697+ ' <li class="nav-item" style="flex: 0 0 50px; width: 50px;"><a class="nav-link" href="#">Link 2</a></li>' ,
698+ ' <li class="nav-item" style="flex: 0 0 50px; width: 50px;"><a class="nav-link" href="#">Link 3</a></li>' ,
699+ '</ul>'
700+ ] . join ( '' )
701+
702+ const navEl = fixtureEl . querySelector ( '[data-bs-toggle="nav-overflow"]' )
703+ const navOverflow = new NavOverflow ( navEl , {
704+ collapseBelow : 500
705+ } )
706+
707+ const keepItem = navEl . querySelector ( '.nav-overflow-keep' )
708+ expect ( keepItem ) . not . toHaveClass ( 'd-none' )
709+
710+ const hiddenItems = navEl . querySelectorAll ( '.nav-item[data-bs-nav-overflow="true"]' )
711+ expect ( hiddenItems . length ) . toEqual ( 2 )
712+
713+ navOverflow . dispose ( )
714+ } )
715+
716+ it ( 'should be disabled by default (collapseBelow: 0)' , ( ) => {
717+ fixtureEl . innerHTML = [
718+ '<ul class="nav" style="display: flex; width: 5000px;" data-bs-toggle="nav-overflow">' ,
719+ ' <li class="nav-item" style="flex: 0 0 50px; width: 50px;"><a class="nav-link" href="#">Link 1</a></li>' ,
720+ ' <li class="nav-item" style="flex: 0 0 50px; width: 50px;"><a class="nav-link" href="#">Link 2</a></li>' ,
721+ '</ul>'
722+ ] . join ( '' )
723+
724+ const navEl = fixtureEl . querySelector ( '[data-bs-toggle="nav-overflow"]' )
725+ const navOverflow = new NavOverflow ( navEl )
726+
727+ expect ( navOverflow . _collapseBelow ) . toEqual ( 0 )
728+
729+ const overflowItem = navEl . querySelector ( '.nav-overflow-item' )
730+ expect ( overflowItem ) . toHaveClass ( 'd-none' )
731+
732+ navOverflow . dispose ( )
733+ } )
522734 } )
523735
524736 describe ( 'dispose' , ( ) => {
0 commit comments