Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/2139 jest snapshots #2233

Merged
merged 10 commits into from
Feb 8, 2021
5 changes: 5 additions & 0 deletions .changeset/two-laws-provide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@emotion/jest': patch
---

Fix issue creating enzyme snapshots for components using an array as the css prop.
Andarist marked this conversation as resolved.
Show resolved Hide resolved
39 changes: 34 additions & 5 deletions packages/jest/src/create-serializer.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,34 @@ function filterEmotionProps(props = {}) {
return rest
}

function isShallowEnzymeElement(element: any, classNames: string[]) {
function getLabelsFromCss(css) {
const getLabel = style => {
const styleString = style.styles || style
const matches = styleString.match(/.*;label:([^;]+);/)
return matches && matches[1]
}
return (Array.isArray(css) ? css.map(getLabel) : [getLabel(css)]).filter(
Boolean
)
}

function isShallowEnzymeElement(
element: any,
keys: string[],
labels: string[]
) {
const delimiter = ' '
const childClassNames = flatMap(element.children || [], ({ props = {} }) =>
(props.className || '').split(delimiter)
).filter(Boolean)
return !hasIntersection(classNames, childClassNames)
return !childClassNames.some(className => {
const [childKey, hash, ...childLabels] = className.split('-')
return (
keys.includes(childKey) &&
childLabels.length &&
childLabels.every(childLabel => labels.includes(childLabel))
)
})
}

const createConvertEmotionElements = (keys: string[], printer: *) => (
Expand All @@ -104,13 +126,20 @@ const createConvertEmotionElements = (keys: string[], printer: *) => (
return node
}
if (isEmotionCssPropEnzymeElement(node)) {
const cssClassNames = (node.props.css.name || '').split(' ')
const labels = getLabelsFromCss(node.props.css)
const cssName = Array.isArray(node.props.css)
? node.props.css
.map(({ name }) => name)
.filter(Boolean)
.join(' ')
: node.props.css.name
const cssClassNames = (cssName || '').split(' ')
const expectedClassNames = flatMap(cssClassNames, cssClassName =>
keys.map(key => `${key}-${cssClassName}`)
)
// if this is a shallow element, we need to manufacture the className
// since the underlying component is not rendered.
if (isShallowEnzymeElement(node, expectedClassNames)) {
if (isShallowEnzymeElement(node, keys, labels)) {
const className = [node.props.className]
.concat(expectedClassNames)
.filter(Boolean)
Expand All @@ -128,7 +157,7 @@ const createConvertEmotionElements = (keys: string[], printer: *) => (
type
}
} else {
return node.children
return node.children[0]
}
}
if (isEmotionCssPropElementType(node)) {
Expand Down
61 changes: 52 additions & 9 deletions packages/jest/test/__snapshots__/react-enzyme.test.js.snap
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`enzyme child containing css array property 1`] = `
.emotion-0 {
background-color: black;
}

.emotion-1 {
color: white;
}

<div
className="emotion-0"
>
Test content
<div
className="emotion-1"
/>
</div>
`;

exports[`enzyme mount basic 1`] = `
.emotion-0 {
background-color: red;
Expand Down Expand Up @@ -114,6 +133,19 @@ exports[`enzyme mount theming 1`] = `
</div>
`;

exports[`enzyme mount using the css helper 1`] = `
.emotion-0 {
background-color: black;
color: white;
}

<div
className="emotion-0"
>
Test content
</div>
`;

exports[`enzyme mount with prop containing css element 1`] = `
.emotion-0 {
background-color: blue;
Expand Down Expand Up @@ -251,17 +283,15 @@ exports[`enzyme mount with styles on top level 1`] = `
background-color: red;
}

Array [
<Greeting
<Greeting
className="emotion-0"
>
<div
className="emotion-0"
>
<div
className="emotion-0"
>
Hello
</div>
</Greeting>,
]
Hello
</div>
</Greeting>
`;

exports[`enzyme shallow basic 1`] = `
Expand Down Expand Up @@ -343,6 +373,19 @@ exports[`enzyme shallow theming 1`] = `
</div>
`;

exports[`enzyme shallow using the css helper 1`] = `
.emotion-0 {
background-color: black;
color: white;
}

<div
className="emotion-0"
>
Test content
</div>
`;

exports[`enzyme shallow with prop containing css element 1`] = `
.emotion-0 {
background-color: blue;
Expand Down
34 changes: 33 additions & 1 deletion packages/jest/test/react-enzyme.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import 'test-utils/enzyme-env'

import jestInCase from 'jest-in-case'
import * as enzyme from 'enzyme'
import { jsx, ThemeProvider } from '@emotion/react'
import { css, jsx, ThemeProvider } from '@emotion/react'
import styled from '@emotion/styled'
import React from 'react'
import toJson from 'enzyme-to-json'
Expand Down Expand Up @@ -143,6 +143,19 @@ const cases = {
)
}
},
'with array of styles as css prop': {
render() {
const style1 = css`
background-color: black;
`

const style2 = css`
color: white;
`

return <div css={[style1, style2]}>Test content</div>
}
},
theming: {
render() {
const Button = styled.button`
Expand Down Expand Up @@ -191,6 +204,25 @@ describe('enzyme', () => {
cases
)

test('parent and child using css property', () => {
const parentStyle = css`
background-color: black;
`

const childStyle = css`
color: white;
`

const wrapper = enzyme.mount(
<div css={parentStyle}>
Test content
<div css={childStyle} />
</div>
)

expect(wrapper).toMatchSnapshot()
})

test('with prop containing css element in fragment', () => {
const FragmentComponent = () => (
<React.Fragment>
Expand Down