Everytime i run snapshot test with jest and rest-testing-library for component with tooltip inside, new css classes are generated and thus snapshot is failing. Any ideas to solve this ?
- Snapshot
+ Received
@@ -49,80 +49,80 @@
>
XSS
</div>
</a>
<div
- class="__react_component_tooltip t478c1214-c3a1-4e62-b8d9-bec855c08c42 place-top type-dark"
+ class="__react_component_tooltip t6228f914-bd48-4261-96f8-0d9fbdc0096a place-top type-dark"
data-id="tooltip"
id="sizePicker-1001"
>
<style>
- .t478c1214-c3a1-4e62-b8d9-bec855c08c42 {
+ .t6228f914-bd48-4261-96f8-0d9fbdc0096a {
color: #fff;
background: #222;
border: 1px solid transparent;
}
- .t478c1214-c3a1-4e62-b8d9-bec855c08c42.place-top {
+ .t6228f914-bd48-4261-96f8-0d9fbdc0096a.place-top {
margin-top: -10px;
}
- .t478c1214-c3a1-4e62-b8d9-bec855c08c42.place-top::before {
+ .t6228f914-bd48-4261-96f8-0d9fbdc0096a.place-top::before {
border-top: 8px solid transparent;
}
- .t478c1214-c3a1-4e62-b8d9-bec855c08c42.place-top::after {
+ .t6228f914-bd48-4261-96f8-0d9fbdc0096a.place-top::after {
border-left: 8px solid transparent;
border-right: 8px solid transparent;
bottom: -6px;
left: 50%;
margin-left: -8px;
border-top-color: #222;
border-top-style: solid;
border-top-width: 6px;
}
- .t478c1214-c3a1-4e62-b8d9-bec855c08c42.place-bottom {
+ .t6228f914-bd48-4261-96f8-0d9fbdc0096a.place-bottom {
margin-top: 10px;
}
- .t478c1214-c3a1-4e62-b8d9-bec855c08c42.place-bottom::before {
+ .t6228f914-bd48-4261-96f8-0d9fbdc0096a.place-bottom::before {
border-bottom: 8px solid transparent;
}
- .t478c1214-c3a1-4e62-b8d9-bec855c08c42.place-bottom::after {
+ .t6228f914-bd48-4261-96f8-0d9fbdc0096a.place-bottom::after {
border-left: 8px solid transparent;
border-right: 8px solid transparent;
top: -6px;
left: 50%;
margin-left: -8px;
border-bottom-color: #222;
border-bottom-style: solid;
border-bottom-width: 6px;
}
- .t478c1214-c3a1-4e62-b8d9-bec855c08c42.place-left {
+ .t6228f914-bd48-4261-96f8-0d9fbdc0096a.place-left {
margin-left: -10px;
}
- .t478c1214-c3a1-4e62-b8d9-bec855c08c42.place-left::before {
+ .t6228f914-bd48-4261-96f8-0d9fbdc0096a.place-left::before {
border-left: 8px solid transparent;
}
- .t478c1214-c3a1-4e62-b8d9-bec855c08c42.place-left::after {
+ .t6228f914-bd48-4261-96f8-0d9fbdc0096a.place-left::after {
border-top: 5px solid transparent;
border-bottom: 5px solid transparent;
right: -6px;
top: 50%;
margin-top: -4px;
border-left-color: #222;
border-left-style: solid;
border-left-width: 6px;
}
- .t478c1214-c3a1-4e62-b8d9-bec855c08c42.place-right {
+ .t6228f914-bd48-4261-96f8-0d9fbdc0096a.place-right {
margin-left: 10px;
}
- .t478c1214-c3a1-4e62-b8d9-bec855c08c42.place-right::before {
+ .t6228f914-bd48-4261-96f8-0d9fbdc0096a.place-right::before {
border-right: 8px solid transparent;
}
- .t478c1214-c3a1-4e62-b8d9-bec855c08c42.place-right::after {
+ .t6228f914-bd48-4261-96f8-0d9fbdc0096a.place-right::after {
border-top: 5px solid transparent;
border-bottom: 5px solid transparent;
left: -6px;
top: 50%;
margin-top: -4px;
31 | const { asFragment } = render(component);
32 |
> 33 | expect(asFragment()).toMatchSnapshot();
| ^
34 | });
This looks related to #562
This isn't a fix, but it might help someone out.
We're using react-tooltip in a Storybook.js component library, and it was failing tests for the reason reported. For now, I've just had to ignore the stories that use this component from Storybook's testing suite.
export const YourStory = () => {
return <Tooltip>Here's some help text!</Tooltip>
}
YourStory.story = {
parameters: {
storyshots: { disable: true }
}
}
I imagine Jest natively has a similar 'ignore' config value - I'm not familiar with it beyond Storybook's Storyshot addon.
Not ideal, but it does mean we can move past this.
What version did this appear?
This first started to occur with version 4.0.5 (see #562). The proposed solution was to add uuid as a dependency and have developers mock the module (see #566):
jest.mock("uuid", () => ({ v4: () => "00000000-0000-0000-0000-000000000000" }));
Initially uuid was bundled to dist/index.js by rollup so uuid could not be mocked. That got fixed with #582.
The current implementation has certain limitations. For example, if your package (or a dependency) depends on a non-compatible uuid version (as of [email protected] its ^7.0.3), uuid will be installed in node_modules/react-tooltip/node_modules/uuid. This requires to change the mocking to:
jest.mock("react-tooltip/node_modules/uuid", () => ({ v4: () => "00000000-0000-0000-0000-000000000000" }));
This could be fixed by making uuid a peerDependency. However that would result in a breaking change, since consumers with no dependency to uuid will get a _Cannot find module 'uuid'_ error message. Instructions for installation would need to be updated as well.
Another alternative that does not depend on uuid's location is to mock crypto's randomBytes function like so:
jest.mock('crypto', () => ({ randomBytes: (num) => new Array(num).fill(0) }));
However, this approach can potentially break other testing that depend on the core crypto module.
As you can see, no solution is without its hiccups, and besides, none of these approaches are officially documented. I believe a more robust approach would be to expose a static method or property that could be executed so that generated uuids are static. For example:
// jest setup file
import ReactTooltip from "react-tooltip";
// alt names: .enableSnapshotMode(), .enableTestMode(), .testMode(), .snapshotMode()
ReactTooltip.useStaticUuids();
We just started using react-tooltip today and it also breaks our snapshot tests... Any update on this?
@marcogrcr Thank you for the initial ideas. I've found a workaround for the Cannot find module message that tests for package availability in a tricky sort of way to survive hoisting.
jest.mock(
(() => {
// This will mock the version of uuid belonging to react-tooltip
// if it exists, otherwise use the top-level uuid module
try {
require('react-tooltip/node_modules/uuid');
return 'react-tooltip/node_modules/uuid';
} catch (error) {
return 'uuid';
}
})(),
() => ({
v4: () => '00000000-0000-0000-0000-000000000000',
})
);
That should make the tests a bit more reliable across dependency and react-tooltip updates.
Most helpful comment
This first started to occur with version
4.0.5(see #562). The proposed solution was to adduuidas a dependency and have developers mock the module (see #566):Initially
uuidwas bundled todist/index.jsby rollup souuidcould not be mocked. That got fixed with #582.The current implementation has certain limitations. For example, if your package (or a dependency) depends on a non-compatible
uuidversion (as of[email protected]its^7.0.3),uuidwill be installed innode_modules/react-tooltip/node_modules/uuid. This requires to change the mocking to:This could be fixed by making
uuidapeerDependency. However that would result in a breaking change, since consumers with no dependency touuidwill get a _Cannot find module 'uuid'_ error message. Instructions for installation would need to be updated as well.Another alternative that does not depend on
uuid's location is to mockcrypto'srandomBytesfunction like so:However, this approach can potentially break other testing that depend on the core
cryptomodule.As you can see, no solution is without its hiccups, and besides, none of these approaches are officially documented. I believe a more robust approach would be to expose a static method or property that could be executed so that generated uuids are static. For example: