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

withStyles break enzyme tests #9266

Closed
Skaronator opened this issue Nov 22, 2017 · 20 comments
Closed

withStyles break enzyme tests #9266

Skaronator opened this issue Nov 22, 2017 · 20 comments
Labels
support: question Community support but can be turned into an improvement test

Comments

@Skaronator
Copy link
Contributor

Skaronator commented Nov 22, 2017

Seems like when using the withStyles HOC it'll actually break my Jest test. It creates children elements where it shouldn't.

Here is the code to reproduce it:

import React from 'react';
import ReactDOM from 'react-dom';
import { shallow } from 'enzyme';

import withStyles from 'material-ui/styles/withStyles';
import LoadingWrapper from './LoadingWrapper';

const ReproBug = ({ loading, children }) => {
  if (loading) {
    return <span>Loading...</span>;
  }
  return children;
}
const ReproBugWithStyles = withStyles({})(ReproBug);


const children = <span>Dummy Children!</span>;

it('should not render children if loading is true', () => {
  const wrapper = shallow(
    <ReproBug loading={true}>{children}</ReproBug>
  );
  expect(wrapper.contains(children)).toEqual(false);
});

it('should not render children if loading is true', () => {
  const wrapper = shallow(
    // using ReproBugWithStyles instead of ReproBug
    <ReproBugWithStyles loading={true}>{children}</ReproBugWithStyles>
  );
  expect(wrapper.contains(children)).toEqual(false); //<--- this check fails, it is actually true
});

I use the create-react-test and simply run yarn test. (they use Jest and enzyme IIRC)

@Skaronator
Copy link
Contributor Author

Skaronator commented Nov 22, 2017

I also notice this in "real world" usage beside the jest test. For example I use this kind of logic on my <LoadingWrapper> for my Apollo requests and Apollo set the loading and data (and some more) variable. So I could make a simple Wrapper which avoid loading the children elements as long as data isn't recieved.

<LoadingWrapper loading={loading}>
    <UseDataElement data={data} />
</LoadingWrapper>

With this bug the <UseDataElement> element is actually "rendered" (it is not) or at least triggered so I receive propTypes warning for missing data.

@Skaronator Skaronator changed the title withStyles break Jest tests withStyles break enzyme tests Nov 22, 2017
@Skaronator
Copy link
Contributor Author

Skaronator commented Nov 22, 2017

Mh I'll get similar errors when trying some of your intern testing code. For example when trying this:
https://github.com/mui-org/material-ui/blob/930937827c58f9468299e9760ac9f88e2b34ebcd/src/Divider/Divider.spec.js#L17-L20

I'll get this error:

Expected value to equal:
      "hr"
Received:
      "Divider"

Maybe I should use your testing scripts instead of the create-react-app ones.

@lambbyrd
Copy link

@Skaronator I was having a ton of issues testing my application. Once I found Mui's docs on testing and used their Shallow and Mount I had no issues.

@oliviertassinari oliviertassinari added test support: question Community support but can be turned into an improvement labels Dec 5, 2017
@oliviertassinari
Copy link
Member

oliviertassinari commented Dec 5, 2017

It creates children elements where it shouldn't

@Skaronator The issue isn't about the children elements but with the intermediary element, it's creating. The shallow() API of enzyme only render one level depth. Any higher-order component is going to obfuscate the children. You have different workarounds. I would encourage you to refer to the enzyme documentation. Still, here they are:

@FahdW
Copy link

FahdW commented Jan 5, 2018

@codepressd how did you manage to get testing working? I keep getting issues like find isn't a function. I cannot target my clickable objects for the life of me.

@Skaronator
Copy link
Contributor Author

@FahdW I'm using create-react-app and therefore Jest for the test. find() works fine for me but I use childAt(<int>) or at(<int>) most of the time. Here is a click test I'm using:

import React from 'react';
import ReactDOM from 'react-dom';
import { createShallow, getClasses } from 'material-ui/test-utils';

import AppDrawerElements from './AppDrawerElements';

describe('<AppDrawerElements />', () => {
  let shallow;

  const TestIcon = () => <span>Not a Icon</span>;

  const URL = {
    display: {
      url: '/theUrl/with/more',
      name: 'Testing...',
      display: true,
      icon: <TestIcon />,
    },
  };

  beforeAll(() => {
    shallow = createShallow({ dive: true });
  });

  it('should fire onClose when click the close button', () => {
    const onCloseMock = jest.fn();
    const onClose = jest.fn(() => {
      onCloseMock();
    });

    const wrapper = shallow(<AppDrawerElements url={URL} onClose={onClose} />);

    wrapper
      .childAt(0)
      .childAt(0)
      .childAt(0)
      .simulate('click');
    expect(onCloseMock).toBeCalled();
  });
});

@FahdW
Copy link

FahdW commented Jan 5, 2018

@Skaronator Thanks for this! How would you test if the function itself was contained in the component? I am guessing you call a spy, so far jest's spy has been underwhelming and I have yet to get it to work. I was going to send a spy onto my dispatch to make sure that some of the internal functions are firing off dispatch calls. But this is good to point me in the right direction.

@mbrookes
Copy link
Member

mbrookes commented Jan 5, 2018

@FahdW You might find it helpful to look at some of Material-UI's own tests.

@FahdW
Copy link

FahdW commented Jan 5, 2018

@mbrookes Thanks will take a look at your source, hopefully find something to help me.

@a-h
Copy link

a-h commented Mar 24, 2018

I had some trouble getting my head around why shallow wasn't working for some tests when I started using withStyles, so I broke it down into a few self-contained examples at https://gist.github.com/a-h/21df0f432ae02a6dfed941debb0e5950

Once I did that, I realised that I needed to switch from shallow to mount since withStyles is a higher order component and 'wraps' the other component.

@charliecalvert
Copy link

charliecalvert commented May 30, 2018

I found that material-ui was not breaking my tests even when using withStyles and that this worked just fine using plain old enzyme:

import { configure, shallow } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
configure({ adapter: new Adapter() });

// CODE OMITTED HERE

it('renders title matches it with containsMatchingElement', () => {
     const wrapper = shallow(<ElfHeader />);
     const target = <Typography>Address Maven</Typography>;
     expect(wrapper.dive().containsMatchingElement(target)).toBe(true);
});

Here was the JSX I wanted to match:

<Typography variant="title" color="inherit" className={classes.flex}>
    Address Maven
</Typography>

And here was the messy code material-ui produced:

<WithStyles(Typography) variant="title" color="inherit" className="ElfHeader-flex-100">
       Address Maven
</WithStyles(Typography)>

Nevertheless, my test passed.

I say this only because this thread is a bit misleading for those who get errors and don't know their source. I guess my point is simply that in most cases, your tests should pass. Note this line from the docs: "You can take advantage of them if you so choose." Not that you have to use them, but use them if you find them convenient.

https://material-ui.com/guides/testing/

@byverdu
Copy link

byverdu commented Nov 16, 2018

The shallow = createShallow({ dive: true }); totally made my day... 🎆

@MatteoGioioso
Copy link

Why this issue is closed?
None of those is working for me,
Still get displayed with
<WithStyles(Component)

Cannot go past through it...

@jondbm
Copy link

jondbm commented Dec 8, 2018

I'm having the same issue as Matteo. When testing the output in Jest i get <WithStyles(MaterialComponent) when I want to test for <MaterialComponent

For example if I want to see if a Drawer component is present I have to test for <WithStyles(Drawer.

Is there a way to get the test render to be the unwrapped component? or is the only way to test for the <WithStyles(... version?

@oliviertassinari
Copy link
Member

It shouldn't be too long before we start/try using hooks over higher-order component internally for the styles. I'm not sure what is the implication for shallow rendering. It will most likely solve this class of issues.

@jondbm
Copy link

jondbm commented Dec 8, 2018

I solved my issue, was an obvious fix. I was using the component name in quotes eg .find('Avatar') instead of importing it into the test and calling it directly .find(Avatar) - no quotes. That worked.

@MatteoGioioso
Copy link

@jondbm Solved the same way

@ShreeGiriKumar

This comment has been minimized.

@ShreeGiriKumar

This comment has been minimized.

@ShreeGiriKumar

This comment has been minimized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
support: question Community support but can be turned into an improvement test
Projects
None yet
Development

No branches or pull requests