Skip to content

Commit

Permalink
feat(header): L3-4484 added tests
Browse files Browse the repository at this point in the history
  • Loading branch information
constantinehuzenko committed Nov 8, 2024
1 parent 4d26986 commit 498b7e0
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 8 deletions.
22 changes: 22 additions & 0 deletions src/components/Navigation/NavigationItem/NavigationItem.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { render, screen } from '@testing-library/react';
import NavigationItem from './NavigationItem';
import { HeaderContext } from '../../../site-furniture/Header/Header';
import userEvent from '@testing-library/user-event';
import { defaultHeaderContext } from '../../../site-furniture/Header/utils';

describe('NavigationItem', () => {
it('renders the navigation item correctly', () => {
Expand All @@ -25,4 +28,23 @@ describe('NavigationItem', () => {
expect(navigationItem).toBeInTheDocument();
expect(navigationItem).toHaveClass('custom-class');
});

it('calls closeMenu, closeSubmenu, and onClick when clicked', async () => {
const closeMenu = vi.fn();
const closeSubmenu = vi.fn();
const onClick = vi.fn();

render(
<HeaderContext.Provider value={{ ...defaultHeaderContext, closeMenu }}>
<NavigationItem href="/" label="Home" closeSubmenu={closeSubmenu} onClick={onClick} />
</HeaderContext.Provider>,
);

const navigationItem = screen.getByTestId('nav-item-Home');
await userEvent.click(navigationItem);

expect(closeMenu).toHaveBeenCalled();
expect(closeSubmenu).toHaveBeenCalled();
expect(onClick).toHaveBeenCalled();
});
});
10 changes: 10 additions & 0 deletions src/patterns/LanguageSelector/LanguageSelector.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { runCommonTests } from '../../utils/testUtils';
import { SupportedLanguages } from '../../types/commonTypes';
import userEvent from '@testing-library/user-event';
import { render, screen } from '@testing-library/react';
import { getLanguageLabel } from './utils';

describe('LanguageSelector', () => {
runCommonTests(LanguageSelector, 'LanguageSelector');
Expand Down Expand Up @@ -58,3 +59,12 @@ describe('LanguageSelector', () => {
expect(onLanguageChange).toHaveBeenCalledWith('en');
});
});

test('getLanguageLabel', () => {
const languageOptions: LanguageOption[] = [
{ label: 'English', value: SupportedLanguages.en },
{ label: '中文', value: SupportedLanguages.zh },
];
const currentLanguage = SupportedLanguages.zh;
expect(getLanguageLabel({ languageOptions, currentLanguage })).toBe('中文');
});
3 changes: 2 additions & 1 deletion src/patterns/LanguageSelector/LanguageSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { LinkVariants } from '../../components/Link';
import { Text, TextVariants } from '../../components/Text';
import NavigationList from '../../components/Navigation/NavigationList/NavigationList';
import { SSRMediaQuery } from '../../providers/SeldonProvider/utils';
import { getLanguageLabel } from './utils';

interface DropdownSelectorProps extends ComponentProps<'div'> {
value: string;
Expand Down Expand Up @@ -95,7 +96,7 @@ const LanguageSelector = forwardRef<HTMLElement, LanguageSelectorProps>(
ref,
) => {
const { className: baseClassName, ...commonProps } = getCommonProps({ id }, 'LanguageSelector');
const languageLabel = languageOptions.find((option) => option.value === currentLanguage)?.label ?? 'English';
const languageLabel = getLanguageLabel({ languageOptions, currentLanguage });

const selectorProps = {
...commonProps,
Expand Down
9 changes: 9 additions & 0 deletions src/patterns/LanguageSelector/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { LanguageSelectorProps } from './LanguageSelector';

interface GetLanguageLabelProps {
languageOptions: LanguageSelectorProps['languageOptions'];
currentLanguage: LanguageSelectorProps['currentLanguage'];
}

export const getLanguageLabel = ({ languageOptions, currentLanguage }: GetLanguageLabelProps) =>
languageOptions?.find((option) => option.value === currentLanguage)?.label ?? 'English';
45 changes: 44 additions & 1 deletion src/site-furniture/Header/Header.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { render, screen } from '@testing-library/react';
import { act, render, renderHook, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import Header from './Header';
import LogoSVG from '../../assets/PhillipsLogo.svg?react';
Expand All @@ -10,6 +10,7 @@ import NavigationItemTrigger from '../../components/Navigation/NavigationItemTri
import NavigationList from '../../components/Navigation/NavigationList/NavigationList';
import { LinkVariants } from '../../components/Link/types';
import Search from '../../components/Search/Search';
import { useMobileMenu } from './hooks';

describe('Header', () => {
const headerComponent = () => (
Expand Down Expand Up @@ -78,3 +79,45 @@ describe('Header with logo', () => {
expect(logoElement).toContainHTML(`<img alt="Phillips" data-testid="header-logo-img" src=${LogoIMG} />`);
});
});

describe('useMobileMenu', () => {
const toggleCloseText = 'Close Menu';
const toggleOpenText = 'Open Menu';

it('should initialize with menu closed', () => {
const { result } = renderHook(() => useMobileMenu({ toggleCloseText, toggleOpenText }));
expect(result.current.isMenuOpen).toBe(false);
expect(result.current.toggleText).toBe(toggleOpenText);
});

it('should toggle menu open and close', () => {
const { result } = renderHook(() => useMobileMenu({ toggleCloseText, toggleOpenText }));

act(() => {
result.current.handleMenuToggle();
});
expect(result.current.isMenuOpen).toBe(true);
expect(result.current.toggleText).toBe(toggleCloseText);

act(() => {
result.current.handleMenuToggle();
});
expect(result.current.isMenuOpen).toBe(false);
expect(result.current.toggleText).toBe(toggleOpenText);
});

it('should close menu when closeMenu is called', () => {
const { result } = renderHook(() => useMobileMenu({ toggleCloseText, toggleOpenText }));

act(() => {
result.current.handleMenuToggle();
});
expect(result.current.isMenuOpen).toBe(true);

act(() => {
result.current.closeMenu();
});
expect(result.current.isMenuOpen).toBe(false);
expect(result.current.toggleText).toBe(toggleOpenText);
});
});
8 changes: 2 additions & 6 deletions src/site-furniture/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import Navigation from '../../components/Navigation/Navigation';
import { Component, ComponentProps, forwardRef, ReactElement, useState, createContext } from 'react';
import { defaultHeaderContext } from './utils';
import { SSRMediaQuery } from '../../providers/SeldonProvider/utils';
import { useMobileMenu } from './hooks';

export interface HeaderProps extends ComponentProps<'header'> {
/**
Expand Down Expand Up @@ -82,12 +83,7 @@ const Header = forwardRef<HTMLElement, HeaderProps>(
const [isSearchExpanded, setIsSearchExpanded] = useState(false);
const navigationElement = findChildrenOfType(children, Navigation);
const otherChildren = findChildrenExcludingTypes(children, [Navigation, UserManagement, LanguageSelector]);
const [isMenuOpen, setIsMenuOpen] = useState(false);
const toggleText = isMenuOpen ? toggleCloseText : toggleOpenText;
const handleMenuToggle = function () {
setIsMenuOpen((prev) => !prev);
};
const closeMenu = () => setIsMenuOpen(false);
const { closeMenu, handleMenuToggle, isMenuOpen, toggleText } = useMobileMenu({ toggleOpenText, toggleCloseText });

return (
<header {...props} className={classnames(`${px}-header`, className)} ref={ref}>
Expand Down
12 changes: 12 additions & 0 deletions src/site-furniture/Header/hooks.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { useState } from 'react';
import { HeaderProps } from './Header';

type UseMobileMenuProps = Pick<HeaderProps, 'toggleCloseText' | 'toggleOpenText'>;

export const useMobileMenu = ({ toggleCloseText, toggleOpenText }: UseMobileMenuProps) => {
const [isMenuOpen, setIsMenuOpen] = useState(false);
const handleMenuToggle = () => setIsMenuOpen((prev) => !prev);
const closeMenu = () => setIsMenuOpen(false);
const toggleText = isMenuOpen ? toggleCloseText : toggleOpenText;
return { isMenuOpen, handleMenuToggle, closeMenu, toggleText };
};
1 change: 1 addition & 0 deletions src/site-furniture/Header/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ export const defaultHeaderContext: HeaderContextType = {
isMenuOpen: false,
isSearchExpanded: false,
setIsSearchExpanded: noOp,
closeMenu: noOp,
};

0 comments on commit 498b7e0

Please sign in to comment.