How to test CSS hover in Enzyme - React - css

I am new To React testing with Enzyme and Jest, and I have this scenario to test:
When hover the ParentDiv, The Child div should change style to background-color: green and display: block.
But in testing, after simulate mouseenter event, none of the style is changed, they still background-color: red and display: none
This is a Class-based component
const Child = styled.div`
background-color: red;
display: none;
`;
const ParentDiv = styled.div`
&:hover {
${Child} {
background-color: green;
display: block;
}
}
`;
<ParentDiv>
<Child>
<p>{text}</p>
</Child>
</ParentDiv>
Test.js
it('Hover over ParentDiv should display the child', () => {
const Wrapper = mount(<MyComponent >);
const parent = Wrapper.find('ParentDiv');
const child = Wrapper.find('child');
expect(child).toHaveStyleRule('display', 'none');
expect(child).toHaveStyleRule('background-color', 'red');
parent.simulate('mouseenter');
// next two lines not working
// expect(child).toHaveStyleRule('display', 'block'); // expected display: block but received display: none
// expect(child).toHaveStyleRule('background-color', 'green');
});

In case anyone comes looking, the solution for this is to use the opts parameter in toHaveStyleRule.
so you need to use this:
expect(child).toHaveStyleRule('display', 'block', { modifier: ':hover' });
Here is a link to the docs: https://github.com/styled-components/jest-styled-components#tohavestylerule

Related

How to add css pseudo element in react

How do I add CSS pseudo-element ::after dynamically through react. I have a header where I'm setting its background color to black on scroll. Now I want to add ::after as well on scroll where I could add some more styling to it. Is there any way I could achieve this?
const Header = () => {
const [ headerColor, setHeaderColor ] = useState(false);
const headerColorChange = () => {
window.scrollY >= 80 ? setHeaderColor(true) : setHeaderColor(false)
}
useEffect(() => {
window.addEventListener("scroll", headerColorChange)
}, [])
return (
<header id="header" className={ headerColor ? 'header-color' : null}>
</header>
)
}
In my CSS file:
.header-color {
background-color: $black;
}
I would like to add ::after to my header so that I could add more styling to it. (on Scroll)
&::after {
max-width: 100%;
}
Before scroll my ::after is at #header
#header::after {
width: 100%;
max-width: 1170px;
border-bottom: 1px solid $white;
}

Styled-components - Over 200 classes were generated, but cant get :hover to work

I came across the error in styled-components :
Over 200 classes were generated for component......
and did the suggested fix from console, and that did the trick, but when I have a container component "Card" that when hovered should change text color of another component "Number" (which has that suggested fix applied, then I cant change the color (i assume because style overrides the hover change, because it works fine with opacity)
the mentioned components are in src/ProgressPieCard (first 2 components)
anyone got any got suggestions, thanks in advance :)
( sorry styling/position is a bit off )
CodeSandBox
const Number = styled.p.attrs<ColorProps>((props) => ({
style: {
color: props.color,
},
}))`
position: absolute;
span {
font-size: 1.5rem;
}
`;
const Card = styled.div.attrs<ColorProps>((props) => ({
style: {
background: props.color,
},
}))`
position: relative;
&:hover {
${Number} {
opacity: 0.5;
// color: red; <-- this dont work
}
}
`;
Values ​​from props were pass as inline styles. They have higher priority. I suggest passing values ​​from props differently. The example below will now work as you wanted.
const Number = styled.p<ColorProps>`
position: absolute;
color: ${p => p.color};
span {
font-size: 1.5rem;
}
`;
const Card = styled.div<ColorProps>`
position: relative;
background: ${p => p.color};
&:hover ${Number} {
opacity: 0.5;
color: red; <-- this WILL work :)
}
`;

How to remove ant-click-animating of button Ant design

After I click on the button, it has the animation around the button. So I want to turn it off, I try to set CSS for element and Pseudo-classes but it's not working.
.ant-switch,
.ant-switch:focus,
.ant-switch:active {
border-color: white !important;
box-shadow: none !important;
outline: unset;
}
My code:
import React from 'react';
import { Switch } from 'antd';
import styled from 'styled-components';
const RSwitch = styled(Switch)`
background-color: ${props => props.backgroundcolor};
.ant-switch-handle::before {
background-color: #9b9b9b;
right: 0;
}
&[aria-checked='true'] {
.ant-switch-handle {
::before {
background-color: ${props => props.color};
}
}
}
`;
export default function SwitchComponent({
onChange,
checked,
color = '#00afdb',
backgroundColor = ''
}) {
return (
<RSwitch
onChange={onChange}
checked={checked}
size="small"
color={color}
backgroundcolor={backgroundColor}
/>
);
}
ant switch picture
HTML of switch
I fixed it with this solution
create a button.less file in your ant overrides and put this inside
[ant-click-animating-without-extra-node='true']::after{display:none;}
and it will work like a charm.
I realize it is just a div tag so I don't display it. If everybody has a better solution, please let me know.
.ant-click-animating-node {
display: none;
}
.ant-btn {
&::after {
all: unset;
}
}

Mock hover state in Storybook?

I have a hover style in my component:
const style = css`
color: blue;
&:hover {
color: red;
}
`;
Can you mock this in Storybook so that it can be shown without having to manually hover over the component?
Since in Storybook you need to show the component hover appearance, rather than correctly simulate the hover related stuff,
the first option is to add a css class with the same style as :hover :
// scss
.component {
&:hover, &.__hover {
color: red;
}
}
// JSX (story)
const ComponentWithHover = () => <Component className="component __hover">Component with hover</Component>
the second one is to use this addon.

How to properly overwrite existing className with emotionJS

I'm trying to use emotion to overwrite the styling of an existing React component from a 3rd party library.
I try my best to simplified the problem in this codesandbox
The ExternalLib simulates a 3rd party component I'm using which I should not change the code.
As you can see it accepts a "prefix" props for css namespace and uses className in static string.(the original one has it as sass variable also)
I first try to get the base className hash with css function, then I try to compose those in emotion way of composition, and I get the expected visual result.
const baseStyle = css`
background-color: blue;
width: 200px;
height: 200px;
`;
const getItemStyle = ({ disabled }) => {
return `
height: 50px;
margin: 4px;
background-color: ${disabled ? "gray" : "yellow"};
`;
};
const getTextStyle = ({ color }) => {
return `
color: ${color}
`;
};
const StyledExternalLib = styled(ExternalLib)`
.${baseStyle}-track {
${getItemStyle};
}
.${baseStyle}-text {
${getTextStyle};
}
`;
however inspecting the style tags, I got many duplicated styles, what am I doing wrong?
you can see there are twice the yellow background
Here what i found, use css prop to the parent tag
css={{
"& .class__youwant--overwrite": {
margin: 80
}
}}
Worked in my case

Resources