From 224b1e6615792b9e88440dde0552bb84a5bcf6f2 Mon Sep 17 00:00:00 2001 From: Ashna Thomas Date: Fri, 6 Dec 2024 22:18:43 +0530 Subject: [PATCH] test(SideNav): #17491 increased unit test coverage (#17869) * test(SideNav): carbon-design-system#17491 increased unit test coverage * test(SideNav): carbon-design-system#17491 increased unit test coverage * test(SideNav): increased coverage * Update packages/react/src/components/UIShell/__tests__/SideNav-test.js * Update packages/react/src/components/UIShell/__tests__/SideNav-test.js * Update packages/react/src/components/UIShell/__tests__/SideNav-test.js * fix(test): format --------- Co-authored-by: Ariella Gilmore Co-authored-by: Nikhil Tomar <63502271+2nikhiltom@users.noreply.github.com> --- .all-contributorsrc | 7 + README.md | 3 + .../UIShell/__tests__/SideNav-test.js | 276 +++++++++++++++++- 3 files changed, 283 insertions(+), 3 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index a7cd07aaf96d..3088b1880d80 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1721,6 +1721,13 @@ "name": "Zoë Gathercole", "avatar_url": "https://avatars.githubusercontent.com/u/56911544?v=4", "profile": "https://github.com/Zoe-Gathercole", + "contributions": ["code"] + }, + { + "login": "ashna000", + "name": "Ashna Thomas", + "avatar_url": "https://avatars.githubusercontent.com/u/12691034?s=96&v=4", + "profile": "https://github.com/ashna000", "contributions": [ "code" ] diff --git a/README.md b/README.md index 30d2bfc8a91a..3b7067b4ac91 100644 --- a/README.md +++ b/README.md @@ -321,6 +321,9 @@ check out our [Contributing Guide](/.github/CONTRIBUTING.md) and our
Zoë Gathercole

💻
Zach Tindall

💻 + +
Ashna Thomas

💻 + diff --git a/packages/react/src/components/UIShell/__tests__/SideNav-test.js b/packages/react/src/components/UIShell/__tests__/SideNav-test.js index 02d727ae319d..d3974e5300d4 100644 --- a/packages/react/src/components/UIShell/__tests__/SideNav-test.js +++ b/packages/react/src/components/UIShell/__tests__/SideNav-test.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import { render, screen } from '@testing-library/react'; +import { render, screen, fireEvent } from '@testing-library/react'; import React from 'react'; import SideNav from '../SideNav'; @@ -15,8 +15,8 @@ Object.defineProperty(window, 'matchMedia', { matches: false, media: query, onchange: null, - addListener: jest.fn(), // deprecated - removeListener: jest.fn(), // deprecated + addListener: jest.fn(), + removeListener: jest.fn(), addEventListener: jest.fn(), removeEventListener: jest.fn(), dispatchEvent: jest.fn(), @@ -36,6 +36,11 @@ describe('SideNav', () => { expect(container.childNodes.length).toBe(2); }); + it('should not render an overlay if `isFixedNav` is true', () => { + const { container } = render(); + expect(container.childNodes.length).toBe(1); + }); + it('should toggle the overlay-active class when `expanded` is true', () => { const { container } = render(); expect(container.firstChild).toHaveClass('cds--side-nav__overlay-active'); @@ -64,4 +69,269 @@ describe('SideNav', () => { render(); expect(ref).toHaveBeenCalledWith(screen.getByRole('navigation')); }); + + it('should call onOverlayClick when overlay is clicked', () => { + const onOverlayClick = jest.fn(); + const { container } = render( + + ); + const overlay = container.firstChild; + fireEvent.click(overlay); + expect(onOverlayClick).toHaveBeenCalledTimes(1); + }); + + it('should not add focus or mouse listeners when disabled', () => { + const onToggle = jest.fn(); + render( + + ); + const sideNav = screen.getByRole('navigation'); + fireEvent.focus(sideNav); + fireEvent.mouseEnter(sideNav); + expect(onToggle).not.toHaveBeenCalled(); + }); + + it('should handle keyboard events like Escape', () => { + const onToggle = jest.fn(); + render( + + ); + const sideNav = screen.getByRole('navigation'); + fireEvent.keyDown(sideNav, { key: 'Escape', keyCode: 27 }); + expect(onToggle).toHaveBeenCalledWith(expect.anything(), false); + }); + + it('should correctly handle `isRail` when true', () => { + render(); + const sideNav = screen.getByRole('navigation'); + expect(sideNav).toHaveClass('cds--side-nav--rail'); + }); + + it('should correctly handle `isRail` when false', () => { + render(); + const sideNav = screen.getByRole('navigation'); + expect(sideNav).not.toHaveClass('cds--side-nav--rail'); + }); + + it('should toggle the expanded state when uncontrolled', () => { + const { container } = render(); + const sideNav = screen.getByRole('navigation'); + fireEvent.focus(sideNav); + expect(container.firstChild).toHaveClass('cds--side-nav__overlay'); + }); + + it('should handle children without throwing error', () => { + const { container } = render( + +
No Errors Here!
+
+ ); + expect(container).toBeInTheDocument(); + }); + + it('should pass isSideNavExpanded to Carbon SideNav children', () => { + const TestChild = React.forwardRef(({ isSideNavExpanded }, ref) => ( +
+ {isSideNavExpanded ? 'Expanded' : 'Collapsed'} +
+ )); + render( + + + + ); + expect(screen.getByTestId('child')).toHaveTextContent('Collapsed'); + }); + + it('should not pass isSideNavExpanded to non-CarbsideNav children', () => { + const NonCarbonChild = () =>
; + render( + + + + ); + expect(screen.getByTestId('non-carbon-child')).toBeInTheDocument(); + }); + + it('should pass isSideNavExpanded correctly based on controlled state', () => { + const TestChild = React.forwardRef(({ isSideNavExpanded }, ref) => ( +
+ {isSideNavExpanded ? 'Expanded' : 'Collapsed'} +
+ )); + const { rerender } = render( + + + + ); + expect(screen.getByTestId('child')).toHaveTextContent('Collapsed'); + rerender( + + + + ); + expect(screen.getByTestId('child')).toHaveTextContent('Collapsed'); + }); + + it('should call handleToggle and onSideNavBlur when blurred', () => { + const onSideNavBlurMock = jest.fn(); + const TestChild = () =>
Child
; + const { getByRole } = render( + + + + ); + const sideNav = getByRole('navigation'); + fireEvent.focus(sideNav); + fireEvent.blur(sideNav); + expect(onSideNavBlurMock).not.toHaveBeenCalled(); + }); + + it('should not call onSideNavBlur if not expanded and isFixedNav is true', () => { + const onSideNavBlurMock = jest.fn(); + const TestChild = () =>
Child
; + const { getByRole } = render( + + + + ); + const sideNav = getByRole('navigation'); + fireEvent.focus(sideNav); + fireEvent.blur(sideNav); + expect(onSideNavBlurMock).not.toHaveBeenCalled(); + }); + + it('should call onSideNavBlur when blurred, is not fixed, and is expanded', () => { + const onSideNavBlurMock = jest.fn(); + const TestChild = () =>
Child
; + const { getByRole } = render( + + + + ); + const sideNav = getByRole('navigation'); + fireEvent.focus(sideNav); + const unrelatedElement = document.createElement('div'); + document.body.appendChild(unrelatedElement); + fireEvent.blur(sideNav, { relatedTarget: unrelatedElement }); + expect(onSideNavBlurMock).toHaveBeenCalled(); + document.body.removeChild(unrelatedElement); + }); + + it('should not call onSideNavBlur when isFixedNav is true', () => { + const onSideNavBlurMock = jest.fn(); + const TestChild = () =>
Child
; + const { getByRole } = render( + + + + ); + const sideNav = getByRole('navigation'); + fireEvent.focus(sideNav); + const unrelatedElement = document.createElement('div'); + document.body.appendChild(unrelatedElement); + fireEvent.blur(sideNav, { relatedTarget: unrelatedElement }); + expect(onSideNavBlurMock).not.toHaveBeenCalled(); + document.body.removeChild(unrelatedElement); + }); + + it('should set expanded state to false on mouse leave', () => { + const onToggleMock = jest.fn(); + const TestChild = () =>
Child
; + const { getByRole } = render( + + + + ); + const sideNav = getByRole('navigation'); + expect(sideNav).toHaveClass('cds--side-nav__navigation'); + fireEvent.mouseLeave(sideNav); + expect(sideNav).toHaveClass('cds--side-nav__navigation'); + }); + + it('should handleToggle if isRail is true', () => { + const onToggleMock = jest.fn(); + const TestChild = () =>
Child
; + const { getByRole } = render( + + + + ); + const sideNav = getByRole('navigation'); + fireEvent.focus(sideNav); + expect(onToggleMock).toHaveBeenCalled(); + fireEvent.mouseLeave(sideNav); + expect(onToggleMock).toHaveBeenCalledWith(false, false); + fireEvent.mouseEnter(sideNav); + expect(onToggleMock).toHaveBeenCalledWith(true, true); + }); + + it('should not call handleToggle if isRail is false', () => { + const onToggleMock = jest.fn(); + const TestChild = () =>
Child
; + const { getByRole } = render( + + + + ); + const sideNav = getByRole('navigation'); + fireEvent.mouseLeave(sideNav); + expect(onToggleMock).not.toHaveBeenCalled(); + }); + + it('should expand the SideNav immediately on click', () => { + const TestChild = () =>
Child
; + const onToggleMock = jest.fn(); + const { getByRole } = render( + + + + ); + const sideNav = getByRole('navigation'); + expect(sideNav).not.toHaveClass('cds--side-nav--expanded'); + fireEvent.click(sideNav); + expect(onToggleMock).toHaveBeenCalledWith(true, true); + expect(sideNav).toHaveClass('cds--side-nav--expanded'); + }); + + it('should focus SideNav after tabbing from headerMenuButton', () => { + render( + <> + + + + ); + const mockHeaderMenuButton = screen.getByRole('button'); + const sideNav = screen.getByRole('navigation'); + + mockHeaderMenuButton.focus(); + fireEvent.keyDown(window, { key: 'Tab' }); + expect(document.activeElement).toBe(sideNav); + }); });