import React from 'react';
import { cleanup, render, screen } from '@testing-library/react';
import { SideNavItemProps } from './SideNavItem.types';
import { SideNavItem } from '.';
type renderedElement = HTMLElement | null;
interface RenderedElements {
navEl?: renderedElement;
groupEl?: renderedElement;
headerContentEl?: renderedElement;
defaultHeaderEl?: renderedElement;
itemEl?: renderedElement;
childEl?: renderedElement;
}
describe('packages/side-nav', () => {
const testIds = {
sideNav: 'side-nav',
sideNavGroup: 'side-nav-group',
sideNavHeader: 'side-nav-header',
sideNavItem: 'side-nav-item',
sideNavLink: 'side-nav-link',
};
const className = 'test-class-name';
let renderedEls: RenderedElements = {};
afterEach(() => {
document.body.innerHTML = '';
renderedEls = {};
cleanup();
});
describe('SideNavItem', () => {
function renderSideNavItem(props: SideNavItemProps = {}) {
const { sideNavItem, sideNavLink } = testIds;
const { children, ...rest } = props;
const { getByTestId, queryByTestId } = render(
// @ts-ignore React17 types
{children}
,
);
renderedEls.itemEl = getByTestId(sideNavItem);
renderedEls.childEl = queryByTestId(sideNavLink);
}
describe('when rendered with a custom class name', () => {
beforeEach(() => {
renderSideNavItem({ className });
});
test('it renders the item as a button', () => {
expect(renderedEls.itemEl).toBeInTheDocument();
expect(renderedEls.itemEl?.tagName).toEqual('BUTTON');
});
test('it renders with the provided class name', () => {
expect(renderedEls.itemEl).toHaveClass(className);
});
});
describe('when rendered as active', () => {
beforeEach(() => {
renderSideNavItem({ active: true });
});
test('it sets the aria attribute for the active item', () => {
expect(renderedEls.itemEl).toHaveAttribute('aria-current', 'page');
});
});
describe('when rendered as disabled', () => {
beforeEach(() => {
renderSideNavItem({ disabled: true });
});
test('it sets the aria attribute for the disabled item', () => {
expect(renderedEls.itemEl).toHaveAttribute('aria-disabled', 'true');
});
});
describe('when rendered as a link', () => {
beforeEach(() => {
renderSideNavItem({ href: '/v2#' });
});
test('it renders as an link menu item', () => {
expect(renderedEls.itemEl).toBeInTheDocument();
expect(renderedEls.itemEl?.tagName).toEqual('A');
expect(renderedEls.itemEl).toHaveAttribute('href', '/v2#');
});
});
describe('when rendered with children', () => {
beforeEach(() => {
const { sideNavLink } = testIds;
const children = (
Clusters
);
renderSideNavItem({ children });
});
test('it renders the children', () => {
expect(renderedEls.childEl).toBeInTheDocument();
expect(renderedEls.childEl?.tagName).toEqual('A');
expect(renderedEls.childEl).toHaveAttribute('href', '#clusters');
});
});
describe('when rendered with SideNavItems as children', () => {
test('it renders nested SideNavItems when immediate parent is active', () => {
render(
Ancestor
Child 1
,
);
expect(screen.getByText('Child 1')).toBeInTheDocument();
});
test('it only renders nested SideNavItems when direct ancestor is active', () => {
render(
Ancestor
Child 1Child 2
,
);
expect(screen.getByText('Child 1')).toBeInTheDocument();
expect(screen.queryByText('Child 2')).not.toBeInTheDocument();
});
test('it does not render nested SideNavItems when parent is not active', () => {
render(
Ancestor
Child 1
,
);
expect(screen.queryByText('Child 1')).not.toBeInTheDocument();
});
});
describe('when rendered as a custom component', () => {
beforeEach(() => {
interface ImageFigureProps {
imageUrl: string;
imageAlt: string;
caption: string;
}
function ImageFigure({
imageUrl,
imageAlt,
caption,
...rest
}: ImageFigureProps) {
return (
{caption}
);
}
const { sideNavItem } = testIds;
const props = {
as: ImageFigure,
imageUrl: '/dogeSelfPortrait',
imageAlt: 'such wow',
caption: 'such art',
};
const { getByTestId } = render(
,
);
renderedEls.itemEl = getByTestId(sideNavItem);
});
test('it renders as the custom component', () => {
expect(renderedEls.itemEl).toBeInTheDocument();
expect(renderedEls.itemEl?.tagName).toEqual('FIGURE');
const imgEl = renderedEls.itemEl?.querySelector('img');
expect(imgEl).toBeInTheDocument();
expect(imgEl).toHaveAttribute('src', '/dogeSelfPortrait');
expect(imgEl).toHaveAttribute('alt', 'such wow');
const figcaptionEl = renderedEls.itemEl?.querySelector('figcaption');
expect(figcaptionEl).toBeInTheDocument();
expect(figcaptionEl).toHaveTextContent('such art');
});
});
});
});