mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Sidemenu: Refactor SideMenuDropDown (#38554)
* SideMenuDropDown: Refactor to be more component-ey + rewrite tests in RTL * SideMenuDropDown: Rename childLinks -> items * Rename mockChildLinks -> mockItems as well
This commit is contained in:
parent
b231afd50f
commit
a583f7e160
@ -1,50 +1,51 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from 'enzyme';
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import userEvent from '@testing-library/user-event';
|
||||||
|
import { BrowserRouter } from 'react-router-dom';
|
||||||
import SideMenuDropDown from './SideMenuDropDown';
|
import SideMenuDropDown from './SideMenuDropDown';
|
||||||
|
|
||||||
const setup = (propOverrides?: object) => {
|
describe('SideMenuDropDown', () => {
|
||||||
const props = Object.assign(
|
const mockHeaderText = 'MyHeaderText';
|
||||||
|
const mockHeaderUrl = '/route';
|
||||||
|
const mockOnHeaderClick = jest.fn();
|
||||||
|
const mockItems = [
|
||||||
{
|
{
|
||||||
link: {
|
text: 'First link',
|
||||||
text: 'link',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
propOverrides
|
{
|
||||||
);
|
text: 'Second link',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
return shallow(<SideMenuDropDown {...props} />);
|
it('displays the header text', () => {
|
||||||
};
|
render(<SideMenuDropDown headerText={mockHeaderText} />);
|
||||||
|
const text = screen.getByText(mockHeaderText);
|
||||||
describe('Render', () => {
|
expect(text).toBeInTheDocument();
|
||||||
it('should render component', () => {
|
|
||||||
const wrapper = setup();
|
|
||||||
|
|
||||||
expect(wrapper).toMatchSnapshot();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render children', () => {
|
it('attaches the link to the header text if provided', () => {
|
||||||
const wrapper = setup({
|
render(
|
||||||
link: {
|
<BrowserRouter>
|
||||||
text: 'link',
|
<SideMenuDropDown headerText={mockHeaderText} headerUrl={mockHeaderUrl} />
|
||||||
children: [{ id: 1 }, { id: 2 }, { id: 3 }],
|
</BrowserRouter>
|
||||||
},
|
);
|
||||||
});
|
const link = screen.getByRole('link', { name: mockHeaderText });
|
||||||
|
expect(link).toBeInTheDocument();
|
||||||
expect(wrapper).toMatchSnapshot();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not render hideFromMenu children', () => {
|
it('calls the onHeaderClick function when the header is clicked', () => {
|
||||||
const wrapper = setup({
|
render(<SideMenuDropDown headerText={mockHeaderText} onHeaderClick={mockOnHeaderClick} />);
|
||||||
link: {
|
const text = screen.getByText(mockHeaderText);
|
||||||
text: 'link',
|
expect(text).toBeInTheDocument();
|
||||||
children: [
|
userEvent.click(text);
|
||||||
{ id: 1, hideFromMenu: false },
|
expect(mockOnHeaderClick).toHaveBeenCalled();
|
||||||
{ id: 2, hideFromMenu: true },
|
});
|
||||||
{ id: 3, hideFromMenu: false },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(wrapper).toMatchSnapshot();
|
it('displays the items', () => {
|
||||||
|
render(<SideMenuDropDown headerText={mockHeaderText} items={mockItems} />);
|
||||||
|
mockItems.forEach(({ text }) => {
|
||||||
|
const childItem = screen.getByText(text);
|
||||||
|
expect(childItem).toBeInTheDocument();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,44 +1,41 @@
|
|||||||
import React, { FC } from 'react';
|
import React from 'react';
|
||||||
import { filter } from 'lodash';
|
|
||||||
import DropDownChild from './DropDownChild';
|
import DropDownChild from './DropDownChild';
|
||||||
import { NavModelItem } from '@grafana/data';
|
import { NavModelItem } from '@grafana/data';
|
||||||
import { IconName, Link } from '@grafana/ui';
|
import { IconName, Link } from '@grafana/ui';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
link: NavModelItem;
|
items?: NavModelItem[];
|
||||||
|
headerText: string;
|
||||||
|
headerUrl?: string;
|
||||||
onHeaderClick?: () => void;
|
onHeaderClick?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SideMenuDropDown: FC<Props> = (props) => {
|
const SideMenuDropDown = ({ items = [], headerText, headerUrl, onHeaderClick }: Props) => {
|
||||||
const { link, onHeaderClick } = props;
|
const headerContent = <span className="sidemenu-item-text">{headerText}</span>;
|
||||||
let childrenLinks: NavModelItem[] = [];
|
const header = headerUrl ? (
|
||||||
if (link.children) {
|
<Link href={headerUrl} onClick={onHeaderClick} className="side-menu-header-link">
|
||||||
childrenLinks = filter(link.children, (item) => !item.hideFromMenu);
|
{headerContent}
|
||||||
}
|
|
||||||
|
|
||||||
const linkContent = <span className="sidemenu-item-text">{link.text}</span>;
|
|
||||||
const anchor = link.url ? (
|
|
||||||
<Link href={link.url} onClick={onHeaderClick} className="side-menu-header-link">
|
|
||||||
{linkContent}
|
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
<a onClick={onHeaderClick} className="side-menu-header-link">
|
<a onClick={onHeaderClick} className="side-menu-header-link">
|
||||||
{linkContent}
|
{headerContent}
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ul className="dropdown-menu dropdown-menu--sidemenu" role="menu">
|
<ul className="dropdown-menu dropdown-menu--sidemenu" role="menu">
|
||||||
<li className="side-menu-header">{anchor}</li>
|
<li className="side-menu-header">{header}</li>
|
||||||
{childrenLinks.map((child, index) => (
|
{items
|
||||||
<DropDownChild
|
.filter((item) => !item.hideFromMenu)
|
||||||
key={`${child.url}-${index}`}
|
.map((child, index) => (
|
||||||
isDivider={child.divider}
|
<DropDownChild
|
||||||
icon={child.icon as IconName}
|
key={`${child.url}-${index}`}
|
||||||
text={child.text}
|
isDivider={child.divider}
|
||||||
url={child.url}
|
icon={child.icon as IconName}
|
||||||
/>
|
text={child.text}
|
||||||
))}
|
url={child.url}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -43,7 +43,7 @@ const TopSectionItem: FC<Props> = ({ link, onClick }) => {
|
|||||||
return (
|
return (
|
||||||
<div className="sidemenu-item dropdown">
|
<div className="sidemenu-item dropdown">
|
||||||
{anchor}
|
{anchor}
|
||||||
<SideMenuDropDown link={link} onHeaderClick={onClick} />
|
<SideMenuDropDown items={link.children} headerText={link.text} headerUrl={link.url} onHeaderClick={onClick} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,79 +0,0 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
||||||
|
|
||||||
exports[`Render should not render hideFromMenu children 1`] = `
|
|
||||||
<ul
|
|
||||||
className="dropdown-menu dropdown-menu--sidemenu"
|
|
||||||
role="menu"
|
|
||||||
>
|
|
||||||
<li
|
|
||||||
className="side-menu-header"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
className="side-menu-header-link"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="sidemenu-item-text"
|
|
||||||
>
|
|
||||||
link
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<DropDownChild
|
|
||||||
key="undefined-0"
|
|
||||||
/>
|
|
||||||
<DropDownChild
|
|
||||||
key="undefined-1"
|
|
||||||
/>
|
|
||||||
</ul>
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`Render should render children 1`] = `
|
|
||||||
<ul
|
|
||||||
className="dropdown-menu dropdown-menu--sidemenu"
|
|
||||||
role="menu"
|
|
||||||
>
|
|
||||||
<li
|
|
||||||
className="side-menu-header"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
className="side-menu-header-link"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="sidemenu-item-text"
|
|
||||||
>
|
|
||||||
link
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<DropDownChild
|
|
||||||
key="undefined-0"
|
|
||||||
/>
|
|
||||||
<DropDownChild
|
|
||||||
key="undefined-1"
|
|
||||||
/>
|
|
||||||
<DropDownChild
|
|
||||||
key="undefined-2"
|
|
||||||
/>
|
|
||||||
</ul>
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`Render should render component 1`] = `
|
|
||||||
<ul
|
|
||||||
className="dropdown-menu dropdown-menu--sidemenu"
|
|
||||||
role="menu"
|
|
||||||
>
|
|
||||||
<li
|
|
||||||
className="side-menu-header"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
className="side-menu-header-link"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="sidemenu-item-text"
|
|
||||||
>
|
|
||||||
link
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
`;
|
|
Loading…
Reference in New Issue
Block a user