enzyme
Version:
JavaScript Testing utilities for React
404 lines (320 loc) • 10.1 kB
JSX
/* globals window */
import React from 'react';
import { expect } from 'chai';
import { describeWithDOM, describeIf } from './_helpers';
import { mount } from '../src';
import {
coercePropValue,
getNode,
nodeEqual,
isPseudoClassSelector,
propFromEvent,
SELECTOR,
selectorType,
mapNativeEventNames,
displayNameOfNode,
} from '../src/Utils';
import { REACT013 } from '../src/version';
describe('Utils', () => {
describeWithDOM('getNode', () => {
it('should return a DOMNode when a DOMComponent is given', () => {
const div = mount(<div />).getNode();
expect(getNode(div)).to.be.instanceOf(window.HTMLElement);
});
it('should return the component when a component is given', () => {
class Foo extends React.Component {
render() { return <div />; }
}
const foo = mount(<Foo />).getNode();
expect(getNode(foo)).to.equal(foo);
});
describeIf(!REACT013, 'stateless function components', () => {
it('should return the component when a component is given', () => {
const Foo = () => <div />;
const foo = mount(<Foo />).getNode();
expect(getNode(foo)).to.equal(foo);
});
});
});
describe('nodeEqual', () => {
it('should match empty elements of same tag', () => {
expect(nodeEqual(
<div />,
<div />,
)).to.equal(true);
});
it('should not match empty elements of different type', () => {
expect(nodeEqual(
<div />,
<nav />,
)).to.equal(false);
});
it('should match basic prop types', () => {
expect(nodeEqual(
<div className="foo" />,
<div className="foo" />,
)).to.equal(true);
expect(nodeEqual(
<div id="foo" className="bar" />,
<div id="foo" className="bar" />,
)).to.equal(true);
expect(nodeEqual(
<div id="foo" className="baz" />,
<div id="foo" className="bar" />,
)).to.equal(false);
});
it('should check children as well', () => {
expect(nodeEqual(
<div>
<div />
</div>,
<div />,
)).to.equal(false);
expect(nodeEqual(
<div>
<div />
</div>,
<div>
<div />
</div>,
)).to.equal(true);
expect(nodeEqual(
<div>
<div className="foo" />
</div>,
<div>
<div className="foo" />
</div>,
)).to.equal(true);
expect(nodeEqual(
<div>
<div className="foo" />
</div>,
<div>
<div />
</div>,
)).to.equal(false);
});
it('should test deepEquality with object props', () => {
expect(nodeEqual(
<div foo={{ a: 1, b: 2 }} />,
<div foo={{ a: 1, b: 2 }} />,
)).to.equal(true);
expect(nodeEqual(
<div foo={{ a: 2, b: 2 }} />,
<div foo={{ a: 1, b: 2 }} />,
)).to.equal(false);
});
describe('children props', () => {
it('should match equal nodes', () => {
expect(nodeEqual(
<div>child</div>,
<div>child</div>,
)).to.equal(true);
});
it('should not match not equal nodes', () => {
expect(nodeEqual(
<div>child</div>,
<div />,
)).to.equal(false);
expect(nodeEqual(
<div />,
<div>child</div>,
)).to.equal(false);
});
it('should skip null children', () => {
expect(nodeEqual(
<div>{null}</div>,
<div />,
)).to.equal(true);
});
it('should skip undefined children', () => {
expect(nodeEqual(
<div>{undefined}</div>,
<div />,
)).to.equal(true);
});
it('should skip empty children', () => {
expect(nodeEqual(
<div>{[]}</div>,
<div />,
)).to.equal(true);
});
it('should skip array of null children', () => {
expect(nodeEqual(
<div>{[null, null, null]}</div>,
<div />,
)).to.equal(true);
});
});
describe('basic props and children mixed', () => {
it('should match equal nodes', () => {
expect(nodeEqual(
<div className="foo">child</div>,
<div className="foo">child</div>,
)).to.equal(true);
});
it('should not match when basic props are not equal', () => {
expect(nodeEqual(
<div className="foo">child</div>,
<div className="bar">child</div>,
)).to.equal(false);
expect(nodeEqual(
<div className="foo">child</div>,
<div className="bar">child</div>,
)).to.equal(false);
});
it('should not match when children are not equal', () => {
expect(nodeEqual(
<div className="foo">child</div>,
<div className="foo">other child</div>,
)).to.equal(false);
expect(nodeEqual(
<div className="foo">child</div>,
<div className="foo">other child</div>,
)).to.equal(false);
});
it('should match nodes when children are different but falsy', () => {
expect(nodeEqual(
<div className="foo">{null}</div>,
<div className="foo" />,
)).to.equal(true);
expect(nodeEqual(
<div children={null} className="foo" />, // eslint-disable-line react/no-children-prop
<div className="foo" />,
)).to.equal(true);
});
});
});
describe('propFromEvent', () => {
const fn = propFromEvent;
it('should work', () => {
expect(fn('click')).to.equal('onClick');
expect(fn('mouseEnter')).to.equal('onMouseEnter');
});
});
describe('isPseudoClassSelector', () => {
describe('prohibited selectors', () => {
function isNotPseudo(selector) {
it(selector, () => {
expect(isPseudoClassSelector(selector)).to.equal(false);
});
}
isNotPseudo('.foo');
isNotPseudo('div');
isNotPseudo('.foo .bar');
isNotPseudo('[hover]');
isNotPseudo('[checked=""]');
isNotPseudo('[checked=":checked"]');
isNotPseudo('[checked=\':checked\']');
isNotPseudo('.foo>.bar');
isNotPseudo('.foo > .bar');
isNotPseudo('.foo~.bar');
isNotPseudo('#foo');
});
describe('allowed selectors', () => {
function isPseudo(selector) {
it(selector, () => {
expect(isPseudoClassSelector(selector)).to.equal(true);
});
}
isPseudo(':checked');
isPseudo(':focus');
isPseudo(':hover');
isPseudo(':disabled');
isPseudo(':any');
isPseudo(':last-child');
isPseudo(':nth-child(1)');
isPseudo('div:checked');
isPseudo('[data-foo=":hover"]:hover');
});
});
describe('selectorType', () => {
it('returns CLASS_TYPE for a prefixed .', () => {
const type = selectorType('.foo');
expect(type).to.be.equal(SELECTOR.CLASS_TYPE);
});
it('returns ID_TYPE for a prefixed #', () => {
const type = selectorType('#foo');
expect(type).to.be.equal(SELECTOR.ID_TYPE);
});
it('returns PROP_TYPE for []', () => {
function isProp(selector) {
expect(selectorType(selector)).to.be.equal(SELECTOR.PROP_TYPE);
}
isProp('[foo]');
isProp('[foo="bar"]');
});
});
describe('coercePropValue', () => {
const key = 'foo';
it('returns undefined if passed undefined', () => {
expect(coercePropValue(key, undefined)).to.equal(undefined);
});
it('returns number if passed a stringified number', () => {
expect(coercePropValue(key, '1')).to.be.equal(1);
expect(coercePropValue(key, '0')).to.be.equal(0);
});
it('returns a boolean if passed a stringified bool', () => {
expect(coercePropValue(key, 'true')).to.equal(true);
expect(coercePropValue(key, 'false')).to.equal(false);
});
});
describe('mapNativeEventNames', () => {
describe('given an event that isn\'t a mapped', () => {
it('returns the original event', () => {
const result = mapNativeEventNames('click');
expect(result).to.equal('click');
});
});
describe('given a React capitalised mouse event', () => {
it('returns the original event', () => {
const result = mapNativeEventNames('mouseEnter');
expect(result).to.equal('mouseEnter');
});
});
describe('given a native lowercase event', () => {
it('transforms it into the React capitalised event', () => {
const result = mapNativeEventNames('dragenter');
expect(result).to.equal('dragEnter');
});
});
});
describe('displayNameOfNode', () => {
describe('given a node with displayName', () => {
it('should return the displayName', () => {
class Foo extends React.Component {
render() { return <div />; }
}
Foo.displayName = 'CustomWrapper';
expect(displayNameOfNode(<Foo />)).to.equal('CustomWrapper');
});
describeIf(!REACT013, 'stateless function components', () => {
it('should return the displayName', () => {
const Foo = () => <div />;
Foo.displayName = 'CustomWrapper';
expect(displayNameOfNode(<Foo />)).to.equal('CustomWrapper');
});
});
});
describe('given a node without displayName', () => {
it('should return the name', () => {
class Foo extends React.Component {
render() { return <div />; }
}
expect(displayNameOfNode(<Foo />)).to.equal('Foo');
});
describeIf(!REACT013, 'stateless function components', () => {
it('should return the name', () => {
const Foo = () => <div />;
expect(displayNameOfNode(<Foo />)).to.equal('Foo');
});
});
});
describe('given a DOM node', () => {
it('should return the type', () => {
expect(displayNameOfNode(<div />)).to.equal('div');
});
});
});
});