haveStyle does not work with linear-gradient
-
@testing-library/jest-domversion: 4.2 -
npmversion: 6.13.1
-
dom-testing-libraryversion: 4.2.4 -
react-testing-libraryversion: 9.3.2
Relevant code or config:
expect(getByTestId('border')).toHaveStyle('background: linear-gradient(red 0%, red 49%, white 50%);'); // Checks the gradient color of the component.
What you did:
I wanted to test the gradient color applied like this:
background: linear-gradient(red 0%, red 49%, white 50%);
What happened:
It always returns true if the expected value is a gradient. If one of them is e.g. a color, it fails as expected. It seems like the gradient string is just parsed into an empty string.
Reproduction:
Here is a sandbox.
If you change the expected value to something else than a gradient, it fails as expected, but lawys true, if it is a gradient.
Problem description:
A gradient in toHaveStyle always returns true.
Suggested solution:
Try to parse the gradient correctly and add a string compare to received and expected gradients.
Can you try using the latest version of jest-dom (v4.2.4)? Also, just to be safe, in the assertion, avoid using compound css properties. Try with background-color linear-gradient(...) instead of just background: ....
I tried it before on my machine, thats why I forgot to update the version.
I updated the sandbox, but the error still persists. It expects - background-color: ; but should expect - background-color: linear-gradient(#96f3f4 0%, #96f3f4 49%, white 50%);
So if the expected and received background-colors are both gradients, they pass no matter the actual gradient.
It seems like that in getStyleDeclaration the normalizing of colors fails because the style is not applied to the copy element created with document.createElement('div');. But only the gradients.
Hi all,
I think I hit something similar and it might be helpful or point someone in the right direction before spending some time reproducing it in an isolated scenario.
After playing with different versions, it seems like there's a regression from version 4.1.1 to 4.1.2 (where it starts failing for us)
Test code
const element = getByTestId('confetti-background-square');
debug();
expect(element).toHaveStyle(`
width: 14px;
height: 14px;
top: 30%;
left: 55%;
background-color: '#F3F2F0';
transform: rotateZ(22deg);
`);
See console output below after running our specs
FAIL src/components/ConfettiBackground/ConfettiBackgroundSquare/ConfettiBackgroundSquare.test.tsx
● Console
console.log node_modules/@testing-library/react/dist/pure.js:94
<body>
<div>
<div
class="confetti-background-square"
data-testid="confetti-background-square"
style="width: 14px; height: 14px; background-color: red; top: 30%; left: 55%; transform: rotateZ(22deg);"
/>
</div>
</body>
● applies the expected styles from required props
expect(element).toHaveStyle()
- Expected
- background-color: ;
height: 14px;
left: 55%;
top: 30%;
transform: rotateZ(22deg);
width: 14px;
16 |
17 | debug();
> 18 | expect(element).toHaveStyle(`
| ^
19 | width: 14px;
20 | height: 14px;
21 | top: 30%;
at Object.<anonymous> (src/components/ConfettiBackground/ConfettiBackgroundSquare/ConfettiBackgroundSquare.test.tsx:18:21)
Fixed it for now by pinning to v4.1.1 - let me know if that's totally unrelated and warrants a separate issue :)
@dennisroethig should the background-color value be quoted? In the expect(element).toHaveStyle assertion you have this line:
background-color: '#F3F2F0';
Furthermore, in the output of the debug() call the element seems to have background-color: red, so it's ok that the assertion fails, right? Because the element was expected to have background color '#F3F2F0' but it has red instead.
Let me know if I'm missing something here.
Adding quotes did not help in my case I am afraid.
Adding quotes did not help in my case I am afraid.
I am not advocating for adding quotes around the color name in the css rules, if that's what you mean. I meant that the quotes around the color name look like not valid css.
To be clear, my latest comment was with regards to @dennisroethig's case. I'm still not sure about your case @Domino987. I'm going to give it a look tomorrow.
Sorry @gnapse, missed the notification and thanks for the quick reply ...
The red was a leftover from my testing, so ignore that 😆
So you're saying the test code should be:
expect(element).toHaveStyle(`
width: 14px;
height: 14px;
top: 30%;
left: 55%;
background-color: "#F3F2F0";
transform: rotateZ(22deg);
`);
I don't think that should make a difference but also confirmed it is doing the same thing. Somehow the test-runner tries to assert
background-color: ;
height: 14px;
left: 55%;
top: 30%;
transform: rotateZ(22deg);
width: 14px;
to
style="width: 14px; height: 14px; background-color: rgb(243, 242, 240); top: 30%; left: 55%; transform: rotateZ(22deg);"
And as I said, pinning to 4.1.1 fixes it. So something must have changed around that time. If it's not clear or you think it's something else on our side I can see if I find some time next week to create a minimal repo to reproduce it, but that will take a bit until I get to it 😆
Thanks again for thinking about it ❤️
So you're saying the test code should be:
No, I was saying the opposite, that the color in the background-color line should not have quotes around it.
In the original test assertion you posted here above it had single quotes, and in your previous comment it has double quotes. But I think it shouldn't have any.
oh wow - thanks so much @gnapse I totally misread the CSS syntax embedded in the JS file and blacked out that it's not valid CSS 🤦♂
consider my comment "fixed" 😆
consider my comment "fixed" 😆
Do you mean then that this issue is now fixed/can-be-closed?
No it only addresses @dennisroethig problem. The assertion still fails for a gradient.
consider my comment "fixed" 😆
Do you mean then that this issue is now fixed/can-be-closed?
haha - only mine, sorry for hijacking 🙇
@Domino987 I'll check up on this early next week and will get back to you.
This seems to apply for any CSS function, and it doesn't matter what value is asserted.
Here's a sandbox with backgroundImage set to a radial gradient and a url.
I've set the assertion to toHaveStyle("background-color: xxx;"), and it still passes.
Indeed. Not sure how to deal with this 😕
@gnapse any news on this?
This happens because the style is not correctly applied when applying it to that placeholder element when the property value is not allowed. Eg: .toHaveStyle('background-color: xxx;')
Which then returns { 'background-color': '' } for the expected style and if that style is not present on an element it actually is truthy.
https://github.com/testing-library/jest-dom/blob/master/src/to-have-style.js#L12
I guess one could error out if copy.style[property] is empty but I dont know if that opens up other weird cases...
Something similiar actually happens for object-styles:
.toHaveStyle({
borderBottomWidth: '450%',
backgroundColor: 'blue',
})
passes as long as element has style backgroundColor: 'blue'. borderBottomWidth just gets ignored as it has an invalid value.
https://github.com/testing-library/jest-dom/blob/master/src/utils.js#L195
It seems to be an issue with JSDom I would say. https://github.com/jsdom/jsdom/issues/2166
Just setting the style property to a gradient leads to a style property with an empty string as value.
const div = document.createElement('div');
const gradient = 'linear-gradient(45deg, #fff, #000)';
div.style.backgroundColor = gradient;
expect(div.style.backgroundColor).toEqual(gradient);
I also tried different syntax and -webkit and -moz but no luck. It's just not possible to set this property. Interesting though the css rule parser package used by jsdom (CSSOM) is understanding css rules having linear-gradient. It's only not valid for style properties.
to test gradient have to use toHaveStyleRule. keep in mind it takes two parameter like below
expect(gradient).toHaveStyleRule( 'background-image', ' linear-gradient(45deg, #FFF, #000) ')
issue can be closed now