GithubHelp home page GithubHelp logo

Comments (30)

koba04 avatar koba04 commented on April 27, 2024 38

@bricejlin
#318 is hidden in the lifecycleExperimental flag.
You can do with the flag for enabling all lifecycle methods in shallow.

shallow(<Foo />, { lifecycleExperimental: true })

from enzyme.

CurtisHumphrey avatar CurtisHumphrey commented on April 27, 2024 10

At the moment I'm doing

const prevProp = wrapper.props()
wrapper.setProps({
  current_step: 2,
})
// forces an update call to componentDidUpdate - https://github.com/airbnb/enzyme/issues/34
wrapper.instance().componentDidUpdate(prevProp)

from enzyme.

LiangMingChen avatar LiangMingChen commented on April 27, 2024 6

The latest update seems to broke this again.
node_modules/enzyme/build/ShallowWrapper.js
line 552

   if (lifecycles.componentDidUpdate && typeof instance.componentDidUpdate === 'function' && (!state || (0, _Utils.shallowEqual)(state, _this3.instance().state))) {
                    instance.componentDidUpdate(prevProps, state, snapshot);
                  }

The last condition make it that only state change will trigger instance.componentUpdate,

from enzyme.

jose920405 avatar jose920405 commented on April 27, 2024 2

In react-native lifecycleExperimental works for componentDidMount() but not for componentDidUpdate().

"name": "enzyme",
"version": "3.1.0",
"react": "16.0.0",
"react-native": "0.47.2",

#1279

from enzyme.

justinmckenzie avatar justinmckenzie commented on April 27, 2024 2

Sorry to bring an old thread back up, but I'm running into a similar issue detailed here, and I can't seem to find any other solutions when searching. Here's my test:

  it('should reset gridWrapperNode scrollTop position if data has changed', () => {
    const mounted = mount(<Grid {...props} />);

    const gridNode = document.createElement('div');
    const gridWrapper = document.createElement('div');

    gridWrapper.classList.add('datagrid-grid-wrapper');
    gridNode.appendChild(gridWrapper);

    mounted.instance().gridNode = gridNode;

    gridWrapper.scrollTop = 40;
    mounted.instance().lastScrollTop = 40;

    mounted.setProps({
      ...props,
      data: [{ val: 'someNewData' }],
    });

    // mounted.instance().componentDidUpdate({});

    expect(gridWrapper.scrollTop).toEqual(0);
    expect(mounted.instance().lastScrollTop).toEqual(0);
  });

When I uncomment out // mounted.instance().componentDidUpdate({});, it works as expected, however I'm expecting the componentDidUpdate method to be called with the props changing. I checked, the props are updating as they should so I was wondering if this is a known issue or if it's something I'm doing wrong?

from enzyme.

blainekasten avatar blainekasten commented on April 27, 2024 1

FWIW, setProps is being deprecated.

https://github.com/facebook/react/pull/5588/files
http://facebook.github.io/react/blog/2015/10/07/react-v0.14.html#new-deprecations-introduced-with-a-warning

from enzyme.

lelandrichardson avatar lelandrichardson commented on April 27, 2024 1

@blainekasten thanks for that info. Funny - I didn't even know .setProps() existed as a real API.

The deprecation doesn't affect us in this case, since .setProps() is achieved using setState() of a parent wrapper component, anyway.

from enzyme.

gatispriede avatar gatispriede commented on April 27, 2024 1

Solved it by using

         wrapper.setProps({
            user: {
                test: {error: "test"}
            }
        });

        wrapper.find('.smth').simulate('click');

Works as a charm, setprops are set, you just need to call a function again that triggers the component o re-render, it will trigger the componentDidUpdate function

from enzyme.

anorudes avatar anorudes commented on April 27, 2024

+1, how correctly to solve the problem?)

from enzyme.

aweary avatar aweary commented on April 27, 2024

I'm betting this will be resolved by #318

from enzyme.

erikthedeveloper avatar erikthedeveloper commented on April 27, 2024

I'm also performing similar hacks to what @CurtisHumphrey mentioned above.

I wonder what the preferred way of achieving this is, if not with setProps? I have yet to dig in too deep myself, but this is something I am definitely interested in contributing to. It looks like #318 is on a good track.

from enzyme.

blainekasten avatar blainekasten commented on April 27, 2024

#318 is now merged. Do we know if this is still a problem? Can any of the affected devs here confirm?

from enzyme.

bricejlin avatar bricejlin commented on April 27, 2024

hi @blainekasten I'm using the latest release 2.4.1 and it still hasn't fixed the issue. I ended up having to use mount to trigger the componentDidUpdate. Would love to just use shallow instead

from enzyme.

aweary avatar aweary commented on April 27, 2024

Closing since this should be resolved by using lifecycleExperimental flag.

from enzyme.

mrbinky3000 avatar mrbinky3000 commented on April 27, 2024

FWIW, I think @CurtisHumphrey 's approach is closest to the best approach. Why do people find it necessary to test if React fires a lifecycle event? If React fails to go through lifecycle events, then React has a larger issue. Testing if react fires a lifecycle event when a prop updates is pointless. The whole point of React is to "react" to prop and state changes. It's like testing to make sure image.onload, or window.onload fires in a browser. If these built-in browser events fail to fire in Chrome when they are supposed to fire, then Google is out of business the next day.

I think in general, people over-test things that don't need to be tested. I also think that people forget that your React components are 90% vanilla javascript.

You don't always need enzyme. React is just javascript. If your ES6 class constructor looks like this...

constructor(props) {
  super(props);
  // other stuff here...
}

Then you can test if componentDidUpdate works correctly, without having to test if React fires it when it's supposed to fire it.

describe('componentDidUpdate()', () => {
  it('should do something', () => {
    const prevProps = { // define previous props };
    const prevState = { // define previous state if needed };
    const instance = new MyComponent({ // new props go here });
    instance.state = { // if you need a new set state, set it here };
    // some method called by componetDidUpdate when there is an update.
    instance.someMethod = jest.fn(); 
    instance.componentDidUpate(prevProps, prevState);
   // expect stuff here.  
   expect(instance.someMethod).toHaveBeenCalledWith( stuff ); 
  })
})

This is what is called "unit testing" a class method. Enzyme shallow() is not a unit test. It is an integration test. Enzyme shallow() mounts a shallow version of a component in a virtual browser.
A true unit test only focuses on a function or method.

The test above tests the inputs of the componentDidUpdate() class method, tests the expected side effects of the class method, and does all of this without redundantly testing if React works.

I like Enzyme, but it is not always the answer.

from enzyme.

ljharb avatar ljharb commented on April 27, 2024

@mrbinky3000 First, you should be using testing a component the way it's used - new MyComponent is never how it's used in production, so that test is not very valuable.

As for "integration test", everything should be an integration test - if it's not one, then your test has to have knowledge about the implementation under test, which is coupling, and makes your tests more brittle.

Enzyme certainly isn't always the answer, but setting up a contrived scenario to test something in an environment in which it never runs in production gives you nothing but false confidence.

from enzyme.

mrbinky3000 avatar mrbinky3000 commented on April 27, 2024

Sorry if this was off-topic. I can discuss this further offline if you want. I've been thinking about this for a while now and would like to know more about why you think this is bad. But here are some things to consider.

  1. All tests are contrived.
  2. If you properly unit test all the class methods and/or functions for a given Component, then the sum of your units should be ok. Garbage in garbage out, and vice versa.
  3. You still need integration tests like shallow and mount. For example, I still use them to test any conditional statements in a render() method. My argument is people need a fraction of the shallow and mount tests that they create today.

from enzyme.

ljharb avatar ljharb commented on April 27, 2024

The sum of your unit tests is not equal to integration tests. You might be able to “get by” with more focused unit tests and fewer wrappers, but those aren’t better tests - those are more contrived since, unlike the wrappers, they don’t mimic production usage.

from enzyme.

ljharb avatar ljharb commented on April 27, 2024

@LiangMingChen could you file a new issue about this, and fill in the entire issue template? That would really help it get fixed quickly.

from enzyme.

fttriquet avatar fttriquet commented on April 27, 2024

@ljharb @LiangMingChen I'm encountering that as well, was the issue created ?

from enzyme.

ljharb avatar ljharb commented on April 27, 2024

Nope, please file one :-)

from enzyme.

fttriquet avatar fttriquet commented on April 27, 2024

Nope, please file one :-)

Turns out it works sorry

from enzyme.

ljharb avatar ljharb commented on April 27, 2024

@Jmac1523 try adding mounted.update().

from enzyme.

justinmckenzie avatar justinmckenzie commented on April 27, 2024

@ljharb I tried, unfortunately to no avail. Is the test less-effective or even ineffective with mounted.instance().componentDidUpdate({}); ?

from enzyme.

ljharb avatar ljharb commented on April 27, 2024

@Jmac1523 can you file a new issue?

from enzyme.

justinmckenzie avatar justinmckenzie commented on April 27, 2024

sure, thanks for getting back to me!

from enzyme.

jasonwr avatar jasonwr commented on April 27, 2024

@Jmac1523 that instance call will only work on state based components. I suppose lifecycle methods only exist in those but then there is the challenge of testing the useEffect method (on update, render, etc.). IMHO there needs to be some support for this from the Enzyme team. shallow doesn't buy you much as Enzyme shallow isn't going to be tied into your lifecycle methods.

from enzyme.

justinmckenzie avatar justinmckenzie commented on April 27, 2024

Err...I know, I never said I was using Hooks

from enzyme.

jasonwr avatar jasonwr commented on April 27, 2024

@Jmac1523 I realize that but with so many components being developed with hooks and moving away from state based it's worth noting. If you find any leads on this let me know. I'm doing some research on a state based approach now. This is something that needs attention from the Enzyme team.

from enzyme.

jasonwr avatar jasonwr commented on April 27, 2024

@Jmac1523 and everyone else. This solution seems to work nicely for testing state-based component lifecycle methods:

it('should call componentDidUpdate', () => {
  let node = document.createElement('div');
  let instance = ReactDOM.render(table, node);
  const spy = jest.spyOn(Table.prototype, 'componentDidUpdate');
  ReactDOM.render(modifiedTable, node);
  expect(spy).toHaveBeenCalled();
})

This is hitting that component during runtime:

image

Ultimately what I'm doing here is setting the table (JSX) on the DOM then just loading in a table with modified properties. Here's the table in Jest:

const justTheTable = (
    <Table
      data={fossilsMainDirectory}
      defaultSortType="string"
      defaultSortKey="class"
      defaultSortAsc={true}
      columnConfiguration={columns.desktop}
      tabletOverrideColumnConfiguration={columns.tablet}
      mobileOverrideColumnConfiguration={columns.mobile}
    >
      {({ filter }) => {
        return (
          <>
            <h1>Hello Spec</h1>
          </>
        );
      }}
    </Table>
  );

const table = (
    <ThemeProvider theme={theme}>
      {justTheTable}
    </ThemeProvider>
  );

from enzyme.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.