import React from 'react';
import { fireEvent, render, screen } from '@testing-library/react';
import { axe } from 'jest-axe';
import userEvent from '@testing-library/user-event';
import 'jest-styled-components';
import 'jest-axe/extend-expect';
import 'regenerator-runtime/runtime';
import '@testing-library/jest-dom';
import { Add, Next } from 'grommet-icons';
import { Grommet, Button, Text } from '../..';
describe('Button', () => {
test('should have no accessibility violations', async () => {
const { container } = render(
,
);
fireEvent.click(screen.getByText('Test'));
const results = await axe(container);
expect(results).toHaveNoViolations();
});
test('passes through the aria-label prop', async () => {
const TEST_LABEL = 'Test Label';
const { container } = render(
,
);
const button = screen.getByRole('button', { name: TEST_LABEL });
expect(button).toHaveAttribute('aria-label', TEST_LABEL);
fireEvent.click(button);
const results = await axe(container);
expect(results).toHaveNoViolations();
});
test('basic', () => {
const { container } = render(
,
);
expect(container.firstChild).toMatchSnapshot();
});
test('children function', () => {
const { container } = render(
,
);
expect(screen.getByTestId('children function')).toBeInTheDocument();
expect(container.firstChild).toMatchSnapshot();
});
test('children function with disabled prop', () => {
const { container } = render(
,
);
expect(
screen.getByRole('button', { name: 'Button#1 Disabled' }),
).toBeInTheDocument();
expect(
screen.getByRole('button', { name: 'Button#2 not Disabled' }),
).toBeInTheDocument();
expect(container.firstChild).toMatchSnapshot();
});
test('warns about invalid label', () => {
const warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
const { container } = render(
,
);
expect(container.firstChild).toMatchSnapshot();
expect(warnSpy).toHaveBeenCalledWith(
'Button should not have children if icon or label is provided',
);
warnSpy.mockReset();
warnSpy.mockRestore();
});
test('warns about invalid icon', () => {
const warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
const { container } = render(
} onClick={() => {}}>
invalid
,
);
expect(container.firstChild).toMatchSnapshot();
expect(warnSpy).toHaveBeenCalledWith(
'Button should not have children if icon or label is provided',
);
warnSpy.mockReset();
warnSpy.mockRestore();
});
test('primary', () => {
const { container } = render(
,
);
expect(screen.getByRole('button', { name: 'Primary Button' })).toHaveStyle({
'background-color': '#7D4CDB',
});
expect(container.firstChild).toMatchSnapshot();
});
test('color', () => {
const { container } = render(
,
);
expect(screen.getByRole('button', { name: 'accent-1' })).toHaveStyle({
'background-color': 'transparent',
});
expect(
screen.getByRole('button', { name: 'primary accent-1' }),
).toHaveStyle({
'background-color': '#6FFFB0',
});
expect(screen.getByRole('button', { name: 'custom color #1' })).toHaveStyle(
{
'background-color': '#111111',
},
);
expect(screen.getByRole('button', { name: 'custom color #2' })).toHaveStyle(
{
'background-color': '#123',
},
);
expect(container.firstChild).toMatchSnapshot();
});
test('fill', () => {
const { container } = render(
,
);
expect(screen.getByRole('button', { name: 'fill' })).toHaveStyle({
width: '100%',
height: '100%',
});
expect(screen.getByRole('button', { name: 'fill false' })).not.toHaveStyle({
width: '100%',
height: '100%',
});
expect(screen.getByRole('button', { name: 'fill horizontal' })).toHaveStyle(
{
width: '100%',
},
);
expect(screen.getByRole('button', { name: 'fill vertical' })).toHaveStyle({
height: '100%',
});
expect(container.firstChild).toMatchSnapshot();
});
test('focus', async () => {
const user = userEvent.setup();
const { container } = render(
{}} />
,
);
const button = screen.getByRole('button', { name: 'Test focus' });
expect(button).not.toHaveFocus();
expect(document.body).toHaveFocus();
await user.tab();
expect(button).toHaveFocus();
expect(document.body).not.toHaveFocus();
expect(button).toHaveStyleRule('box-shadow', '0 0 2px 2px #6FFFB0', {
modifier: ':focus',
});
expect(container.firstChild).toMatchSnapshot();
});
test('tip', () => {
const { container } = render(
{}} tip="tooltip" />
,
);
expect(screen.queryByText('tooltip')).not.toBeInTheDocument();
fireEvent.mouseOver(screen.getByText('Default Tip'));
expect(screen.getByText('tooltip')).toBeInTheDocument();
expect(container.firstChild).toMatchSnapshot();
});
test('disabled', () => {
const { container } = render(
} />
} plain />
} plain={false} />
} label="Button" />
} label="Button" plain />
} label="Button" primary />
,
);
const allButtons = screen.getAllByRole('button');
expect(allButtons).toHaveLength(11);
allButtons.forEach((button) => expect(button).toBeDisabled());
expect(container.firstChild).toMatchSnapshot();
});
test('active', () => {
const { container } = render(
,
);
expect(container.firstChild).toMatchSnapshot();
});
test('active + primary', () => {
const { container } = render(
,
);
expect(container.firstChild).toMatchSnapshot();
});
test('icon label', () => {
const { container } = render(
}
label="Test"
onClick={() => {}}
/>
,
);
expect(screen.getByTestId('icon')).toBeInTheDocument();
expect(container.firstChild).toMatchSnapshot();
});
test('reverse icon label', () => {
const { container } = render(
}
label="Test"
onClick={() => {}}
/>
,
);
expect(screen.getByTestId('icon')).toBeInTheDocument();
expect(container.firstChild).toMatchSnapshot();
});
test('href', () => {
const { container } = render(
,
);
expect(
screen.getByRole('link', { name: 'Button as link' }),
).toHaveAttribute('href', 'test');
expect(container.firstChild).toMatchSnapshot();
});
test('hoverIndicator background', () => {
const { container } = render(
{}} hoverIndicator="background">
hoverIndicator
,
);
expect(
screen.getByRole('button', { name: 'hoverIndicator' }),
).toHaveStyleRule('background-color', 'rgba(221,221,221,0.4)', {
modifier: ':hover',
});
expect(container.firstChild).toMatchSnapshot();
});
test('hoverIndicator as object with color', () => {
const { container } = render(
{}} hoverIndicator={{ color: 'brand' }}>
hoverIndicator
,
);
expect(
screen.getByRole('button', { name: 'hoverIndicator' }),
).toHaveStyleRule('background-color', 'rgba(125,76,219,1)', {
modifier: ':hover',
});
expect(container.firstChild).toMatchSnapshot();
});
test('hoverIndicator as object with invalid color', () => {
const { container } = render(
{}} hoverIndicator={{ color: 'invalid' }}>
hoverIndicator
,
);
expect(container.firstChild).toMatchSnapshot();
});
test('hoverIndicator color', () => {
const { container } = render(
{}} hoverIndicator="dark-3">
hoverIndicator
,
);
expect(container.firstChild).toMatchSnapshot();
});
test('onClick', () => {
const onClick = jest.fn();
render(
,
);
fireEvent.click(screen.getByRole('button'));
expect(onClick).toBeCalled();
});
test('size', () => {
const { container } = render(
} primary />
} primary />
} primary />
} primary />
} reverse />
} reverse />
} reverse />
} reverse />
,
);
expect(container.firstChild).toMatchSnapshot();
});
test('as', () => {
const Anchor = () => ;
const { asFragment } = render(
,
);
expect(screen.queryByRole('button')).not.toBeInTheDocument();
expect(asFragment()).toMatchSnapshot();
});
test('a11yTitle', () => {
const { container } = render(
,
);
const allButtons = screen.getAllByRole('button', { name: 'Title' });
expect(allButtons).toHaveLength(2);
allButtons.forEach((button) =>
expect(button).toHaveAttribute('aria-label', 'Title'),
);
expect(container.firstChild).toMatchSnapshot();
});
test(`disabled state cursor should indicate the button cannot be
clicked`, () => {
render(
,
);
const button = screen.getByRole('button', { name: 'Button' });
expect(button).toHaveStyle({ cursor: 'default' });
const cursorStyle = window.getComputedStyle(button).cursor;
expect(cursorStyle).not.toBe('pointer');
expect(cursorStyle).toBe('default');
});
test(`badge should be offset from top-right corner`, () => {
const { container } = render(
,
);
expect(container.firstChild).toMatchSnapshot();
});
test(`badge should display number content`, () => {
const { container } = render(
,
);
expect(screen.getByText('2')).toBeInTheDocument();
expect(container.firstChild).toMatchSnapshot();
});
test(`badge should display "+" when number is greater than max`, () => {
const { container } = render(
,
);
expect(screen.getByText('9+')).toBeInTheDocument();
expect(container.firstChild).toMatchSnapshot();
});
test(`badge should apply background`, () => {
const { container } = render(
,
);
expect(container.firstChild).toMatchSnapshot();
});
test(`badge should render custom element`, () => {
const { container } = render(
}
/>
,
);
expect(screen.getByTestId('badge')).toBeInTheDocument();
expect(container.firstChild).toMatchSnapshot();
});
test(`badge should render relative to contents when button has no
border or background`, () => {
const { container } = render(
} badge />
,
);
expect(container.firstChild).toMatchSnapshot();
});
test(`line-height should be zero for icon only`, () => {
const { getByRole } = render(
} />
,
);
expect(getByRole('button')).toHaveStyleRule('line-height', '0');
});
test('should render pad', () => {
const { asFragment } = render(
}
pad="xlarge"
/>
}
pad={{ horizontal: '18px', vertical: '6px' }}
/>
{/* should not render pad on plain button */}
,
);
const stringPadButton = screen.getByTestId('string-pad');
const objectPadButton = screen.getByTestId('object-pad');
const childPadButton = screen.getByTestId('child-pad');
let style;
style = window.getComputedStyle(stringPadButton);
expect(style.padding).toBe('96px');
style = window.getComputedStyle(objectPadButton);
expect(style.paddingTop).toBe('6px');
expect(style.paddingBottom).toBe('6px');
expect(style.paddingLeft).toBe('18px');
expect(style.paddingRight).toBe('18px');
style = window.getComputedStyle(childPadButton);
expect(style.padding).toBe('0px');
expect(asFragment()).toMatchSnapshot();
});
});