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

Implement matchesClass method for class name matching with RegExp #349

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -56,6 +56,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
21 changes: 21 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,25 @@ 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(
`ReactWrapper::matchesClass() expects a regular expression,
receieved a ${typeof regex} instead.`
);
}
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 @@ -33,6 +33,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
20 changes: 20 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,24 @@ 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(
`ShallowWrapper::matchesClass() expects a regular expression
receieved a ${typeof regex} instead.`
);
}
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 @@ -1391,6 +1391,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 @@ -1598,6 +1598,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