Skip to content

Commit

Permalink
Add RexExp support to hasClass
Browse files Browse the repository at this point in the history
add matchesClass method and tests
  • Loading branch information
Brandon Dail authored and Brandon Dail committed Apr 26, 2016
1 parent de3664f commit 81ce26d
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 0 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"license": "MIT",
"dependencies": {
"cheerio": "^0.20.0",
"is-regex": "^1.0.3",
"is-subset": "^0.1.1",
"lodash": "^4.8.2",
"object.assign": "^4.0.3",
Expand Down
8 changes: 8 additions & 0 deletions src/MountedTraversal.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ export function instHasClassName(inst, className) {
return ` ${classes} `.indexOf(` ${className} `) > -1;
}

export function instMatchesClassName(inst, regex) {
if (!isDOMComponent(inst)) {
return false;
}
const classes = findDOMNode(inst).className || '';
return regex.test(classes);
}

export function instHasId(inst, id) {
if (!isDOMComponent(inst)) return false;
const instId = findDOMNode(inst).id || '';
Expand Down
18 changes: 18 additions & 0 deletions src/ReactWrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ import cheerio from 'cheerio';
import flatten from 'lodash/flatten';
import unique from 'lodash/uniq';
import compact from 'lodash/compact';
import isRegex from 'is-regex';
import createWrapperComponent from './ReactWrapperComponent';
import {
instHasClassName,
instMatchesClassName,
childrenOfInst,
parentsOfInst,
buildInstPredicate,
Expand Down Expand Up @@ -534,6 +536,22 @@ export default class ReactWrapper {
return this.single(n => instHasClassName(n, className));
}

/**
* Returns whether or not the current root node has a class matching the
* passed regular expression
*
* NOTE: can only be called on a wrapper of a single node.
*
* @param {RegExp} regex
* @returns {Boolean}
*/
matchesClass(regex) {
if (!isRegex(regex)) {
throw new Error('matchesClass expects a regular expression as its only argument.');
}
return this.single(n => instMatchesClassName(n, regex));
}

/**
* Iterates through each node of the current wrapper and executes the provided function with a
* wrapper around the corresponding node passed in as the first argument.
Expand Down
5 changes: 5 additions & 0 deletions src/ShallowTraversal.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ export function hasClassName(node, className) {
return ` ${classes} `.indexOf(` ${className} `) > -1;
}

export function matchesClassName(node, regex) {
const classes = propsOfNode(node).className || '';
return regex.test(classes);
}

export function treeForEach(tree, fn) {
if (tree !== null && tree !== false && typeof tree !== 'undefined') {
fn(tree);
Expand Down
17 changes: 17 additions & 0 deletions src/ShallowWrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import flatten from 'lodash/flatten';
import unique from 'lodash/uniq';
import compact from 'lodash/compact';
import cheerio from 'cheerio';
import isRegex from 'is-regex';
import {
nodeEqual,
containsChildrenSubArray,
Expand All @@ -17,6 +18,7 @@ import {
import {
getTextFromNode,
hasClassName,
matchesClassName,
childrenOfNode,
parentsOfNode,
treeFilter,
Expand Down Expand Up @@ -522,6 +524,21 @@ export default class ShallowWrapper {
return this.single(n => hasClassName(n, className));
}

/**
* Returns whether or not the current root node has the given class name or not.
*
* NOTE: can only be called on a wrapper of a single node.
*
* @param className
* @returns {Boolean}
*/
matchesClass(regex) {
if (!isRegex(regex)) {
throw new Error('matchesClass expects a regular expression as its only argument.');
}
return this.single(n => matchesClassName(n, regex));
}

/**
* Iterates through each node of the current wrapper and executes the provided function with a
* wrapper around the corresponding node passed in as the first argument.
Expand Down
20 changes: 20 additions & 0 deletions test/ReactWrapper-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1374,6 +1374,26 @@ describeWithDOM('mount', () => {
});
});

describe('.matchesClass(regex)', () => {
it('should match class names with a regular expression', () => {
const wrapper = mount(
<div className="foo bar baz some-long-string FoOo bling-42" />
);

expect(wrapper.matchesClass(/foo/)).to.equal(true);
expect(wrapper.matchesClass(/bar/)).to.equal(true);
expect(wrapper.matchesClass(/baz/)).to.equal(true);
expect(wrapper.matchesClass(/some-long-string/)).to.equal(true);
expect(wrapper.matchesClass(/FoOo/)).to.equal(true);
expect(wrapper.matchesClass(/bling/)).to.equal(true);
expect(wrapper.matchesClass(/doesnt-exist/)).to.equal(false);
});
it('should throw if the argument is not a regular expression', () => {
const wrapper = mount(<div className="foo" />);
expect(() => wrapper.matchesClass('string')).to.throw(Error);
});
});

describe('.forEach(fn)', () => {
it('should call a function for each node in the wrapper', () => {
const wrapper = mount(
Expand Down
20 changes: 20 additions & 0 deletions test/ShallowWrapper-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1582,6 +1582,26 @@ describe('shallow', () => {
});
});

describe('.matchesClass(regex)', () => {
it('should match class names with a regular expression', () => {
const wrapper = shallow(
<div className="foo bar baz some-long-string FoOo bling-42" />
);

expect(wrapper.matchesClass(/foo/)).to.equal(true);
expect(wrapper.matchesClass(/bar/)).to.equal(true);
expect(wrapper.matchesClass(/baz/)).to.equal(true);
expect(wrapper.matchesClass(/some-long-string/)).to.equal(true);
expect(wrapper.matchesClass(/FoOo/)).to.equal(true);
expect(wrapper.matchesClass(/bling/)).to.equal(true);
expect(wrapper.matchesClass(/doesnt-exist/)).to.equal(false);
});
it('should throw if the argument is not a regular expression', () => {
const wrapper = shallow(<div className="foo" />);
expect(() => wrapper.matchesClass('string')).to.throw(Error);
});
});

describe('.forEach(fn)', () => {
it('should call a function for each node in the wrapper', () => {
const wrapper = shallow(
Expand Down

0 comments on commit 81ce26d

Please sign in to comment.