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();
});
CodePudding user response:
Problem
I found a few obstacles that you're running into:
- There's a mistake in the test, where the
background-color
was expected to be#000
when it's set asbackground: redu
in theButton.js
file. - I'm pretty confident that the testing-library's
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. - Currently, there's really no way for you to test a button's current appearance based upon a browser interaction, unless that interaction add/removes styles dynamically using some sort of React state or prop (similar to what you've done with
disabled
). As a result, there's no way to accurately determine it's appearance since everyButton
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
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
>
Click on me
</button>
</DocumentFragment>
`;
Recommendation:
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?
Not recommended:
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",
});
});