Testing opacity while hover button is not working. Tried with both userEvent.hover(hoverButton)
and fireEvent.mouseOver(hoverButton)
unfortunately the result is same. At the same time the other properties are working, for example 'cursor:not-allowed'
Button.js
import styled from 'styled-components';
const ButtonWrapper = styled.button`
color: #fff;
background-color: tomato;
font-size: 14px;
padding: 6px 30px;
height: 35px;
&:not(:disabled):hover {
opacity: 0.8;
background: red;
}
${({ disabled }) =>
disabled && `
opacity: 0.4;
cursor: not-allowed;
`}
`;
// background-color: ${(props) => props.theme.buttonColors[props.kind]};
const Button = ({ children, className, disabled, size = 'medium' }) => {
return <ButtonWrapper
className={className}
disabled={disabled}
onClick={() => console.log('Hello mate')}
size={size}
>{children}</ButtonWrapper>;
}
export default Button;
Button.test.js
import { fireEvent, render, screen } from '@testing-library/react';
import userEvent from "@testing-library/user-event";
import Button from './index';
test('should render button', () => {
render(<Button>Click on me</Button>);
expect(screen.getByText(/Click on me/i)).toBeInTheDocument();
});
test('should render disabled button', () => {
render(<Button disabled>hover on me</Button>);
const hoverButton = screen.getByRole('button');
expect(hoverButton).toBeDisabled();
expect(hoverButton).toHaveStyle('opacity: 0.4')
expect(hoverButton).toHaveStyle('cursor:not-allowed')
});
test('should hover button', () => {
render(<Button>hover on me</Button>);
// const hoverButton = screen.getByRole('button');
const hoverButton = screen.getByRole('button', { name: 'hover on me' });
userEvent.hover(hoverButton);
// fireEvent.mouseOver(hoverButton)
expect(hoverButton).toHaveStyle('opacity: 0.8')
expect(hoverButton).toHaveStyle(`background-color: #000`);
});
test('toMatchSnapshot', () => {
const { asFragment } = render(<Button>Click on me</Button>);
expect(asFragment()).toMatchSnapshot();
});
I found a few obstacles that you're running into:
background-color
was expected to be #000
when it's set as background: redu
in the Button.js
file.hover
interaction doesn't update the computed styles. I verified this using getComputedStyle in the DOM versus in the test. That said, you can use jest-styled-components' toHaveStyleRule
, to check for pseudo styles however that's not really not going to cover what you're attempting to test.disabled
). As a result, there's no way to accurately determine it's appearance since every Button
has the same pseudo styles (the snapshots showcase this, but also looking at the DOM will showcase the same thing):exports[`Button disabled snapshot 1`] = `
<DocumentFragment>
.c0 {
color: #fff;
background-color: tomato;
font-size: 14px;
padding: 6px 30px;
height: 35px;
opacity: 0.4;
cursor: not-allowed;
}
.c0:not(:disabled):hover {
opacity: 0.8;
background: red;
}
<button
class="c0"
disabled=""
>
Click on me
</button>
</DocumentFragment>
`;
exports[`Button enabled snapshot 1`] = `
<DocumentFragment>
.c0 {
color: #fff;
background-color: tomato;
font-size: 14px;
padding: 6px 30px;
height: 35px;
}
.c0:not(:disabled):hover {
opacity: 0.8;
background: red;
}
<button
class="c0"
>
Click on me
</button>
</DocumentFragment>
`;
You don't need to test against native interactions/style changes with the DOM. Instead, test against what you do control. In this case, you're controlling whether or not a button can be disabled and appending styles based upon that prop. Other than testing that (which you've already done), in this case, any other tests should be considered ancillary/superfluous.
Taking a step back, what exactly are you trying to test? It seems like you are trying to test if a browser can apply a style via a specific CSS selector to a button? This seems rather unnecessary, no?
This will test if an element contains a particular pseudo style, but again, it's shared and there's really no way to determine when its styles are active (even if you added a disabled
button prop, this test will still pass because it still contains the pseudo styles!):
test("should contain button hover styles", () => {
render(<Button>hover on me</Button>);
const hoverButton = screen.getByRole("button");
expect(hoverButton).toHaveStyleRule("opacity", "0.8", {
modifier: ":not(:disabled):hover",
});
expect(hoverButton).toHaveStyleRule("background", "red", {
modifier: ":not(:disabled):hover",
});
});