import { mount , ReactWrapper } from 'enzyme' ; import React from 'react' ; import { BehaviorSubject } from 'rxjs' ; import sinon from 'sinon' ; import { StubBrowserStorage } from 'test_utils/stub_browser_storage' ; import { ChromeNavLink , DEFAULT_APP_CATEGORIES } from '../../..' ; import { httpServiceMock } from '../../../http/http_service.mock' ; import { ChromeRecentlyAccessedHistoryItem } from '../../recently_accessed' ; import { CollapsibleNav } from './collapsible_nav' ; jest . mock ( '@elastic/eui/lib/services/accessibility/html_id_generator' , ( ) => ( { htmlIdGenerator : ( ) => ( ) => 'mockId' , } ) ) ; const { opensearchDashboards , observability , security , management } = DEFAULT_APP_CATEGORIES ; function mockLink ( { title = 'discover' , category } ) { return { title , category , id : title , href : title , baseUrl : '/' , isActive : true , 'data-test-subj' : title , } ; } function mockRecentNavLink ( { label = 'recent' } ) { return { label , link : label , id : label , } ; } function mockProps ( ) { return { appId$ : new BehaviorSubject ( 'test' ) , basePath : httpServiceMock . createSetupContract ( { basePath : '/test' } ) . basePath , id : 'collapsibe-nav' , isLocked : false , isNavOpen : false , homeHref : '/' , navLinks$ : new BehaviorSubject ( [ ] ) , recentlyAccessed$ : new BehaviorSubject ( [ ] ) , storage : new StubBrowserStorage ( ) , onIsLockedUpdate : ( ) => { } , closeNav : ( ) => { } , navigateToApp : ( ) => Promise . resolve ( ) , navigateToUrl : ( ) => Promise . resolve ( ) , customNavLink$ : new BehaviorSubject ( undefined ) , branding : { darkMode : false , mark : { defaultUrl : '/defaultModeLogo' , darkModeUrl : '/darkModeLogo' , } , } , } ; } function expectShownNavLinksCount ( component , count ) { expect ( component . find ( '.euiAccordion-isOpen a[data-test-subj^="collapsibleNavAppLink"]' ) . length ) . toEqual ( count ) ; } function expectNavIsClosed ( component ) { expectShownNavLinksCount ( component , 0 ) ; } function clickGroup ( component , group ) { component . find ( `[data-test-subj="collapsibleNavGroup-${ group }"] button` ) . simulate ( 'click' ) ; } describe ( 'CollapsibleNav' , ( ) => { it ( 'renders the default nav' , ( ) => { const onLock = sinon . spy ( ) ; const component = mount ( < CollapsibleNav { ... mockProps ( ) } onIsLockedUpdate = { onLock } / > ) ; expect ( component ) . toMatchSnapshot ( ) ; component . setProps ( { isOpen : true } ) ; expect ( component ) . toMatchSnapshot ( ) ; component . setProps ( { isLocked : true } ) ; expect ( component ) . toMatchSnapshot ( ) ; component . find ( 'button[data-test-subj="collapsible-nav-lock"]' ) . simulate ( 'click' ) ; expect ( onLock . callCount ) . toEqual ( 1 ) ; } ) ; it ( 'renders links grouped by category' , ( ) => { const navLinks = [ mockLink ( { title : 'discover' , category : opensearchDashboards } ) , mockLink ( { title : 'siem' , category : security } ) , mockLink ( { title : 'metrics' , category : observability } ) , mockLink ( { title : 'monitoring' , category : management } ) , mockLink ( { title : 'visualize' , category : opensearchDashboards } ) , mockLink ( { title : 'dashboard' , category : opensearchDashboards } ) , mockLink ( { title : 'canvas' } ) , mockLink ( { title : 'logs' , category : observability } ) , ] ; const recentNavLinks = [ mockRecentNavLink ( { label : 'recent 1' } ) , mockRecentNavLink ( { label : 'recent 2' } ) , ] ; const customNavLink = mockLink ( { title : 'Custom link' } ) ; const component = mount ( < CollapsibleNav { ... mockProps ( ) } isNavOpen = { true } navLinks$ = { new BehaviorSubject ( navLinks ) } recentlyAccessed$ = { new BehaviorSubject ( recentNavLinks ) } customNavLink$ = { new BehaviorSubject ( customNavLink ) } / > ) ; expect ( component ) . toMatchSnapshot ( ) ; } ) ; it ( 'remembers collapsible section state' , ( ) => { const navLinks = [ mockLink ( { category : opensearchDashboards } ) , mockLink ( { category : observability } ) , ] ; const recentNavLinks = [ mockRecentNavLink ( { } ) ] ; const component = mount ( < CollapsibleNav { ... mockProps ( ) } isNavOpen = { true } navLinks$ = { new BehaviorSubject ( navLinks ) } recentlyAccessed$ = { new BehaviorSubject ( recentNavLinks ) } / > ) ; expectShownNavLinksCount ( component , 3 ) ; clickGroup ( component , 'opensearchDashboards' ) ; clickGroup ( component , 'recentlyViewed' ) ; expectShownNavLinksCount ( component , 1 ) ; component . setProps ( { isNavOpen : false } ) ; expectNavIsClosed ( component ) ; component . setProps ( { isNavOpen : true } ) ; expectShownNavLinksCount ( component , 1 ) ; } ) ; it ( 'closes the nav after clicking a link' , ( ) => { const onClose = sinon . spy ( ) ; const navLinks = [ mockLink ( { category : opensearchDashboards } ) , mockLink ( { title : 'categoryless' } ) , ] ; const recentNavLinks = [ mockRecentNavLink ( { } ) ] ; const component = mount ( < CollapsibleNav { ... mockProps ( ) } isNavOpen = { true } navLinks$ = { new BehaviorSubject ( navLinks ) } recentlyAccessed$ = { new BehaviorSubject ( recentNavLinks ) } / > ) ; component . setProps ( { closeNav : ( ) => { component . setProps ( { isNavOpen : false } ) ; onClose ( ) ; } , } ) ; component . find ( '[data-test-subj="collapsibleNavGroup-recentlyViewed"] a' ) . simulate ( 'click' ) ; expect ( onClose . callCount ) . toEqual ( 1 ) ; expectNavIsClosed ( component ) ; component . setProps ( { isNavOpen : true } ) ; component . find ( '[data-test-subj="collapsibleNavGroup-opensearchDashboards"] a' ) . simulate ( 'click' ) ; expect ( onClose . callCount ) . toEqual ( 2 ) ; expectNavIsClosed ( component ) ; component . setProps ( { isNavOpen : true } ) ; component . find ( '[data-test-subj="collapsibleNavGroup-noCategory"] a' ) . simulate ( 'click' ) ; expect ( onClose . callCount ) . toEqual ( 3 ) ; expectNavIsClosed ( component ) ; } ) ; it ( 'renders the nav bar with custom logo in default mode' , ( ) => { const navLinks = [ mockLink ( { category : opensearchDashboards } ) , mockLink ( { category : observability } ) , ] ; const recentNavLinks = [ mockRecentNavLink ( { } ) ] ; const component = mount ( < CollapsibleNav { ... mockProps ( ) } isNavOpen = { true } navLinks$ = { new BehaviorSubject ( navLinks ) } recentlyAccessed$ = { new BehaviorSubject ( recentNavLinks ) } / > ) ; expect ( component ) . toMatchSnapshot ( ) ; component . setProps ( { branding : { darkMode : false , mark : { } , } , } ) ; expect ( component ) . toMatchSnapshot ( ) ; } ) ; it ( 'renders the nav bar with custom logo in dark mode' , ( ) => { const navLinks = [ mockLink ( { category : opensearchDashboards } ) , mockLink ( { category : observability } ) , ] ; const recentNavLinks = [ mockRecentNavLink ( { } ) ] ; const component = mount ( < CollapsibleNav { ... mockProps ( ) } isNavOpen = { true } navLinks$ = { new BehaviorSubject ( navLinks ) } recentlyAccessed$ = { new BehaviorSubject ( recentNavLinks ) } / > ) ; component . setProps ( { branding : { darkMode : true , mark : { defaultUrl : '/defaultModeLogo' , darkModeUrl : '/darkModeLogo' , } , } , } ) ; expect ( component ) . toMatchSnapshot ( ) ; component . setProps ( { branding : { darkMode : true , mark : { defaultUrl : '/defaultModeLogo' , } , } , } ) ; expect ( component ) . toMatchSnapshot ( ) ; component . setProps ( { branding : { darkMode : false , mark : { } , } , } ) ; expect ( component ) . toMatchSnapshot ( ) ; } ) ; } ) ;