Skip to content

Commit

Permalink
Merge pull request #670 from ljharb/fix_id_selectors
Browse files Browse the repository at this point in the history
[Fix] `mount`/`shallow`: fix ID selectors

Fixes #495.
  • Loading branch information
ljharb authored Nov 9, 2016
2 parents 33b5680 + d3af3dc commit 459f86a
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 2 deletions.
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@
"lodash": "^4.16.4",
"object-is": "^1.0.1",
"object.assign": "^4.0.4",
"object.values": "^1.0.3"
"object.entries": "^1.0.3",
"object.values": "^1.0.3",
"uuid": "^2.0.3"
},
"devDependencies": {
"babel-cli": "^6.18.0",
Expand Down
22 changes: 21 additions & 1 deletion src/Utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
import isEqual from 'lodash/isEqual';
import React from 'react';
import is from 'object-is';
import uuid from 'uuid';
import entries from 'object.entries';
import assign from 'object.assign';
import functionName from 'function.prototype.name';
import {
isDOMComponent,
Expand Down Expand Up @@ -171,7 +174,24 @@ export function withSetStateAllowed(fn) {
}

export function splitSelector(selector) {
return selector.split(/(?=\.|\[.*])|(?=#|\[#.*])/);
// step 1: make a map of all quoted strings with a uuid
const quotedSegments = selector.split(/[^" ]+|("[^"]*")|.*/g)
.filter(Boolean)
.reduce((obj, match) => assign({}, obj, { [match]: uuid.v4() }), {});

return selector
// step 2: replace all quoted strings with the uuid, so we don't have to properly parse them
.replace(/[^" ]+|("[^"]*")|.*/g, x => quotedSegments[x] || x)
// step 3: split as best we can without a proper parser
.split(/(?=\.|\[.*])|(?=#|\[#.*])/)
// step 4: restore the quoted strings by swapping back the uuid's for the original segments
.map((selectorSegment) => {
let restoredSegment = selectorSegment;
entries(quotedSegments).forEach(([k, v]) => {
restoredSegment = restoredSegment.replace(v, k);
});
return restoredSegment;
});
}


Expand Down
24 changes: 24 additions & 0 deletions test/ReactWrapper-spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,30 @@ describeWithDOM('mount', () => {
expect(wrapper.find('[key]')).to.have.length(0);
});
});

describe('works with attribute selectors containing #', () => {
let wrapper;
beforeEach(() => {
wrapper = mount(
<div>
<a id="test" href="/page">Hello</a>
<a href="/page#anchor">World</a>
</div>
);
});

it('works with an ID', () => {
expect(wrapper.find('a#test')).to.have.lengthOf(1);
});

it('works with a normal attribute', () => {
expect(wrapper.find('a[href="/page"]')).to.have.lengthOf(1);
});

it('works with an attribute with a #', () => {
expect(wrapper.find('a[href="/page#anchor"]')).to.have.lengthOf(1);
});
});
});

describe('.findWhere(predicate)', () => {
Expand Down
24 changes: 24 additions & 0 deletions test/ShallowWrapper-spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,30 @@ describe('shallow', () => {
expect(wrapper.find('Foo').type()).to.equal(Foo);
});
});

describe('works with attribute selectors containing #', () => {
let wrapper;
beforeEach(() => {
wrapper = shallow(
<div>
<a id="test" href="/page">Hello</a>
<a href="/page#anchor">World</a>
</div>
);
});

it('works with an ID', () => {
expect(wrapper.find('a#test')).to.have.lengthOf(1);
});

it('works with a normal attribute', () => {
expect(wrapper.find('a[href="/page"]')).to.have.lengthOf(1);
});

it('works with an attribute with a #', () => {
expect(wrapper.find('a[href="/page#anchor"]')).to.have.lengthOf(1);
});
});
});

describe('.findWhere(predicate)', () => {
Expand Down

0 comments on commit 459f86a

Please sign in to comment.