Jest-styled-components: Snapshots now adding full html DOM, why?

Created on 2 Jul 2018  ·  4Comments  ·  Source: styled-components/jest-styled-components

I just re-ran my tests after screwing around with Babel and my build system (bad idea I know) and now my styled-components snapshots have completely changed. Each component renders as it should but now the snapshot is wrapped by a full DOM ( etc etc), any ideas why? Is it ok or a bug?

FYI I'm using https://www.npmjs.com/package/react-testing-library to 'render' in the tests.

Before snapshot:

// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Link snapshot 1`] = `
Object {
  "container": <div>
    <a
      class="sc-bdVaJa dOvzuO"
      href="https://google.com"
    >
      This is a link
    </a>
  </div>,
  "debug": [Function],
  "getAllByAltText": [Function],
  "getAllByLabelText": [Function],
  "getAllByPlaceholderText": [Function],
  "getAllByTestId": [Function],
  "getAllByText": [Function],
  "getAllByTitle": [Function],
  "getAllByValue": [Function],
  "getByAltText": [Function],
  "getByLabelText": [Function],
  "getByPlaceholderText": [Function],
  "getByTestId": [Function],
  "getByText": [Function],
  "getByTitle": [Function],
  "getByValue": [Function],
  "queryAllByAltText": [Function],
  "queryAllByLabelText": [Function],
  "queryAllByPlaceholderText": [Function],
  "queryAllByTestId": [Function],
  "queryAllByText": [Function],
  "queryAllByTitle": [Function],
  "queryAllByValue": [Function],
  "queryByAltText": [Function],
  "queryByLabelText": [Function],
  "queryByPlaceholderText": [Function],
  "queryByTestId": [Function],
  "queryByText": [Function],
  "queryByTitle": [Function],
  "queryByValue": [Function],
  "rerender": [Function],
  "unmount": [Function],
}
`;

After snapshot:

Notice that <html> and a full 'page' has been added to the snapshot.. 😕

// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Link snapshot 1`] = `
Object {
  "baseElement": <html>
    <head>
      <style
        data-styled-components=""
      >


/* sc-component-id: sc-bdVaJa */
.sc-bdVaJa {} .dOvzuO{-webkit-text-decoration:none;text-decoration:none;color:#007C98;-webkit-transition:all 300ms cubic-bezier(0.77,0,0.175,1);transition:all 300ms cubic-bezier(0.77,0,0.175,1);} .dOvzuO:hover,.dOvzuO:focus{-webkit-text-decoration:underline;text-decoration:underline;color:#005E73;}
      </style>
    </head>
    <body>
      <div>
        <a
          class="sc-bdVaJa dOvzuO"
          href="https://google.com"
        >
          This is a link
        </a>
      </div>
    </body>
  </html>,
  "container": <div>
    <a
      class="sc-bdVaJa dOvzuO"
      href="https://fairfx.com"
    >
      This is a link
    </a>
  </div>,
  "debug": [Function],
  "getAllByAltText": [Function],
  "getAllByLabelText": [Function],
  "getAllByPlaceholderText": [Function],
  "getAllByTestId": [Function],
  "getAllByText": [Function],
  "getAllByTitle": [Function],
  "getAllByValue": [Function],
  "getByAltText": [Function],
  "getByLabelText": [Function],
  "getByPlaceholderText": [Function],
  "getByTestId": [Function],
  "getByText": [Function],
  "getByTitle": [Function],
  "getByValue": [Function],
  "queryAllByAltText": [Function],
  "queryAllByLabelText": [Function],
  "queryAllByPlaceholderText": [Function],
  "queryAllByTestId": [Function],
  "queryAllByText": [Function],
  "queryAllByTitle": [Function],
  "queryAllByValue": [Function],
  "queryByAltText": [Function],
  "queryByLabelText": [Function],
  "queryByPlaceholderText": [Function],
  "queryByTestId": [Function],
  "queryByText": [Function],
  "queryByTitle": [Function],
  "queryByValue": [Function],
  "rerender": [Function],
  "unmount": [Function],
}
`;

Test file:

import React from 'react'
import { render, cleanup } from 'react-testing-library'

import Link from './index'

afterEach(cleanup)

test('Link snapshot', () => {
  const tree = render(<Link href="https://google.com">This is a link</Link>)
  expect(tree).toMatchSnapshot()
})

Component source:

import React from 'react'
import styled from 'styled-components'
import tokens from '../../../tokens'

export default styled('a')`
  text-decoration: none;
  color: ${({ inverse }) =>
    inverse ? tokens.color('linkInverse') : tokens.color('link')};
  transition: ${tokens.get('transition.default.transition')};

  &:hover,
  &:focus {
    text-decoration: underline;
    color: ${({ inverse }) =>
      inverse
        ? tokens.color('linkInverse', 'over')
        : tokens.color('link', 'over')};
  }
`

.babelrc

{
  "presets": [
    [
      "env",
      {
        "modules": false
      }
    ],
    "react"
  ],
  "plugins": [
    "transform-object-rest-spread",
    [
      "babel-plugin-styled-components",
      {
        "displayName": true
      }
    ]
  ],
  "env": {
    "test": {
      "presets": [
        [
          "env",
          {
            "modules": "commonjs",
            "debug": false
          }
        ],
        "react",
        "jest"
      ]
    },
    "production": {
      "plugins": [
        "transform-object-rest-spread",
        [
          "babel-plugin-styled-components",
          {
            "displayName": false
          }
        ]
      ],
    }
  }
}

Let me know if I can provide more info.

help wanted react testing library

Most helpful comment

Hi friends.

Definitely do NOT snapshot the entire object you get back from render. It has a TON of stuff in there that's totally irrelevant for your tests.

If you want to snapshot the entire rendered element, then do:

const {container} = render(<Foo />)
expect(container).toMatchSnapshot()

Note that the container will always be a div so it's probably not necessary to include it in a snapshot, so you can simplify things if you do:

const {container} = render(<Foo />)
expect(container.firstChild).toMatchSnapshot()

Note: this will only work if your component renders a single element rather than an array or fragment.

Good luck!

All 4 comments

Hello @mrmartineau,
unfortunately, I'm not familiar with react-testing-library, but there's another issue around it (#129).

To me, even the snapshot before was wrong, as I would expect it to look more like this:

<div>
  <a
    class="sc-bdVaJa dOvzuO"
    href="https://google.com"
  >
    This is a link
  </a>
</div>

Let's if someone is able to help.

@MicheleBertoli thanks, I had thought that it was this jest-styled-components that caused the issue but perhaps react-testing-library. I will raise a ticket there to see if that produces any answers.

Hi friends.

Definitely do NOT snapshot the entire object you get back from render. It has a TON of stuff in there that's totally irrelevant for your tests.

If you want to snapshot the entire rendered element, then do:

const {container} = render(<Foo />)
expect(container).toMatchSnapshot()

Note that the container will always be a div so it's probably not necessary to include it in a snapshot, so you can simplify things if you do:

const {container} = render(<Foo />)
expect(container.firstChild).toMatchSnapshot()

Note: this will only work if your component renders a single element rather than an array or fragment.

Good luck!

@kentcdodds thank you! I did not know that. Did I miss that somewhere in the documentation?

Was this page helpful?
0 / 5 - 0 ratings