Giter Site home page Giter Site logo

enzymejs / enzyme Goto Github PK

View Code? Open in Web Editor NEW
20.0K 256.0 2.0K 7.76 MB

JavaScript Testing utilities for React

Home Page: https://enzymejs.github.io/enzyme/

License: MIT License

Shell 0.02% JavaScript 99.98%
enzyme react mocha react-components ava jest chai assertion-library traversal test-runners

enzyme's Introduction

Enzyme

Join the chat at https://gitter.im/enzymejs/enzyme

npm Version License Build Status Coverage Status

Enzyme is a JavaScript Testing utility for React that makes it easier to test your React Components' output. You can also manipulate, traverse, and in some ways simulate runtime given the output.

Enzyme's API is meant to be intuitive and flexible by mimicking jQuery's API for DOM manipulation and traversal.

Upgrading from Enzyme 2.x or React < 16

Are you here to check whether or not Enzyme is compatible with React 16? Are you currently using Enzyme 2.x? Great! Check out our migration guide for help moving on to Enzyme v3 where React 16 is supported.

To get started with enzyme, you can simply install it via npm. You will need to install enzyme along with an Adapter corresponding to the version of react (or other UI Component library) you are using. For instance, if you are using enzyme with React 16, you can run:

npm i --save-dev enzyme enzyme-adapter-react-16

Each adapter may have additional peer dependencies which you will need to install as well. For instance, enzyme-adapter-react-16 has peer dependencies on react and react-dom.

At the moment, Enzyme has adapters that provide compatibility with React 16.x, React 15.x, React 0.14.x and React 0.13.x.

The following adapters are officially provided by enzyme, and have the following compatibility with React:

Enzyme Adapter Package React semver compatibility
enzyme-adapter-react-16 ^16.4.0-0
enzyme-adapter-react-16.3 ~16.3.0-0
enzyme-adapter-react-16.2 ~16.2
enzyme-adapter-react-16.1 ~16.0.0-0 || ~16.1
enzyme-adapter-react-15 ^15.5.0
enzyme-adapter-react-15.4 15.0.0-0 - 15.4.x
enzyme-adapter-react-14 ^0.14.0
enzyme-adapter-react-13 ^0.13.0

Finally, you need to configure enzyme to use the adapter you want it to use. To do this, you can use the top level configure(...) API.

import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

Enzyme.configure({ adapter: new Adapter() });

3rd Party Adapters

It is possible for the community to create additional (non-official) adapters that will make enzyme work with other libraries. If you have made one and it's not included in the list below, feel free to make a PR to this README and add a link to it! The known 3rd party adapters are:

Adapter Package For Library Status
enzyme-adapter-preact-pure preact (stable)
enzyme-adapter-inferno inferno (work in progress)

Running Enzyme Tests

Enzyme is unopinionated regarding which test runner or assertion library you use, and should be compatible with all major test runners and assertion libraries out there. The documentation and examples for enzyme use Mocha and Chai, but you should be able to extrapolate to your framework of choice.

If you are interested in using enzyme with custom assertions and convenience functions for testing your React components, you can consider using:

Using Enzyme with Mocha

Using Enzyme with Karma

Using Enzyme with Browserify

Using Enzyme with SystemJS

Using Enzyme with Webpack

Using Enzyme with JSDOM

Using Enzyme with React Native

Using Enzyme with Jest

Using Enzyme with Lab

Using Enzyme with Tape and AVA

Basic Usage

import React from 'react';
import { expect } from 'chai';
import { shallow } from 'enzyme';
import sinon from 'sinon';

import MyComponent from './MyComponent';
import Foo from './Foo';

describe('<MyComponent />', () => {
  it('renders three <Foo /> components', () => {
    const wrapper = shallow(<MyComponent />);
    expect(wrapper.find(Foo)).to.have.lengthOf(3);
  });

  it('renders an `.icon-star`', () => {
    const wrapper = shallow(<MyComponent />);
    expect(wrapper.find('.icon-star')).to.have.lengthOf(1);
  });

  it('renders children when passed in', () => {
    const wrapper = shallow((
      <MyComponent>
        <div className="unique" />
      </MyComponent>
    ));
    expect(wrapper.contains(<div className="unique" />)).to.equal(true);
  });

  it('simulates click events', () => {
    const onButtonClick = sinon.spy();
    const wrapper = shallow(<Foo onButtonClick={onButtonClick} />);
    wrapper.find('button').simulate('click');
    expect(onButtonClick).to.have.property('callCount', 1);
  });
});

Read the full API Documentation

import React from 'react';
import sinon from 'sinon';
import { expect } from 'chai';
import { mount } from 'enzyme';

import Foo from './Foo';

describe('<Foo />', () => {
  it('allows us to set props', () => {
    const wrapper = mount(<Foo bar="baz" />);
    expect(wrapper.props().bar).to.equal('baz');
    wrapper.setProps({ bar: 'foo' });
    expect(wrapper.props().bar).to.equal('foo');
  });

  it('simulates click events', () => {
    const onButtonClick = sinon.spy();
    const wrapper = mount((
      <Foo onButtonClick={onButtonClick} />
    ));
    wrapper.find('button').simulate('click');
    expect(onButtonClick).to.have.property('callCount', 1);
  });

  it('calls componentDidMount', () => {
    sinon.spy(Foo.prototype, 'componentDidMount');
    const wrapper = mount(<Foo />);
    expect(Foo.prototype.componentDidMount).to.have.property('callCount', 1);
    Foo.prototype.componentDidMount.restore();
  });
});

Read the full API Documentation

import React from 'react';
import { expect } from 'chai';
import { render } from 'enzyme';

import Foo from './Foo';

describe('<Foo />', () => {
  it('renders three `.foo-bar`s', () => {
    const wrapper = render(<Foo />);
    expect(wrapper.find('.foo-bar')).to.have.lengthOf(3);
  });

  it('renders the title', () => {
    const wrapper = render(<Foo title="unique" />);
    expect(wrapper.text()).to.contain('unique');
  });
});

Read the full API Documentation

React Hooks support

Enzyme supports react hooks with some limitations in .shallow() due to upstream issues in React's shallow renderer:

  • useEffect() and useLayoutEffect() don't get called in the React shallow renderer. Related issue

  • useCallback() doesn't memoize callback in React shallow renderer. Related issue

If you're using React 16.8+ and .mount(), Enzyme will wrap apis including .simulate(), .setProps(), .setContext(), .invoke() with ReactTestUtils.act() so you don't need to manually wrap it.

A common pattern to trigger handlers with .act() and assert is:

const wrapper = mount(<SomeComponent />);
act(() => wrapper.prop('handler')());
wrapper.update();
expect(/* ... */);

We cannot wrap the result of .prop() (or .props()) with .act() in Enzyme internally since it will break the equality of the returned value. However, you could use .invoke() to simplify the code:

const wrapper = mount(<SomeComponent />);
wrapper.invoke('handler')();
expect(/* ... */);

Future

Enzyme Future

Contributing

See the Contributors Guide

In the wild

Organizations and projects using enzyme can list themselves here.

License

MIT

enzyme's People

Contributors

alecrobins avatar aweary avatar bdwain avatar blainekasten avatar chenesan avatar cpojer avatar dferber90 avatar eddyerburgh avatar gregberge avatar iancmyers avatar jackfranklin avatar jgzuke avatar jordwest avatar jquense avatar jwbay avatar kii-dot avatar kmcq avatar koba04 avatar lelandrichardson avatar lencioni avatar lh0x00 avatar ljharb avatar madicap avatar marlonbernardes avatar minznerjosh avatar mwilliamson avatar nfcampos avatar serut avatar silvenon avatar smacker avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

enzyme's Issues

Jasmine support

As it follows from the docs

Reagent is unopinionated regarding which test runner or assertion library you use, and should be compatible with all major test runners and assertion libraries out there.

I tried to use it with Jasmine and it worked fine until I tried to use mount. I got the error.

TypeError: before is not a function

before hook is the Mocha-specific thing, Jasmine has the similar thing named beforeAll.

Thanks for the awesome tool! It is really missing piece to my tests, but I can't use it due to lack of Jasmine support.

Error when calling this.setState in componentDidMount when using reagent's mount

I have a component that looks like this:

class MySharona extends React.Component {
  constructor(props) {
    super(props);
    this.state = {mounted: false};
  }

  componentDidMount() {
    this.setState({mounted: true});
  }

  render() {
    return <div>{this.state.mounted}</div>;
  }
}

I've got a test that looks like this:

import { expect } from 'chai';
import { mount, describeWithDom } from 'reagent';
import React from 'react';

import MySharona from './MySharona.js';

describeWithDom('MySharona', () => {
  it('passes my test', () => {
    const wrapper = mount(<MySharona />);
    expect(wrapper.find('div').text).to.be('true');
  });
});

Instead of getting a passing test, I get a horrible, horrible error, that crushes my soul and makes me sad:

Error: Invariant Violation: dangerouslyReplaceNodeWithMarkup(...): Cannot render markup in a worker thread. Make surewindowanddocumentare available globally before requiring React when unit testing or use React.renderToString for server rendering.

`.props()` doesn't seem to work on the root element

This issue is sort of a misnomer. It usually goes something like this:

Say you have some component:

class Foo extends React.Component {
  render() {
    return <div className="in-foo">{this.props.foo}</div>
  }
}
const wrapper = shallow(<Foo foo="bar" />);
expect(wrapper.props()).to.eql({ className: 'in-foo', children: 'bar' });
expect(wrapper.props()).to.not.eql({ foo: 'bar' });

The trick is you are looking at the root node of the rendered result of <Foo />, not the <Foo /> itself. As a result, you are getting back className and children rather than the props that were passed in.

This is the expected behavior and will not change. If you want to get the props you passed in:

expect(wrapper.instance().props).to.eql({ foo: 'bar' });

Support functional stateless components

Hello guys.
Thank you so much, reagent is exactly the lib I was waiting for!

I noticed that using mount() does not work on functional stateless components.

There is a workaround: wrapping the function component with:

import React from 'react';

// Utility to wrap stateless component and allow functional stateless components
// to be tested using reagent
export var StatelessWrapper = Wrapped => class extends React.Component {
  render() {
    return <Wrapped {...this.props} />;
  }
};

I would be nice if the lib did that automatically.

Jest support documentation

In order for this to work with jest, jest needs to know about some libraries specifically not to be mocked. It'd be nice if you could document this somewhere. This is specifically what I had to do to get tests running:

/package.json

{
  "jest": {
    "unmockedModulePathPatterns": [
      "enzyme",
      "cheerio",
      "htmlparser2",
      "sinon",
      "..."
    ]
  }
}

This is an exhaustive list of needed items

  • enzyme
  • cheerio
  • htmlparser2
  • sinon
  • underscore
  • lodash dep of cheerio, needed for render method
  • domhandler dep of htmlparser2, from cheerio
  • object.assign
  • define-properties
  • function-bind
  • object-keys

`html()` has no button, while `find('button').length` is 1

I'm writing a test that checks that a component does not include a <button> when a certain prop isnt passed.

I'm using the shallow renderer as two of the examples on this section seems to do exactly what I intend to do.

const wrapper = shallow(<MyComponent />);

When I log the output html of the component through wrapper.html() I see there's no <button> in there. In fact I can see the <noscript/>'s created by my conditional rendering component.

However, wrapper.find('button') or wrapper.find('.btn') (as it has this class) both return an object with length equals 1.

wrapper.contanis('button') is also true.

What could I be doing wrong, have I misunderstood something?
What is the best way to assert the presence of a node in the rendered output?

I could of course assert on the contents of html() but that feels a bit brittle.

Create chai assertion plugin

Potential API:

chai.use(require('reagent/chai'));
expect(wrapper).to.have.props({ foo: "bar" });
expect(wrapper).to.have.children();
expect(wrapper).to.not.have.children();
expect(wrapper).to.match('.foo.bar');
expect(wrapper).to.be.empty;
expect(wrapper).to.not.be.empty;

Lets change the API for spyLifecycle and spyMethods

The goal of this is to

  • Make whats happening a bit more explicit. Currently there's a bit of magic.
  • Let you use your own sinon rather than rely on reagent using its own.
let spy; 

describe('MyComponent', () => {
  beforeEach() {
    spy = reagent.spyLifecycle(sinon, MyComponent);
  },

  it('should do things', () => {
    const my = mount(<MyComponent />);
    my.setProps({ hello: 'world' });

    assert.isTrue(spy.get('componentWillReceiveProps').calledOnce, 'receive props was called');

    // or if we don't want to be stringly typed...
    assert.isTrue(my.componentWillReceiveProps.calledOnce);
  });

  afterEach() {
    spy.destroy();
  }
});

Pros: It's more explicit what's happening.
Cons: You now have to do the beforeEach/afterEach setup yourself.

Ideally we'd merge spyLifecycle and spyMethods so it just spies every method.

jsdom mount

I already make travis use nvm use 4 and the test involved mount method still fail, any solution?

link to build

link to file line

Setting text value of input

To set the value of an input currently I have to do:

const form = mount(<MyComponent />);
const input = form.find('input').get(0);
input.value = 'Blah blah';

It would be really nice in my opinion if I could instead do something akin to jQuery:

form.find('input').text('Blah blah')
// or probably better
form.find('input').value('Blah blah')

What are your thoughts on that? I'd be happy to attempt to work on the PR :)

Add support for passing context

I have a component in my app that has a router passed to it via context:

const contextTypes = { router: React.PropTypes.func.isRequired, };

Reagent tests currently do not support passing in a context and will throw this error:

Error: expected zero console.warn calls, got 1:
      warn(Warning: Failed Context Types: Required context `router` was not specified in `MyComponent`.) at warning (node_modules/react/lib/warning.js:48:15)
    at Context.<anonymous> (spec/javascripts/_failTestsOnErrors.js:21:23)

It would be great to be able to pass context into shallow.

Better error if you try to simulate a non-existing event

Running

input.simulate('keyDown', { which: val });

Produces

TypeError: Cannot read property 'apply' of undefined
      at ReactWrapper.<anonymous> (node_modules/enzyme/build/ReactWrapper.js:351:44)
      at ReactWrapper.single (node_modules/enzyme/build/ReactWrapper.js:739:17)
      at ReactWrapper.simulate (node_modules/enzyme/build/ReactWrapper.js:350:12)

Because there's an unchecked reference to an event type. Instead, enzyme should give an informative message.

simulate example doesn't make sense, nor does it work

http://airbnb.io/enzyme/docs/api/ShallowWrapper/simulate.html

I'm trying to get a grip on how to test my React components. Specifically, I feel like a proper test would be to assert some state, call a function that calls setState, and re-assert the state. The below example uses an inline function, which confuses me more.. is there no such possibility to directly call the function without "simulating" an event? Furthermore, the simulate example in the docs doesn't seem to make sense:

class Foo extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }
  render() {
    const { count } = this.state;
    return (
      <div>
        <div className={`clicks-${count}`}>
          {count} clicks
        </div>
        <a onClick={() => this.setState({ count: count + 1 })}>
          Increment
        </a>
      </div>
    );
  }
}

const wrapper = shallow(<Foo />);

expect(wrapper.find('.clicks-0').length).to.equal(1);
wrapper.simulate('click');
expect(wrapper.find('.clicks-1').length).to.equal(1);

I don't understand simulate('click') here.. doesn't it need to find the anchor tag first to click it?

How to unmount mounted components?

It would be really nice if the ReactWrapper would expose a .unmount() function that would behind the scenes perform something similar to doing mountedComponent.getInstance().componentWillUnmount(); for those components rendered with mount().
It would be also OK if the docs would mention what is the recommended way of doing this, too.

A use case for this is to prevent leaking listeners bound during componentWillMount calls.

Update to babel 6

Ideally enzyme would update to babel 6 so that it can be compatible with applications built in babel 6 land and their configuration files.

Document how to test for null/false

I would like to add to the docs a good way to test for null, but I'm not sure which one is it.

This is the component:

import React, { PropTypes } from 'react';

const Component = (props) => {
  return props.returnNull ? null : <div />;
};

Component.propTypes = {
  returnNull: PropTypes.bool
};

export default Component;

I want to test if setting the flag to true will return null:

import React from 'react';
import { shallow } from 'reagent';
import { expect } from 'chai';
import Component from './Component';

describe('<Component />', () => {
  it('returns null if the flag is on', () => {
    const wrapper = shallow(
      <Component returnNull={true} />
    );
    expect(wrapper.text()).to.equal('');
  });
});

What is the correct way to do it? Would it perhaps be better if wrapper.type() returned null instead of throwing?

rename `.get()` to `.at()` and repurpose `.get()`

The idea is we want .get(index) to have the same semantics as jQuery, where it returns the actual node at the index rather than the wrapped node. The current functionality that .get(index) has can be moved to an .at(index) method.

Webpack build issues

I'm trying to get enzyme working using a pretty standard webpack/karma setup. Webpack throws a bunch of errors related to the dependencies enzyme imports, including sinon, cheerio, and jsdom. Sinon gives webpack heartburn because it uses it's own require (which seems to be documented here: webpack/webpack#304), and then there are a bunch of "Module not found" errors for jsdom and cheerio.

I'm importing enzyme as described in the docs and can't really think of anything else I might be missing, so I'm curious if anyone else is trying to use webpack and running into a similar issue, or if there's just something weird with my configuration. I'd expect to be able to just import it and have it work, but maybe I need to do something with those external libraries?

Here's my test file for reference:

import expect from 'expect';
import { shallow } from 'enzyme';
import React from 'react';
import Button from '../Button';

describe('Button', () => {
    it('should render children passed in', () => {
        const wrapper = shallow(
            <Button><div className="foo" /></Button>
        );

        expect(wrapper.contains(<div className="foo" />)).toBe(true);
    });
});

I won't paste the entire error log from webpack because it's pretty long, but here's a sample:


WARNING in ./~/enzyme/~/jsdom/~/acorn/dist/acorn.js
Critical dependencies:
1:478-485 This seems to be a pre-built javascript file. Though this is possible, it's not recommended. Try to require the original source to get better results.
 @ ./~/enzyme/~/jsdom/~/acorn/dist/acorn.js 1:478-485

WARNING in ./~/enzyme/~/jsdom/~/acorn/dist/walk.js
Critical dependencies:
1:503-510 This seems to be a pre-built javascript file. Though this is possible, it's not recommended. Try to require the original source to get better results.
 @ ./~/enzyme/~/jsdom/~/acorn/dist/walk.js 1:503-510

ERROR in ./~/enzyme/build/react-compat.js
Module not found: Error: Cannot resolve module 'react/lib/ExecutionEnvironment' in /Users/agoggin/www/vhosts/hammerhead/node_modules/enzyme/build
 @ ./~/enzyme/build/react-compat.js 22:2-43

ERROR in ./~/enzyme/~/cheerio/index.js
Module not found: Error: Cannot resolve module 'json' in /Users/agoggin/www/vhosts/hammerhead/node_modules/enzyme/node_modules/cheerio
 @ ./~/enzyme/~/cheerio/index.js 11:18-38

ERROR in ./~/enzyme/~/jsdom/lib/jsdom.js
Module not found: Error: Cannot resolve module 'fs' in /Users/agoggin/www/vhosts/hammerhead/node_modules/enzyme/node_modules/jsdom/lib
 @ ./~/enzyme/~/jsdom/lib/jsdom.js 6:9-22

My webpack/karma config is pretty vanilla, but it'd help I can post that, too.

setProps causes Invariant Violation

given a simple test case

import {mount} from 'enzyme';

it('should update content', () => {
    function Foo({foo, id}) {
        const content = foo ? <span className="message">{id}</span> : id;
        return <div>{content}</div>;
    }
    const wrapper = mount(<Foo id="1" />);
    wrapper.setProps({ id: '1', foo: true});
    expect(wrapper.find('.message').length).toBe(1);
});

fails on the latest assertion with the error

Error: Invariant Violation: findComponentRoot(..., .7ng446bthc.0): Unable to find element. This probably means the DOM was unexpectedly mutated (e.g., by the browser), usually due to forgetting a <tbody> when using tables, nesting tags like <form>, <p>, or <a>, or using non-SVG elements in an <svg> parent. Try inspecting the child nodes of the element with React ID ``.
    at invariant (../project/node_modules/fbjs/lib/invariant.js:39:15)
    at Object.ReactMount.findComponentRoot (../project/node_modules/react/lib/ReactMount.js:764:54)
    at Object.ReactMount.findReactNodeByID (../project/node_modules/react/lib/ReactMount.js:679:23)
    at Object.getNode (../project/node_modules/react/lib/ReactMount.js:162:32)
    at ReactDOMComponent.Mixin.getPublicInstance (../project/node_modules/react/lib/ReactDOMComponent.js:925:29)
    at findAllInRenderedTreeInternal (../project/node_modules/enzyme/build/MountedTraversal.js:233:27)
    at findAllInRenderedTreeInternal (../project/node_modules/enzyme/build/MountedTraversal.js:246:26)
    at findAllInRenderedTreeInternal (../project/node_modules/enzyme/build/MountedTraversal.js:249:24)
    at treeFilter (../project/node_modules/enzyme/build/MountedTraversal.js:261:10)
    at ReactWrapper.<anonymous> (../project/node_modules/enzyme/build/ReactWrapper.js:37:45)

It happened when I conditionally render some elements. With shallow render it works fine.

$.find('.myclass').first().html()

$.find(`.${ props.helloClass }`).first().html()
/Users/eric/Dropbox/dev/react-pure-component-starter/node_modules/fbjs/lib/invariant.js:45
    throw error;
    ^

Error: Invariant Violation: renderToStaticMarkup(): You must pass a valid ReactElement.

Ok... maybe it didn't find anything?

$.find(`.${ props.helloClass }`).first().length // 1

Looks like it found something. How do I see what it found without a working .html()?

I'd love to step through and find out, but I'm struggling to get iron-node or node-inspector to work on the tests. Wish I had more time to dig in.

Any hints?

Inconsistency in setProps

setProps(newProps) on ReactWrapper replaces all props with a passed new one.

setProps(newProps) on ShallowWrapper merges it with exsisting.

I think that ReactWrapper should merge props as well because it is more useful and similar how React's setState works.

How do you use mount/jsdom without mocha?

Hi. I've loaded jsdom like this:

jsdom.env({
    html: '<html><body></body</html>',
    done: () => runTests()
});

And just to be through I tried const document = jsdom.env... and const window = jsdom.env ...

The runTests method had this statement: mount();

But ever time I run it, I get the following error: "It looks like you called mount() without a jsdom document being loaded. ' + 'Make sure to only use mount() inside of a `describeWithDOM(...)"

Your documentation says I don't need to use describeWithDOM if I'm not using mocha.

setState causes Invariant Violation when it changes markup

I'm aware of #27, mine happens on React v0.14 and it crushes my soul as well 😞

As far as I've tested (AFAIT?), this only happens when the state alters markup:

import React from 'react';
import { mount, describeWithDOM } from 'enzyme';

const Component = React.createClass({
  getInitialState() {
    return { flag: false };
  },

  render() {
    return this.state.flag ? <a /> : <div />
  }
});

describeWithDOM('<Component />', () => {
  it('turns on the flag', () => {
    const wrapper = mount(<Component />);
    wrapper.setState({ flag: true });
  });
});
Error: Invariant Violation: dangerouslyReplaceNodeWithMarkup(...): Cannot render markup in a worker thread. Make sure `window` and `document` are available globally before requiring React when unit testing or use ReactDOMServer.renderToString() for server rendering.

This does not happen if both elements are the same (e.g. this.state.flag ? <div /> : <div />).

Jest seemed to have solved this issue, it doesn't happen there, so it might be worth looking how they did it. I can take a look later, but I was wondering if you knew what's causing this.

This SO answer might help, though I'm not sure if it's related.

Project Name Ideas

@hkjels, @Kauko and others have raised concern in #43 regarding the name conflict of "reagent" with the ClojureScript library.

This new issue is meant for discussion regarding new name ideas ONLY. If you have greater comments to add to the overall discussion/issue of renaming the library, please do so in the aforementioned thread.

Please do NOT suggest the name unless it has its corresponding package name available in npm.

Please do NOT comment with "+1" comments

Ignore _book

The enzyme npm package includes a compiled _book directory that occupies a lot of space:

~/src/app/node_modules/enzyme〉du -sh *
4.0K    CHANGELOG.md
4.0K    CONTRIBUTING.md
4.0K    LICENSE.md
8.0K    README.md
6.3M    _book
4.0K    book.json
236K    build
356K    docs
4.0K    install-relevant-react.sh
2.7M    node_modules
8.0K    package.json
1.7M    packages
172K    src

Could this be included in npmignore so that it doesn't slow down installs?

Mistake in the homepage doc for shallow?

There's an example of simulating click events using the shallow renderer:

  it('simulates click events', () => {
    const onButtonClick = sinon.spy();
    const wrapper = shallow(
      <Foo onButtonClick={onButtonClick} />
    );
    wrapper.find('button').click();
    expect(onButtonClick.calledOnce).to.be.true;
  });

But when I try to use it, I get this:

$.find('.' + helloClass).click();
                             ^

TypeError: $.find(...).click is not a function

I didn't search meticulously, but I don't see a .click() method in the source... where is it?

jsdom dependency?

I'm just curious as to why jsdom is required for the full rendering. I understand the need for a DOM, but what about in environments in which a DOM already exists? In our current architecture, we're running our tests directly in the browser via Karma.

I do see that jsdom is an optional dependency, and that its require statement is wrapped in a try/catch. Does this mean that it would still work if you're using some alternative DOM? If so, then just the docs are misleading.

Projectname

This can be confused with the ClojureScript view-layer over React called Reagent. It should be mentioned in the Readme.

`.setProps()` doesn't trigger componentDidUpdate lifecycle method

When using shallow, the .setProps() method doesn't trigger the componentDidUpdate lifecycle method. However, .setState() does trigger it. It seems like they both should (or both shouldn't).

simple example
describe('MyComponent', () => {
  let spy;

  before(function() {
    spy = sinon.spy(MyComponent.prototype, 'componentDidUpdate');
  });

  after(function() {
    spy.restore();
  });

  // fails
  it('calls componentDidUpdate when setting props', () => {
    const wrapper = shallow(<MyComponent color="yellow" />);
    wrapper.setProps({ 'color': 'green' });
    expect(spy.calledOnce).to.be.true;
  });

  // passes
  it('calls componentDidUpdate when setting state', () => {
    const wrapper = shallow(<MyComponent color="yellow" />);
    wrapper.setState({ foo: 'bar' });
    expect(spy.calledOnce).to.be.true;
  });
});

How to find an element based on its ref attribute?

When refactoring my tests to use enzyme, I wanted to find some elements based on their ref attribute. Is there a way to achieve that?

Lets say I have this component (it's just a made-up example):

export default class Example extends React.Component {

  render () {
    return (
      <form>
        <button ref="first-button">First button</button>
        <button ref="second-button">Second button</button>
       </form>
    )
  }
}

How do I find the second-button using its ref attribute?

  it('should find an element based on its ref attribute', () => {
    const component = shallow(<Example />)
    // This does not work yet, complex CSS selectors are not supported
    const button = component.find('button[ref="second-button"]');
    // This works, but I don't like depending on the JSX structure. 
    // My tests would fail if I added a new button or changed the button to a link, for example.
    const button = component.find('button').get(1);
  });

Is implementing a ref([key]) method a good/viable idea?

const button = component.ref('second-button');

I could help if you think this is something worth to have.

Remove direct dependency on Sinon

Why are Sinon methods being exported from this package (for example in https://github.com/airbnb/reagent/blob/master/src/index.js#L20)? This poses a problem for us, as Sinon is throwing an exception on our codebase and we don't necessarily want to use Sinon and would rather have the flexibility to choose our own mocking/stubbing library. I understand that it's perhaps a convenience to be able to useSinon, but It seems outside of the scope of what Reagent is trying to accomplish, and it is trivial to set up Sinon ourselves. Is there a chance you'll rethink this approach? I'd really like to be able to use Reagent for testing, but right now this is preventing us from doing so.

id selector does not seem to work

Was trying to test a simple piece of code:

const renderShallow = shallow(<div id='ttt' className='ttt'>hello</div>);
console.log(renderShallow.find('#ttt')); // not found
console.log(renderShallow.find('.ttt')); // found

and it returns an empty array when i tried to use an id selector. It works fine on class selectors.

Any way to get the value of an input/select?

I'm trying to make sure that a select box is rendered with the proper value selected. I don't see any hooks into value in the docs for shallow or render. Is there an obvious thing I'm missing?

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.