Skip to content

Commit

Permalink
Merge pull request #680 from airbnb/fix-677
Browse files Browse the repository at this point in the history
Fix bug introduced in #677
  • Loading branch information
nfcampos authored Dec 22, 2016
2 parents 8ede787 + fc2fef0 commit 3d7b68b
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 15 deletions.
3 changes: 3 additions & 0 deletions src/MountedTraversal.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ export function instEqual(a, b, lenComp) {

export function instHasClassName(inst, className) {
const node = findDOMNode(inst);
if (node === null) { // inst renders null
return false;
}
if (node.classList) {
return node.classList.contains(className);
}
Expand Down
9 changes: 1 addition & 8 deletions src/ReactWrapper.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import {
typeOfNode,
displayNameOfNode,
ITERATOR_SYMBOL,
isFunctionalComponent,
} from './Utils';
import {
debugInsts,
Expand Down Expand Up @@ -139,13 +138,7 @@ class ReactWrapper {
* @returns {DOMComponent}
*/
getDOMNode() {
return this.single('getDOMNode', (n) => {
if (isFunctionalComponent(n)) {
throw new TypeError('Method “getDOMNode” cannot be used on functional components.');
}

return findDOMNode(n);
});
return this.single('getDOMNode', findDOMNode);
}

/**
Expand Down
87 changes: 80 additions & 7 deletions test/ReactWrapper-spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2109,7 +2109,21 @@ describeWithDOM('mount', () => {
});
});

context('When using a Composite component', () => {
describeIf(!REACT013, 'with stateless components', () => {
it('should return whether or not node has a certain class', () => {
const Foo = () => <div className="foo bar baz some-long-string FoOo" />;
const wrapper = mount(<Foo />);

expect(wrapper.hasClass('foo')).to.equal(true);
expect(wrapper.hasClass('bar')).to.equal(true);
expect(wrapper.hasClass('baz')).to.equal(true);
expect(wrapper.hasClass('some-long-string')).to.equal(true);
expect(wrapper.hasClass('FoOo')).to.equal(true);
expect(wrapper.hasClass('doesnt-exist')).to.equal(false);
});
});

context('When using a Composite class component', () => {
it('should return whether or not node has a certain class', () => {
class Foo extends React.Component {
render() {
Expand All @@ -2126,6 +2140,42 @@ describeWithDOM('mount', () => {
expect(wrapper.hasClass('doesnt-exist')).to.equal(false);
});
});

context('When using nested composite components', () => {
it('should return whether or not node has a certain class', () => {
class Foo extends React.Component {
render() {
return (<div className="foo bar baz some-long-string FoOo" />);
}
}
class Bar extends React.Component {
render() {
return <Foo />;
}
}
const wrapper = mount(<Bar />);

expect(wrapper.hasClass('foo')).to.equal(true);
expect(wrapper.hasClass('bar')).to.equal(true);
expect(wrapper.hasClass('baz')).to.equal(true);
expect(wrapper.hasClass('some-long-string')).to.equal(true);
expect(wrapper.hasClass('FoOo')).to.equal(true);
expect(wrapper.hasClass('doesnt-exist')).to.equal(false);
});
});

context('When using a Composite component that renders null', () => {
it('should return whether or not node has a certain class', () => {
class Foo extends React.Component {
render() {
return null;
}
}
const wrapper = mount(<Foo />);

expect(wrapper.hasClass('foo')).to.equal(false);
});
});
});

describe('.forEach(fn)', () => {
Expand Down Expand Up @@ -3337,27 +3387,50 @@ describeWithDOM('mount', () => {
}
}

it('should return the outer most DOMComponent of the root wrapper', () => {
it('should return the outermost DOMComponent of the root wrapper', () => {
const wrapper = mount(<Test />);
expect(wrapper.getDOMNode()).to.have.property('className', 'outer');
});

it('should return the outer most DOMComponent of the inner div wrapper', () => {
it('should return the outermost DOMComponent of the inner div wrapper', () => {
const wrapper = mount(<Test />);
expect(wrapper.find('.inner').getDOMNode()).to.have.property('className', 'inner');
});

it('should throw when wrapping multiple elements', () => {
const wrapper = mount(<Test />).find('span');
expect(() => wrapper.getDOMNode()).to.throw(Error);
expect(() => wrapper.getDOMNode()).to.throw(
Error,
'Method “getDOMNode” is only meant to be run on a single node. 2 found instead.',
);
});

describeIf(!REACT013, 'stateless components', () => {
const SFC = () => (<div />);
const SFC = () => (
<div className="outer">
<div className="inner">
<span />
<span />
</div>
</div>
);

it('should throw when wrapping an SFC', () => {
it('should return the outermost DOMComponent of the root wrapper', () => {
const wrapper = mount(<SFC />);
expect(() => wrapper.getDOMNode()).to.throw(TypeError, 'Method “getDOMNode” cannot be used on functional components.');
expect(wrapper.getDOMNode()).to.have.property('className', 'outer');
});

it('should return the outermost DOMComponent of the inner div wrapper', () => {
const wrapper = mount(<SFC />);
expect(wrapper.find('.inner').getDOMNode()).to.have.property('className', 'inner');
});

it('should throw when wrapping multiple elements', () => {
const wrapper = mount(<SFC />).find('span');
expect(() => wrapper.getDOMNode()).to.throw(
Error,
'Method “getDOMNode” is only meant to be run on a single node. 2 found instead.',
);
});
});
});
Expand Down

0 comments on commit 3d7b68b

Please sign in to comment.