From d14d1a92dd39abbd22ae785d7bdf9cdcdc7f7214 Mon Sep 17 00:00:00 2001 From: Tom Lienard Date: Tue, 12 Oct 2021 17:09:19 +0200 Subject: [PATCH 1/9] feat(jest-helpers): add jest-helpers package --- packages/jest-helpers/.npmignore | 3 + packages/jest-helpers/package.json | 33 +++++ .../src/helpers/renderWithTheme.tsx | 24 ++++ .../src/helpers/shouldMatchEmotionSnapshot.ts | 22 ++++ .../shouldMatchEmotionSnapshotWithPortal.ts | 35 ++++++ packages/jest-helpers/src/index.ts | 40 ++++++ yarn.lock | 114 +++++++++++++++++- 7 files changed, 269 insertions(+), 2 deletions(-) create mode 100644 packages/jest-helpers/.npmignore create mode 100644 packages/jest-helpers/package.json create mode 100644 packages/jest-helpers/src/helpers/renderWithTheme.tsx create mode 100644 packages/jest-helpers/src/helpers/shouldMatchEmotionSnapshot.ts create mode 100644 packages/jest-helpers/src/helpers/shouldMatchEmotionSnapshotWithPortal.ts create mode 100644 packages/jest-helpers/src/index.ts diff --git a/packages/jest-helpers/.npmignore b/packages/jest-helpers/.npmignore new file mode 100644 index 000000000..d1811b877 --- /dev/null +++ b/packages/jest-helpers/.npmignore @@ -0,0 +1,3 @@ +**/__tests__/** +src +!.npmignore diff --git a/packages/jest-helpers/package.json b/packages/jest-helpers/package.json new file mode 100644 index 000000000..df324f24e --- /dev/null +++ b/packages/jest-helpers/package.json @@ -0,0 +1,33 @@ +{ + "name": "@scaleway/jest-helpers", + "version": "1.0.0", + "description": "A package for jest helpers", + "type": "module", + "main": "dist/index.js", + "module": "dist/index.js", + "types": "dist/index.d.ts", + "publishConfig": { + "access": "public" + }, + "repository": { + "type": "git", + "url": "https://github.com/scaleway/scaleway-lib", + "directory": "packages/jest-helpers" + }, + "license": "MIT", + "devDependencies": { + "@emotion/cache": "^11.1.3", + "@emotion/jest": "^11.3.0", + "@emotion/react": "^11.1.4", + "@testing-library/react": "^12.1.2", + "@types/react": "^17.0.27", + "react": "^17.0.2" + }, + "peerDependencies": { + "@emotion/cache": "^11.1.3", + "@emotion/jest": "^11.3.0", + "@emotion/react": "^11.1.4", + "@testing-library/react": "^12.1.2", + "react": "^17.0.2" + } +} diff --git a/packages/jest-helpers/src/helpers/renderWithTheme.tsx b/packages/jest-helpers/src/helpers/renderWithTheme.tsx new file mode 100644 index 000000000..5a012c159 --- /dev/null +++ b/packages/jest-helpers/src/helpers/renderWithTheme.tsx @@ -0,0 +1,24 @@ +/* eslint-disable react/jsx-props-no-spreading */ +import createCache from '@emotion/cache' +import { CacheProvider } from '@emotion/react' +import { RenderOptions, render } from '@testing-library/react' +import React, { FC, ReactNode } from 'react' + +const emotionCache = createCache({ + key: 'cache', +}) + +emotionCache.compat = true + +export type RenderWithThemeFn = (component: ReactNode, options?: RenderOptions, theme?: Theme) => ReturnType + +export default function makeRenderWithTheme(Wrapper: FC<{ theme?: Theme }>): RenderWithThemeFn { + return (component, options, theme) => render( + + + {component} + + , + options, + ) +} diff --git a/packages/jest-helpers/src/helpers/shouldMatchEmotionSnapshot.ts b/packages/jest-helpers/src/helpers/shouldMatchEmotionSnapshot.ts new file mode 100644 index 000000000..126cd62b5 --- /dev/null +++ b/packages/jest-helpers/src/helpers/shouldMatchEmotionSnapshot.ts @@ -0,0 +1,22 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import { RenderOptions, render } from '@testing-library/react' +import { ReactNode } from 'react' +import { RenderWithThemeFn } from './renderWithTheme' + +interface Options { + options?: RenderOptions + transform?: (node: ReturnType) => Promise | void + theme?: Theme +} + +export type ShouldMatchEmotionSnapshotFn = (component: ReactNode, options?: Options) => Promise + +export default function makeShouldMatchEmotionSnapshot(renderWithTheme: RenderWithThemeFn): ShouldMatchEmotionSnapshotFn { + return async (component, { options, transform, theme } = {}) => { + const node = renderWithTheme(component, options, theme) + if (transform) await transform(node) + + expect(node.asFragment()).toMatchSnapshot() + node.unmount() + } +} diff --git a/packages/jest-helpers/src/helpers/shouldMatchEmotionSnapshotWithPortal.ts b/packages/jest-helpers/src/helpers/shouldMatchEmotionSnapshotWithPortal.ts new file mode 100644 index 000000000..d58c2a494 --- /dev/null +++ b/packages/jest-helpers/src/helpers/shouldMatchEmotionSnapshotWithPortal.ts @@ -0,0 +1,35 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import { RenderOptions, render } from '@testing-library/react' +import { ReactNode } from 'react' +import { RenderWithThemeFn } from './renderWithTheme' + +interface Options { + options?: RenderOptions + transform?: (node: ReturnType) => Promise | void + theme?: Theme +} + +export type ShouldMatchEmotionSnapshotWithPortalFn = (component: ReactNode, options?: Options) => Promise + +export default function makeShouldMatchEmotionSnapshotWithPortal(renderWithTheme: RenderWithThemeFn): ShouldMatchEmotionSnapshotWithPortalFn { + return async (component, { options, transform, theme } = {}) => { + // Save the instance of console (disable warning about adding element directly to document.body which is necessary when testing portal components) + const { console } = global + global.console = { ...console, error: jest.fn() } + + const node = renderWithTheme( + component, + { + container: document.body, + ...options, + }, + theme, + ) + if (transform) await transform(node) + expect(node.asFragment()).toMatchSnapshot() + + // Unmounting to don't see the warning message described above + node.unmount() + global.console = console + } +} diff --git a/packages/jest-helpers/src/index.ts b/packages/jest-helpers/src/index.ts new file mode 100644 index 000000000..67c3f1727 --- /dev/null +++ b/packages/jest-helpers/src/index.ts @@ -0,0 +1,40 @@ +import { CreateSerializerOptions, createSerializer } from '@emotion/jest' +import { FC } from 'react' +import makeRenderWithTheme, { RenderWithThemeFn } from './helpers/renderWithTheme' +import makeShouldMatchEmotionSnapshot, { ShouldMatchEmotionSnapshotFn } from './helpers/shouldMatchEmotionSnapshot' +import makeShouldMatchEmotionSnapshotWithPortal, { ShouldMatchEmotionSnapshotWithPortalFn } from './helpers/shouldMatchEmotionSnapshotWithPortal' + +export { default as makeRenderWithTheme } from './helpers/renderWithTheme' + +type Helpers = { + renderWithTheme: RenderWithThemeFn + shouldMatchEmotionSnapshot: ShouldMatchEmotionSnapshotFn + shouldMatchEmotionSnapshotWithPortal: ShouldMatchEmotionSnapshotWithPortalFn +} + +export default function makeHelpers(Wrapper: FC<{ theme?: Theme }>, createSerializerOptions?: CreateSerializerOptions): Helpers { + let isInitialized = false + + const initializeIfNeeded = (callback: T) => { + if (!isInitialized) { + isInitialized = true + + // use only class hash (generated from css style content) + expect.addSnapshotSerializer( + createSerializer(createSerializerOptions), + ) + } + + return callback; + } + + const renderWithTheme = makeRenderWithTheme(Wrapper) + const shouldMatchEmotionSnapshot = initializeIfNeeded(makeShouldMatchEmotionSnapshot(renderWithTheme)) + const shouldMatchEmotionSnapshotWithPortal = initializeIfNeeded(makeShouldMatchEmotionSnapshotWithPortal(renderWithTheme)) + + return { + renderWithTheme, + shouldMatchEmotionSnapshot, + shouldMatchEmotionSnapshotWithPortal, + } +} diff --git a/yarn.lock b/yarn.lock index a7d4d0e80..8bfb92ee1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1108,6 +1108,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.13.10": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.4.tgz#fd17d16bfdf878e6dd02d19753a39fa8a8d9c84a" + integrity sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/template@^7.14.5", "@babel/template@^7.15.4", "@babel/template@^7.3.3": version "7.15.4" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.15.4.tgz#51898d35dcf3faa670c4ee6afcfd517ee139f194" @@ -1284,6 +1291,90 @@ dependencies: chalk "^4.0.0" +"@emotion/cache@^11.1.3", "@emotion/cache@^11.4.0": + version "11.4.0" + resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.4.0.tgz#293fc9d9a7a38b9aad8e9337e5014366c3b09ac0" + integrity sha512-Zx70bjE7LErRO9OaZrhf22Qye1y4F7iDl+ITjet0J+i+B88PrAOBkKvaAWhxsZf72tDLajwCgfCjJ2dvH77C3g== + dependencies: + "@emotion/memoize" "^0.7.4" + "@emotion/sheet" "^1.0.0" + "@emotion/utils" "^1.0.0" + "@emotion/weak-memoize" "^0.2.5" + stylis "^4.0.3" + +"@emotion/css-prettifier@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@emotion/css-prettifier/-/css-prettifier-1.0.0.tgz#3ed4240d93c9798c001cedf27dd0aa960bdddd1a" + integrity sha512-efxSrRTiTqHTQVKW15Gz5H4pNAw8OqcG8NaiwkJIkqIdNXTD4Qr1zC1Ou6r2acd1oJJ2s56nb1ClnXMiWoj6gQ== + dependencies: + "@emotion/memoize" "^0.7.4" + stylis "^4.0.3" + +"@emotion/hash@^0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413" + integrity sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow== + +"@emotion/jest@^11.3.0": + version "11.3.0" + resolved "https://registry.yarnpkg.com/@emotion/jest/-/jest-11.3.0.tgz#43bed6dcb47c8691b346cee231861ebc8f9b0016" + integrity sha512-LZqYc3yerhic1IvAcEwBLRs1DsUt3oY7Oz6n+e+HU32iYOK/vpfzlhgmQURE94BHfv6eCOj6DV38f3jSnIkBkQ== + dependencies: + "@babel/runtime" "^7.13.10" + "@emotion/css-prettifier" "^1.0.0" + chalk "^4.1.0" + specificity "^0.4.1" + stylis "^4.0.3" + +"@emotion/memoize@^0.7.4": + version "0.7.5" + resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.5.tgz#2c40f81449a4e554e9fc6396910ed4843ec2be50" + integrity sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ== + +"@emotion/react@^11.1.4": + version "11.4.1" + resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.4.1.tgz#a1b0b767b5bad57515ffb0cad9349614d27f4d57" + integrity sha512-pRegcsuGYj4FCdZN6j5vqCALkNytdrKw3TZMekTzNXixRg4wkLsU5QEaBG5LC6l01Vppxlp7FE3aTHpIG5phLg== + dependencies: + "@babel/runtime" "^7.13.10" + "@emotion/cache" "^11.4.0" + "@emotion/serialize" "^1.0.2" + "@emotion/sheet" "^1.0.2" + "@emotion/utils" "^1.0.0" + "@emotion/weak-memoize" "^0.2.5" + hoist-non-react-statics "^3.3.1" + +"@emotion/serialize@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.0.2.tgz#77cb21a0571c9f68eb66087754a65fa97bfcd965" + integrity sha512-95MgNJ9+/ajxU7QIAruiOAdYNjxZX7G2mhgrtDWswA21VviYIRP1R5QilZ/bDY42xiKsaktP4egJb3QdYQZi1A== + dependencies: + "@emotion/hash" "^0.8.0" + "@emotion/memoize" "^0.7.4" + "@emotion/unitless" "^0.7.5" + "@emotion/utils" "^1.0.0" + csstype "^3.0.2" + +"@emotion/sheet@^1.0.0", "@emotion/sheet@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.0.2.tgz#1d9ffde531714ba28e62dac6a996a8b1089719d0" + integrity sha512-QQPB1B70JEVUHuNtzjHftMGv6eC3Y9wqavyarj4x4lg47RACkeSfNo5pxIOKizwS9AEFLohsqoaxGQj4p0vSIw== + +"@emotion/unitless@^0.7.5": + version "0.7.5" + resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed" + integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== + +"@emotion/utils@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.0.0.tgz#abe06a83160b10570816c913990245813a2fd6af" + integrity sha512-mQC2b3XLDs6QCW+pDQDiyO/EdGZYOygE8s5N5rrzjSI4M3IejPE/JPndCBwRT9z982aqQNi6beWs1UeayrQxxA== + +"@emotion/weak-memoize@^0.2.5": + version "0.2.5" + resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46" + integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA== + "@endemolshinegroup/cosmiconfig-typescript-loader@^3.0.2": version "3.0.2" resolved "https://registry.yarnpkg.com/@endemolshinegroup/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-3.0.2.tgz#eea4635828dde372838b0909693ebd9aafeec22d" @@ -2524,7 +2615,7 @@ "@types/react-test-renderer" ">=16.9.0" react-error-boundary "^3.1.0" -"@testing-library/react@^12.0.0": +"@testing-library/react@^12.0.0", "@testing-library/react@^12.1.2": version "12.1.2" resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-12.1.2.tgz#f1bc9a45943461fa2a598bb4597df1ae044cfc76" integrity sha512-ihQiEOklNyHIpo2Y8FREkyD1QAea054U0MVbwH1m8N9TxeFz+KoJ9LkqoKqJlzx2JDm56DVwaJ1r36JYxZM05g== @@ -2704,6 +2795,15 @@ "@types/scheduler" "*" csstype "^3.0.2" +"@types/react@^17.0.27": + version "17.0.27" + resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.27.tgz#6498ed9b3ad117e818deb5525fa1946c09f2e0e6" + integrity sha512-zgiJwtsggVGtr53MndV7jfiUESTqrbxOcBvwfe6KS/9bzaVPCTDieTWnFNecVNx6EAaapg5xsLLWFfHHR437AA== + dependencies: + "@types/prop-types" "*" + "@types/scheduler" "*" + csstype "^3.0.2" + "@types/resolve@1.17.1": version "1.17.1" resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6" @@ -4953,7 +5053,7 @@ history@^4.9.0: tiny-warning "^1.0.0" value-equal "^1.0.1" -hoist-non-react-statics@^3.1.0: +hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.1: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== @@ -8126,6 +8226,11 @@ spdx-license-ids@^3.0.0: resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz#c80757383c28abf7296744998cbc106ae8b854ce" integrity sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw== +specificity@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/specificity/-/specificity-0.4.1.tgz#aab5e645012db08ba182e151165738d00887b019" + integrity sha512-1klA3Gi5PD1Wv9Q0wUoOQN1IWAuPu0D1U03ThXTr0cJ20+/iq2tHSDnK7Kk/0LXJ1ztUB2/1Os0wKmfyNgUQfg== + split-on-first@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f" @@ -8340,6 +8445,11 @@ strong-log-transformer@^2.1.0: minimist "^1.2.0" through "^2.3.4" +stylis@^4.0.3: + version "4.0.10" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.0.10.tgz#446512d1097197ab3f02fb3c258358c3f7a14240" + integrity sha512-m3k+dk7QeJw660eIKRRn3xPF6uuvHs/FFzjX3HQ5ove0qYsiygoAhwn5a3IYKaZPo5LrYD0rfVmtv1gNY1uYwg== + supports-color@8.1.1, supports-color@^8.0.0: version "8.1.1" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" From b2d6cedfdd3f581a32fb480f53922b8a1cfec2d8 Mon Sep 17 00:00:00 2001 From: Tom Lienard Date: Wed, 13 Oct 2021 11:11:54 +0200 Subject: [PATCH 2/9] chore(deps): update deps --- packages/jest-helpers/package.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/jest-helpers/package.json b/packages/jest-helpers/package.json index df324f24e..ab1ababff 100644 --- a/packages/jest-helpers/package.json +++ b/packages/jest-helpers/package.json @@ -21,13 +21,12 @@ "@emotion/react": "^11.1.4", "@testing-library/react": "^12.1.2", "@types/react": "^17.0.27", - "react": "^17.0.2" + "react": "^17.0.1" }, "peerDependencies": { "@emotion/cache": "^11.1.3", "@emotion/jest": "^11.3.0", "@emotion/react": "^11.1.4", - "@testing-library/react": "^12.1.2", - "react": "^17.0.2" + "react": "^17.0.1" } } From 8bb40af43e570842150aa16af27526efeeec41b3 Mon Sep 17 00:00:00 2001 From: Tom Lienard Date: Wed, 13 Oct 2021 11:31:43 +0200 Subject: [PATCH 3/9] docs: add readme --- README.md | 6 ++ packages/jest-helpers/README.md | 91 ++++++++++++++++++++++++++++++ packages/jest-helpers/package.json | 2 +- 3 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 packages/jest-helpers/README.md diff --git a/README.md b/README.md index b9312dac4..6ba2f7994 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,12 @@ scaleway-lib is a set of NPM packages used at Scaleway. ![npm bundle size](https://img.shields.io/bundlephobia/min/@scaleway/regex) ![npm](https://img.shields.io/npm/v/@scaleway/regex) +- [`@scaleway/jest-helpers`](./packages/jest-helpers/README.md): utilities jest functions. + + ![npm](https://img.shields.io/npm/dm/@scaleway/jest-helpers) + ![npm bundle size](https://img.shields.io/bundlephobia/min/@scaleway/jest-helpers) + ![npm](https://img.shields.io/npm/v/@scaleway/jest-helpers) + ## Development ### Locally diff --git a/packages/jest-helpers/README.md b/packages/jest-helpers/README.md new file mode 100644 index 000000000..eac130995 --- /dev/null +++ b/packages/jest-helpers/README.md @@ -0,0 +1,91 @@ +# `@scaleway/jest-helpers` + +## A package for utilities jest functions + +## Install + +```bash +$ yarn add @scaleway/jest-functions +``` + +## How to use + +### Create the helpers functions + +```tsx +import makeHelpers from '@scaleway/jest-helpers' + +const Wrapper = ({ children }) => ( + {children} +) + +export const { + renderWithTheme, + shouldMatchEmotionSnapshot, + shouldMatchEmotionSnapshotWithPortal, +} = makeHelpers(Wrapper) +``` + +#### With a theme prop + +```tsx +import makeHelpers from '@scaleway/jest-helpers' +import defaultTheme from '..' + +interface WrapperProps { + theme?: typeof defaultTheme +} + +const Wrapper = ({ theme, children }) => ( + {children} +) + +export const { + renderWithTheme, + shouldMatchEmotionSnapshot, + shouldMatchEmotionSnapshotWithPortal, +} = makeHelpers(Wrapper) +``` + +#### With CreateSerializerOptions + +```tsx +import makeHelpers from '@scaleway/jest-helpers' + +const Wrapper = ({ children }) => ( + {children} +) + +export const { + renderWithTheme, + shouldMatchEmotionSnapshot, + shouldMatchEmotionSnapshotWithPortal, +} = makeHelpers(Wrapper, { classNameReplacer: className => className }) +``` + +### renderWithTheme + +Automatically uses `CacheProvider` from `@emotion/cache`. Use it with a component, optional options & optional theme. + +```tsx +const renderWithTheme = ( + component: ReactNode, + options?: RenderOptions, + theme?: Theme, +) => ReturnType +``` + +### shouldMatchEmotionSnapshot / shouldMatchEmotionSnapshotWithPortal + +Internally it uses the `renderWithTheme` generated from above. + +```tsx +const shouldMatchEmotionSnapshot = ( + component: ReactNode, + options: { + options?: RenderOptions + transform?: (node: ReturnType) => Promise | void + theme?: Theme + }, +) => Promise +``` diff --git a/packages/jest-helpers/package.json b/packages/jest-helpers/package.json index ab1ababff..97c32bc6d 100644 --- a/packages/jest-helpers/package.json +++ b/packages/jest-helpers/package.json @@ -1,7 +1,7 @@ { "name": "@scaleway/jest-helpers", "version": "1.0.0", - "description": "A package for jest helpers", + "description": "A package for utilities jest functions", "type": "module", "main": "dist/index.js", "module": "dist/index.js", From a0fd8000ff23f5cc09b3b86f0e6f8612b5cb5a0a Mon Sep 17 00:00:00 2001 From: Tom Lienard Date: Wed, 13 Oct 2021 11:34:20 +0200 Subject: [PATCH 4/9] fix(jest-helpers): eslint no-extraenous-dependencies --- packages/jest-helpers/src/helpers/renderWithTheme.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/jest-helpers/src/helpers/renderWithTheme.tsx b/packages/jest-helpers/src/helpers/renderWithTheme.tsx index 5a012c159..4617a46ce 100644 --- a/packages/jest-helpers/src/helpers/renderWithTheme.tsx +++ b/packages/jest-helpers/src/helpers/renderWithTheme.tsx @@ -1,3 +1,4 @@ +/* eslint-disable import/no-extraneous-dependencies */ /* eslint-disable react/jsx-props-no-spreading */ import createCache from '@emotion/cache' import { CacheProvider } from '@emotion/react' From ea89acab7112cf7552e796b00dfcc1893ed9a0d6 Mon Sep 17 00:00:00 2001 From: Tom Lienard Date: Wed, 13 Oct 2021 11:46:30 +0200 Subject: [PATCH 5/9] chore(deps): add @testing-library/react to peerDeps --- packages/jest-helpers/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/jest-helpers/package.json b/packages/jest-helpers/package.json index 97c32bc6d..ceec5980a 100644 --- a/packages/jest-helpers/package.json +++ b/packages/jest-helpers/package.json @@ -27,6 +27,7 @@ "@emotion/cache": "^11.1.3", "@emotion/jest": "^11.3.0", "@emotion/react": "^11.1.4", + "@testing-library/react": "^12.1.2", "react": "^17.0.1" } } From 5a10bdc8c334c7be84eedf2350b0000976c5f654 Mon Sep 17 00:00:00 2001 From: Tom Lienard Date: Wed, 13 Oct 2021 12:04:11 +0200 Subject: [PATCH 6/9] chore(jest-helpers): add doc to methods fields in readme --- packages/jest-helpers/README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/jest-helpers/README.md b/packages/jest-helpers/README.md index eac130995..42700ce77 100644 --- a/packages/jest-helpers/README.md +++ b/packages/jest-helpers/README.md @@ -69,9 +69,9 @@ Automatically uses `CacheProvider` from `@emotion/cache`. Use it with a componen ```tsx const renderWithTheme = ( - component: ReactNode, - options?: RenderOptions, - theme?: Theme, + component: ReactNode, // The component to render + options?: RenderOptions, // RenderOptions from @testing-library/react + theme?: Theme, // Optional theme to use which will be passed to the Wrapper above ) => ReturnType ``` @@ -81,11 +81,11 @@ Internally it uses the `renderWithTheme` generated from above. ```tsx const shouldMatchEmotionSnapshot = ( - component: ReactNode, - options: { - options?: RenderOptions - transform?: (node: ReturnType) => Promise | void - theme?: Theme + component: ReactNode, // The component to render + options: { // In an object to make it backward-compatible and don't introduce any API breaking changes + options?: RenderOptions // RenderOptions from @testing-library/react + transform?: (node: ReturnType) => Promise | void // (a)sync function execute between the render and the expect. You can use this if you need mockAllIsIntersecting + theme?: Theme // Optional theme to use which will be passed to the Wrapper above }, ) => Promise ``` From ee921f55fd8c723f2ea1eac9b52ee96ea35d9ef4 Mon Sep 17 00:00:00 2001 From: Tom Lienard Date: Wed, 13 Oct 2021 14:54:50 +0200 Subject: [PATCH 7/9] chore(deps): update deps --- packages/jest-helpers/package.json | 13 +++++-------- .../jest-helpers/src/helpers/renderWithTheme.tsx | 2 -- .../src/helpers/shouldMatchEmotionSnapshot.ts | 1 - .../helpers/shouldMatchEmotionSnapshotWithPortal.ts | 1 - 4 files changed, 5 insertions(+), 12 deletions(-) diff --git a/packages/jest-helpers/package.json b/packages/jest-helpers/package.json index ceec5980a..ce6a5433f 100644 --- a/packages/jest-helpers/package.json +++ b/packages/jest-helpers/package.json @@ -15,19 +15,16 @@ "directory": "packages/jest-helpers" }, "license": "MIT", - "devDependencies": { + "dependencies": { "@emotion/cache": "^11.1.3", "@emotion/jest": "^11.3.0", "@emotion/react": "^11.1.4", - "@testing-library/react": "^12.1.2", - "@types/react": "^17.0.27", - "react": "^17.0.1" + "@testing-library/react": "^12.1.2" + }, + "devDependencies": { + "@types/react": "^17.0.27" }, "peerDependencies": { - "@emotion/cache": "^11.1.3", - "@emotion/jest": "^11.3.0", - "@emotion/react": "^11.1.4", - "@testing-library/react": "^12.1.2", "react": "^17.0.1" } } diff --git a/packages/jest-helpers/src/helpers/renderWithTheme.tsx b/packages/jest-helpers/src/helpers/renderWithTheme.tsx index 4617a46ce..877b1e914 100644 --- a/packages/jest-helpers/src/helpers/renderWithTheme.tsx +++ b/packages/jest-helpers/src/helpers/renderWithTheme.tsx @@ -1,5 +1,3 @@ -/* eslint-disable import/no-extraneous-dependencies */ -/* eslint-disable react/jsx-props-no-spreading */ import createCache from '@emotion/cache' import { CacheProvider } from '@emotion/react' import { RenderOptions, render } from '@testing-library/react' diff --git a/packages/jest-helpers/src/helpers/shouldMatchEmotionSnapshot.ts b/packages/jest-helpers/src/helpers/shouldMatchEmotionSnapshot.ts index 126cd62b5..ffbb096e0 100644 --- a/packages/jest-helpers/src/helpers/shouldMatchEmotionSnapshot.ts +++ b/packages/jest-helpers/src/helpers/shouldMatchEmotionSnapshot.ts @@ -1,4 +1,3 @@ -/* eslint-disable import/no-extraneous-dependencies */ import { RenderOptions, render } from '@testing-library/react' import { ReactNode } from 'react' import { RenderWithThemeFn } from './renderWithTheme' diff --git a/packages/jest-helpers/src/helpers/shouldMatchEmotionSnapshotWithPortal.ts b/packages/jest-helpers/src/helpers/shouldMatchEmotionSnapshotWithPortal.ts index d58c2a494..81dd95769 100644 --- a/packages/jest-helpers/src/helpers/shouldMatchEmotionSnapshotWithPortal.ts +++ b/packages/jest-helpers/src/helpers/shouldMatchEmotionSnapshotWithPortal.ts @@ -1,4 +1,3 @@ -/* eslint-disable import/no-extraneous-dependencies */ import { RenderOptions, render } from '@testing-library/react' import { ReactNode } from 'react' import { RenderWithThemeFn } from './renderWithTheme' From 15108c00a58817ba82bb4f38c73dd281d1738f3a Mon Sep 17 00:00:00 2001 From: Tom Lienard Date: Wed, 13 Oct 2021 15:17:16 +0200 Subject: [PATCH 8/9] refactor(jest-helpers): remove initializeIfNeeded --- packages/jest-helpers/src/index.ts | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/packages/jest-helpers/src/index.ts b/packages/jest-helpers/src/index.ts index 67c3f1727..d5f9c1cab 100644 --- a/packages/jest-helpers/src/index.ts +++ b/packages/jest-helpers/src/index.ts @@ -13,24 +13,13 @@ type Helpers = { } export default function makeHelpers(Wrapper: FC<{ theme?: Theme }>, createSerializerOptions?: CreateSerializerOptions): Helpers { - let isInitialized = false - - const initializeIfNeeded = (callback: T) => { - if (!isInitialized) { - isInitialized = true - - // use only class hash (generated from css style content) - expect.addSnapshotSerializer( - createSerializer(createSerializerOptions), - ) - } - - return callback; - } + expect.addSnapshotSerializer( + createSerializer(createSerializerOptions), + ) const renderWithTheme = makeRenderWithTheme(Wrapper) - const shouldMatchEmotionSnapshot = initializeIfNeeded(makeShouldMatchEmotionSnapshot(renderWithTheme)) - const shouldMatchEmotionSnapshotWithPortal = initializeIfNeeded(makeShouldMatchEmotionSnapshotWithPortal(renderWithTheme)) + const shouldMatchEmotionSnapshot = makeShouldMatchEmotionSnapshot(renderWithTheme) + const shouldMatchEmotionSnapshotWithPortal = makeShouldMatchEmotionSnapshotWithPortal(renderWithTheme) return { renderWithTheme, From 4dd39e3ea1e11d7ed387eb0a2c4e04160272ee69 Mon Sep 17 00:00:00 2001 From: Tom Lienard Date: Wed, 13 Oct 2021 16:40:57 +0200 Subject: [PATCH 9/9] feat(jest-helpers): add tests --- .../__snapshots__/index.test.tsx.snap | 55 +++++++++++++++++++ .../jest-helpers/src/__tests__/index.test.tsx | 52 ++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 packages/jest-helpers/src/__tests__/__snapshots__/index.test.tsx.snap create mode 100644 packages/jest-helpers/src/__tests__/index.test.tsx diff --git a/packages/jest-helpers/src/__tests__/__snapshots__/index.test.tsx.snap b/packages/jest-helpers/src/__tests__/__snapshots__/index.test.tsx.snap new file mode 100644 index 000000000..6706c2112 --- /dev/null +++ b/packages/jest-helpers/src/__tests__/__snapshots__/index.test.tsx.snap @@ -0,0 +1,55 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`@jest-helpers should call tranform with shouldMatchEmotionSnapshot 1`] = ` + +
+
+
+ +`; + +exports[`@jest-helpers should call transform with shouldMatchEmotionSnapshot 1`] = ` + +
+
+
+ +`; + +exports[`@jest-helpers should render with renderWithTheme 1`] = ` +
+`; + +exports[`@jest-helpers should render with shouldMatchEmotionSnapshot 1`] = ` + +
+
+
+ +`; + +exports[`@jest-helpers should render with shouldMatchEmotionSnapshotWithPortal 1`] = ` + +
+
+
+ +`; diff --git a/packages/jest-helpers/src/__tests__/index.test.tsx b/packages/jest-helpers/src/__tests__/index.test.tsx new file mode 100644 index 000000000..beefd9578 --- /dev/null +++ b/packages/jest-helpers/src/__tests__/index.test.tsx @@ -0,0 +1,52 @@ +import React from 'react' +import makeHelpers from ".." +import { RenderWithThemeFn } from "../helpers/renderWithTheme" +import { ShouldMatchEmotionSnapshotFn } from '../helpers/shouldMatchEmotionSnapshot' +import { ShouldMatchEmotionSnapshotWithPortalFn } from '../helpers/shouldMatchEmotionSnapshotWithPortal' + +describe('@jest-helpers', () => { + let renderWithTheme: RenderWithThemeFn + let shouldMatchEmotionSnapshot: ShouldMatchEmotionSnapshotFn + let shouldMatchEmotionSnapshotWithPortal: ShouldMatchEmotionSnapshotWithPortalFn + + beforeAll(() => { + const helpers = makeHelpers(({ children }) => ( +
+ {children} +
+ )) + + renderWithTheme = helpers.renderWithTheme + shouldMatchEmotionSnapshot = helpers.shouldMatchEmotionSnapshot + shouldMatchEmotionSnapshotWithPortal = helpers.shouldMatchEmotionSnapshotWithPortal + }) + + test('should render with renderWithTheme', () => { + const node = renderWithTheme(
) + const element = node.getByTestId("test") + + expect(element).toMatchSnapshot() + }) + + test('should render with shouldMatchEmotionSnapshot', async () => { + await shouldMatchEmotionSnapshot(
) + }) + + test('should call tranform with shouldMatchEmotionSnapshot', async () => { + const transform = jest.fn() + await shouldMatchEmotionSnapshot(
, { transform }) + + expect(transform).toHaveBeenCalledTimes(1) + }) + + test('should render with shouldMatchEmotionSnapshotWithPortal', async () => { + await shouldMatchEmotionSnapshotWithPortal(
) + }) + + it('should call transform with shouldMatchEmotionSnapshot', async () => { + const transform = jest.fn() + await shouldMatchEmotionSnapshotWithPortal(
, { transform }) + + expect(transform).toHaveBeenCalledTimes(1) + }) +}) \ No newline at end of file