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

bugfix: fix error in hasClass when className is regex expression #2057

Merged
merged 3 commits into from Mar 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/api/ShallowWrapper/hasClass.md
Expand Up @@ -23,7 +23,7 @@ expect(wrapper.find('.my-button').hasClass('disabled')).to.equal(true);

```jsx
// Searching using RegExp works fine when classes were injected by a jss decorator
const wrapper = mount(<MyComponent />);
const wrapper = shallow(<MyComponent />);
expect(wrapper.find('.my-button').hasClass(/(ComponentName)-(other)-(\d+)/)).to.equal(true);
```

Expand Down
32 changes: 27 additions & 5 deletions packages/enzyme-test-suite/test/ReactWrapper-spec.jsx
Expand Up @@ -4663,7 +4663,7 @@ describeWithDOM('mount', () => {
});

describe('.hasClass(className)', () => {
context('When using a DOM component', () => {
context('when using a DOM component', () => {
it('returns whether or not node has a certain class', () => {
const wrapper = mount(<div className="foo bar baz some-long-string FoOo" />);

Expand Down Expand Up @@ -4697,7 +4697,7 @@ describeWithDOM('mount', () => {
});
});

context('When using a Composite class component', () => {
context('when using a Composite class component', () => {
it('returns whether or not node has a certain class', () => {
class Foo extends React.Component {
render() {
Expand All @@ -4722,7 +4722,7 @@ describeWithDOM('mount', () => {
});
});

context('When using nested composite components', () => {
context('when using nested composite components', () => {
it('returns whether or not node has a certain class', () => {
class Foo extends React.Component {
render() {
Expand Down Expand Up @@ -4754,7 +4754,7 @@ describeWithDOM('mount', () => {
});
});

context('When using a Composite component that renders null', () => {
context('when using a Composite component that renders null', () => {
it('returns whether or not node has a certain class', () => {
class Foo extends React.Component {
render() {
Expand All @@ -4773,8 +4773,30 @@ describeWithDOM('mount', () => {
return <div {...this.props} />;
}
}
const wrapper = mount(<Foo className={{ classA: true, classB: false }} />);
const obj = { classA: true, classB: false };
const wrapper = mount(<Foo className={obj} />);
expect(wrapper.hasClass('foo')).to.equal(false);
expect(wrapper.hasClass('classA')).to.equal(false);
expect(wrapper.hasClass('classB')).to.equal(false);
expect(wrapper.hasClass(String(obj))).to.equal(true);
});

it('allows hyphens', () => {
const wrapper = mount(<div className="foo-bar" />);
expect(wrapper.hasClass('foo-bar')).to.equal(true);
});

it('works if className has a function in toString property', () => {
function classes() {}
classes.toString = () => 'foo-bar';
const wrapper = mount(<div className={classes} />);
expect(wrapper.hasClass('foo-bar')).to.equal(true);
});

it('works if searching with a RegExp', () => {
const wrapper = mount(<div className="ComponentName-classname-123" />);
expect(wrapper.hasClass(/(ComponentName)-(classname)-(\d+)/)).to.equal(true);
expect(wrapper.hasClass(/(ComponentName)-(other)-(\d+)/)).to.equal(false);
});
});

Expand Down
98 changes: 96 additions & 2 deletions packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx
Expand Up @@ -4628,6 +4628,65 @@ describe('shallow', () => {
});

describe('.hasClass(className)', () => {
context('when using a DOM component', () => {
it('returns whether or not node has a certain class', () => {
const wrapper = shallow(<div className="foo bar baz some-long-string FoOo" />);

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);
});
});

describeIf(is('> 0.13'), 'with stateless function components (SFCs)', () => {
it('returns whether or not node has a certain class', () => {
const Foo = () => <main><div className="foo bar baz some-long-string FoOo" /></main>;
const wrapper = shallow(<Foo />);

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

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

context('when using a Composite class component', () => {
it('returns whether or not node has a certain class', () => {
class Foo extends React.Component {
render() {
return (<main><div className="foo bar baz some-long-string FoOo" /></main>);
}
}
const wrapper = shallow(<Foo />);

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

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

it('returns whether or not node has a certain class', () => {
const wrapper = shallow((
<div className="foo bar baz some-long-string FoOo" />
Expand All @@ -4641,14 +4700,49 @@ describe('shallow', () => {
expect(wrapper.hasClass('doesnt-exist')).to.equal(false);
});

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

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

it('works with a non-string `className` prop', () => {
class Foo extends React.Component {
render() {
return <Foo {...this.props} />;
return <div {...this.props} />;
}
}
const wrapper = shallow(<Foo className={{ classA: true, classB: false }} />);
const obj = { classA: true, classB: false };
const wrapper = shallow(<Foo className={obj} />);
expect(wrapper.hasClass('foo')).to.equal(false);
expect(wrapper.hasClass('classA')).to.equal(false);
expect(wrapper.hasClass('classB')).to.equal(false);
expect(wrapper.hasClass(String(obj))).to.equal(true);
});

it('allows hyphens', () => {
const wrapper = shallow(<div className="foo-bar" />);
expect(wrapper.hasClass('foo-bar')).to.equal(true);
});

it('works if className has a function in toString property', () => {
function classes() {}
classes.toString = () => 'foo-bar';
const wrapper = shallow(<div className={classes} />);
expect(wrapper.hasClass('foo-bar')).to.equal(true);
});

it('works if searching with a RegExp', () => {
const wrapper = shallow(<div className="ComponentName-classname-123" />);
expect(wrapper.hasClass(/(ComponentName)-(classname)-(\d+)/)).to.equal(true);
expect(wrapper.hasClass(/(ComponentName)-(other)-(\d+)/)).to.equal(false);
});
});

Expand Down
2 changes: 1 addition & 1 deletion packages/enzyme/src/ReactWrapper.js
Expand Up @@ -855,7 +855,7 @@ class ReactWrapper {
* @returns {Boolean}
*/
hasClass(className) {
if (className && className.indexOf('.') !== -1) {
if (typeof className === 'string' && className.indexOf('.') !== -1) {
// eslint-disable-next-line no-console
console.warn('It looks like you\'re calling `ReactWrapper::hasClass()` with a CSS selector. hasClass() expects a class name, not a CSS selector.');
}
Expand Down
2 changes: 1 addition & 1 deletion packages/enzyme/src/ShallowWrapper.js
Expand Up @@ -1253,7 +1253,7 @@ class ShallowWrapper {
* @returns {Boolean}
*/
hasClass(className) {
if (className && className.indexOf('.') !== -1) {
if (typeof className === 'string' && className.indexOf('.') !== -1) {
// eslint-disable-next-line no-console
console.warn('It looks like you\'re calling `ShallowWrapper::hasClass()` with a CSS selector. hasClass() expects a class name, not a CSS selector.');
}
Expand Down