An Interest In:
Web News this Week
- April 18, 2024
- April 17, 2024
- April 16, 2024
- April 15, 2024
- April 14, 2024
- April 13, 2024
- April 12, 2024
Mocking framer-motion v4
Testing Library has changed the UI testing game for the better. If you haven't tried it yet, check it out.
At work our new UI efforts are powered by Chakra UI, which uses Framer Motion under the hood for animations. With all this work, we're testing all of it using Jest and React Testing Library (RTL).
One great way to defend against UI regressions (copy, styles, etc) is snapshot testing. As we're getting more and more into Chakra's features and better tests, we've run into issues where the animated style
properties have minute differences between snapshots.
RTL recommends mocking animation libraries to solve this problem. There are a few solutions for doing this with framer-motion
on the web, but I don't think they are up to snuff for the current version of the library (4._
).
After digging around the framer motion source, I realized our attempt at mocking the motion
export as an object (see here) wasn't working because motion
is constructed using Proxy.
Enough with the words, how do I stabilize my snapshot tests?!
// __mocks__/framer-motion.tsimport { CustomDomComponent, CustomMotionComponentConfig } from 'framer-motion/types/render/dom/motion-proxy';import * as React from 'react';const actual = jest.requireActual('framer-motion');// https://github.com/framer/motion/blob/main/src/render/dom/motion.tsfunction custom<Props>( Component: string | React.ComponentType<Props>, _customMotionComponentConfig: CustomMotionComponentConfig = {},): CustomDomComponent<Props> { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore return React.forwardRef((props, ref) => { const regularProps = Object.fromEntries( // do not pass framer props to DOM element Object.entries(props).filter(([key]) => !actual.isValidMotionProp(key)), ); return typeof Component === 'string' ? ( // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore <div ref={ref} {...regularProps} /> ) : ( // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore <Component ref={ref} {...regularProps} /> ); });}const componentCache = new Map<string, unknown>();const motion = new Proxy(custom, { get: (_target, key: string) => { if (!componentCache.has(key)) { componentCache.set(key, custom(key)); } // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return componentCache.get(key)!; },});module.exports = { __esModule: true, ...actual, AnimatePresence: ({ children }: { children: React.ReactChildren }) => <>{children}</>, motion,};
Now in your test setup file you can call jest.mock('framer-motion')
and all the animation related properties will be filtered out.
Happy testing!
Original Link: https://dev.to/tmikeschu/mocking-framer-motion-v4-19go
Dev To
An online community for sharing and discovering great ideas, having debates, and making friendsMore About this Source Visit Dev To