Patrick Lu
Patrick Lu

Reputation: 111

Invalid Chai property: toMatchSnapshot -- React.js Jest testing

I'm getting an error: Invalid Chai property: toMatchSnapshot when I try to use Jest + Enzyme's snapshot testing. I've updated my React version to 16.2 and I use enzyme-to-json library with Enzyme 3.

Code is below:

import React from 'react';
import ReactDOM from 'react-dom';
import ConnectedApp, { App } from './App';
import { ConnectedRouter } from 'react-router-redux';
import { Provider } from 'react-redux';
import { expect } from 'chai';
import { mount, shallow } from 'enzyme';
import createHistory from 'history/createMemoryHistory'
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import toJson from 'enzyme-to-json';

describe('App tests', () => {
  const middlewares = [thunk];
  const mockStore = configureMockStore(middlewares);
  let store, container, history, wrapper;

  const initialState = {
    output: true
  }

  beforeEach(() => {
    store = mockStore(initialState);
    history = createHistory();
    wrapper = mount(
      <Provider store={store}>
        <ConnectedRouter history={history}>
          <ConnectedApp />
        </ConnectedRouter>
      </Provider>
    )  
  });

  it('+++capturing Snapshot of App', () => {
    expect(toJson(wrapper)).toMatchSnapshot();
  });
})

I've also tried this with Jest's render like so:

import renderer from 'react-test-renderer';

it('renders correctly', () => {
  var component = <Provider store={store}>
                    <ConnectedRouter history={history}>
                      <ConnectedApp />
                    </ConnectedRouter>
                   </Provider>
  const tree = renderer
    .create(component)
    .toJSON();
  expect(tree).toMatchSnapshot();
});

But I still get the Invalid Chai property: toMatchSnapshot error. Anyone know what's up?

Upvotes: 10

Views: 10154

Answers (4)

snicker
snicker

Reputation: 41

For those transitioning away from chai (which would be hijacking expect() from jest in the top level setupTests.js file) the simpler solution is to load jest's expect() again on top of the current test file like so:

import { expect } from "@jest/globals";

That is, until you can't fully do away with any

global.expect = chai.expect;

somewhere in the code, setupTests.js for example.

Upvotes: 1

Alok Ranjan
Alok Ranjan

Reputation: 1097

This is partially related to this post & root cause given by other authors are quite accurate and very informative.

I also faced same problem as discussed in this post, when I was trying to use expect(container).toHaveLength(1);

I solved this issue by changing my way to write assertion in Jest way like, expect(container).to.have.length(1);

So basically we need to find way to change our assertion to write in Jest way, if we are using Jest.

Hope it may help someone.

Upvotes: -2

shubham pandey
shubham pandey

Reputation: 77

Its Simple.Just write your test scripts (something.spec.js) in to another file without importing 'chai' . It will work like a charm. No need for messy stuffs.Keep it Simple !

Upvotes: 0

Sanborn
Sanborn

Reputation: 289

This isn't an issue with the renderer you are using. The problem is that you are using chai expectations instead of the expectation library that ships with jest. The chai API has no toMatchSnapshot method. To fix it you can do the following:

  1. Stop using chai and use the jest expectations exclusively. This may simply be a matter of removing line 6: import { expect } from 'chai'

However, if you need to continue to use chai (i.e. you have a lot of chai tests already written and you don't want to do a major overhaul all at once) you can do two things:

  1. Alias either the the chai or jest expect functions in your test setup file e.g. global.chaiExpect = chai.expect
  2. Monkey-patch the global expect function so that you can use both the chai and the jest API like in this blog post: https://medium.com/@RubenOostinga/combining-chai-and-jest-matchers-d12d1ffd0303

    The relevant bit is this:

// Make sure chai and jasmine ".not" play nice together
const originalNot = Object.getOwnPropertyDescriptor(chai.Assertion.prototype, 'not').get;
Object.defineProperty(chai.Assertion.prototype, 'not', {
  get() {
    Object.assign(this, this.assignedNot);
    return originalNot.apply(this);
  },
  set(newNot) {
    this.assignedNot = newNot;
    return newNot;
  },
});

// Combine both jest and chai matchers on expect
const originalExpect = global.expect;

global.expect = (actual) => {
  const originalMatchers = originalExpect(actual);
  const chaiMatchers = chai.expect(actual);
  const combinedMatchers = Object.assign(chaiMatchers, originalMatchers);
  return combinedMatchers;
}; 

Upvotes: 7

Related Questions