Skip to content

Commit

Permalink
[New]: shallow/mount: selectors: support universal selector
Browse files Browse the repository at this point in the history
  • Loading branch information
chenesan authored and ljharb committed Dec 16, 2018
1 parent aa1af32 commit 7bd0bdb
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/api/selector.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ follows:
- element tag name syntax (`input`, `div`, `span`, etc.)
- id syntax (`#foo`, `#foo-bar`, etc.)
- attribute syntax (`[href="foo"]`, `[type="text"]`, and the other attribute selectors listed [here](https://developer.mozilla.org/en-US/docs/Learn/CSS/Introduction_to_CSS/Attribute_selectors).)
- universal syntax (`*`)

The attribute syntax also works by value, rather than by string. Strings, numbers, and boolean property values are supported. Example:

Expand Down
110 changes: 110 additions & 0 deletions packages/enzyme-test-suite/test/selector-spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,116 @@ describe('selectors', () => {
};
});
describeMethod(name, () => {
it('universal selector *', () => {
const wrapper = renderMethod((
<div>
<div className="top-div">
<span>inside top div</span>
</div>

<div className="bottom-div" />
<span />
</div>
));

expect(wrapper.find('*')).to.have.lengthOf(5);
});

it('* + *', () => {
const wrapper = renderMethod((
<div>
<div className="top-div">
<span>inside top div</span>
</div>
<div className="bottom-div" />
<span />
</div>
));

expect(wrapper.find('* + *')).to.have.lengthOf(2);
});

it('.top-div ~ *', () => {
const wrapper = renderMethod((
<div>
<div className="top-div">
<span>inside top div</span>
</div>
<div className="bottom-div" />
<span />
</div>
));

expect(wrapper.find('.top-div ~ *')).to.have.lengthOf(2);
});

it('* > span', () => {
const wrapper = renderMethod((
<div>
<div className="top-div">
<span>inside top div</span>
</div>
<div className="bottom-div" />
<span />
</div>
));

expect(wrapper.find('* > span')).to.have.lengthOf(2);
});

it('* .top-div *', () => {
const wrapper = renderMethod((
<div>
<div className="top-div">
<span>inside top div</span>
</div>
<div className="bottom-div" />
<span id="bottom-span" />
</div>
));

expect(wrapper.find('* .top-div *')).to.have.lengthOf(1);
});

it('#wrap-div > *', () => {
const wrapper = renderMethod((
<div id="wrap-div">
<div className="top-div">
<span>inside top div</span>
</div>
<div className="bottom-div" />
<span id="bottom-span" />
</div>
));

expect(wrapper.find('#wrap-div > *')).to.have.lengthOf(3);
});

it('universal selector should also find component node', () => {
class ExampleComponent extends React.Component {
render() {
return <span>Hello world</span>;
}
}
const wrapper = renderMethod((
<div id="wrap-div">
<div className="top-div">
<ExampleComponent />
</div>
<div className="bottom-div" />
<ExampleComponent />
</div>
));

expect(wrapper.find('* > ExampleComponent')).to.have.lengthOf(2);
if (name === 'shallow') {
// cannot render span inside ExampleComponent when shallow rendering
expect(wrapper.find('*')).to.have.lengthOf(5);
} else {
expect(wrapper.find('*')).to.have.lengthOf(7);
}
});

it('simple descendent', () => {
const wrapper = renderMethod((
<div>
Expand Down
7 changes: 7 additions & 0 deletions packages/enzyme/src/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const SELECTOR = 'selector';
const TYPE_SELECTOR = 'typeSelector';
const CLASS_SELECTOR = 'classSelector';
const ID_SELECTOR = 'idSelector';
const UNIVERSAL_SELECTOR = 'universalSelector';
const ATTRIBUTE_PRESENCE = 'attributePresenceSelector';
const ATTRIBUTE_VALUE = 'attributeValueSelector';
// @TODO we dont support these, throw if they are used
Expand Down Expand Up @@ -184,6 +185,12 @@ function nodeMatchesToken(node, token, root) {
return false;
}
switch (token.type) {
/**
* Match every node
* @example '*' matches every node
*/
case UNIVERSAL_SELECTOR:
return true;
/**
* Match against the className prop
* @example '.active' matches <div className='active' />
Expand Down

0 comments on commit 7bd0bdb

Please sign in to comment.