Sidemenu: Refactor `DropDownChild` (#38509)

* DropDownChild: Refactor DropDownChild to be more component-like

* Rewrite tests in RTL

* Let's not do this just yet...
pull/38554/head
Ashley Harrison 4 years ago committed by GitHub
parent 78596a6756
commit b30882bd2b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 61
      public/app/core/components/sidemenu/DropDownChild.test.tsx
  2. 25
      public/app/core/components/sidemenu/DropDownChild.tsx
  3. 14
      public/app/core/components/sidemenu/SideMenuDropDown.tsx
  4. 22
      public/app/core/components/sidemenu/__snapshots__/DropDownChild.test.tsx.snap
  5. 27
      public/app/core/components/sidemenu/__snapshots__/SideMenuDropDown.test.tsx.snap

@ -1,35 +1,48 @@
import React from 'react';
import { shallow } from 'enzyme';
import { render, screen } from '@testing-library/react';
import { BrowserRouter } from 'react-router-dom';
import DropDownChild from './DropDownChild';
const setup = (propOverrides?: object) => {
const props = Object.assign(
{
child: {
divider: true,
},
},
propOverrides
);
describe('DropDownChild', () => {
const mockText = 'MyChildItem';
const mockUrl = '/route';
const mockIcon = 'home-alt';
return shallow(<DropDownChild {...props} />);
};
it('displays the text', () => {
render(<DropDownChild text={mockText} />);
const text = screen.getByText(mockText);
expect(text).toBeInTheDocument();
});
describe('Render', () => {
it('should render component', () => {
const wrapper = setup();
it('attaches the link to the text if provided', () => {
render(
<BrowserRouter>
<DropDownChild text={mockText} url={mockUrl} />
</BrowserRouter>
);
const link = screen.getByRole('link', { name: mockText });
expect(link).toBeInTheDocument();
});
expect(wrapper).toMatchSnapshot();
it('displays an icon if a valid icon is provided', () => {
render(<DropDownChild text={mockText} icon={mockIcon} />);
const icon = screen.getByTestId('dropdown-child-icon');
expect(icon).toBeInTheDocument();
});
it('should render icon if exists', () => {
const wrapper = setup({
child: {
divider: false,
icon: 'icon-test',
},
});
it('displays a divider instead when isDivider is true', () => {
render(<DropDownChild text={mockText} icon={mockIcon} url={mockUrl} isDivider />);
// Check the divider is shown
const divider = screen.getByTestId('dropdown-child-divider');
expect(divider).toBeInTheDocument();
expect(wrapper).toMatchSnapshot();
// Check nothing else is rendered
const text = screen.queryByText(mockText);
const icon = screen.queryByTestId('dropdown-child-icon');
const link = screen.queryByRole('link', { name: mockText });
expect(text).not.toBeInTheDocument();
expect(icon).not.toBeInTheDocument();
expect(link).not.toBeInTheDocument();
});
});

@ -1,29 +1,30 @@
import React, { FC } from 'react';
import React from 'react';
import { css } from '@emotion/css';
import { Icon, IconName, Link, useTheme } from '@grafana/ui';
import { Icon, IconName, Link, useTheme2 } from '@grafana/ui';
export interface Props {
child: any;
isDivider?: boolean;
icon?: IconName;
text: string;
url?: string;
}
const DropDownChild: FC<Props> = (props) => {
const { child } = props;
const listItemClassName = child.divider ? 'divider' : '';
const theme = useTheme();
const DropDownChild = ({ isDivider = false, icon, text, url }: Props) => {
const theme = useTheme2();
const iconClassName = css`
margin-right: ${theme.spacing.sm};
margin-right: ${theme.spacing(1)};
`;
const linkContent = (
<>
{child.icon && <Icon name={child.icon as IconName} className={iconClassName} />}
{child.text}
{icon && <Icon data-testid="dropdown-child-icon" name={icon} className={iconClassName} />}
{text}
</>
);
const anchor = child.url ? <Link href={child.url}>{linkContent}</Link> : <a>{linkContent}</a>;
const anchor = url ? <Link href={url}>{linkContent}</Link> : <a>{linkContent}</a>;
return <li className={listItemClassName}>{anchor}</li>;
return isDivider ? <li data-testid="dropdown-child-divider" className="divider" /> : <li>{anchor}</li>;
};
export default DropDownChild;

@ -2,7 +2,7 @@ import React, { FC } from 'react';
import { filter } from 'lodash';
import DropDownChild from './DropDownChild';
import { NavModelItem } from '@grafana/data';
import { Link } from '@grafana/ui';
import { IconName, Link } from '@grafana/ui';
interface Props {
link: NavModelItem;
@ -30,9 +30,15 @@ const SideMenuDropDown: FC<Props> = (props) => {
return (
<ul className="dropdown-menu dropdown-menu--sidemenu" role="menu">
<li className="side-menu-header">{anchor}</li>
{childrenLinks.map((child, index) => {
return <DropDownChild child={child} key={`${child.url}-${index}`} />;
})}
{childrenLinks.map((child, index) => (
<DropDownChild
key={`${child.url}-${index}`}
isDivider={child.divider}
icon={child.icon as IconName}
text={child.text}
url={child.url}
/>
))}
</ul>
);
};

@ -1,22 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Render should render component 1`] = `
<li
className="divider"
>
<a />
</li>
`;
exports[`Render should render icon if exists 1`] = `
<li
className=""
>
<a>
<Icon
className="css-290ig"
name="icon-test"
/>
</a>
</li>
`;

@ -19,21 +19,9 @@ exports[`Render should not render hideFromMenu children 1`] = `
</a>
</li>
<DropDownChild
child={
Object {
"hideFromMenu": false,
"id": 1,
}
}
key="undefined-0"
/>
<DropDownChild
child={
Object {
"hideFromMenu": false,
"id": 3,
}
}
key="undefined-1"
/>
</ul>
@ -58,27 +46,12 @@ exports[`Render should render children 1`] = `
</a>
</li>
<DropDownChild
child={
Object {
"id": 1,
}
}
key="undefined-0"
/>
<DropDownChild
child={
Object {
"id": 2,
}
}
key="undefined-1"
/>
<DropDownChild
child={
Object {
"id": 3,
}
}
key="undefined-2"
/>
</ul>

Loading…
Cancel
Save