I use css-modules and have trouble with this selector:
.PlaybackBar__minimize___Psnl-.PlaybackBar__button___mzBxL
const wrapper = shallow(<div><button className="PlaybackBar__minimize___Psnl- PlaybackBar__button___mzBxL"></button></div>);
expect(wrapper.find('.PlaybackBar__minimize___Psnl-.PlaybackBar__button___mzBxL')).to.have.length(1);
Problem here https://github.com/nfpiche/enzyme/blob/master/src/Utils.js#L179.
I suggest to supplement the regex.
Hey @fresk-nc, thanks for the issue! I was able to reproduce a simplified case. You can see it here: Aweary/enzyme-test-repo/blob/issue-413/test.js. The issue is the dash after the first class name. You can see in the test case that by adding a trailing dash:
const firstClass = 'foo'
const secondClass = 'bar'
const transformedFirstClass = firstClass + '-'
const transformedSecondClass = secondClass
It causes the query to fail. I did verify that a trailing dash works fine in an actual DOM environment:
div = document.createElement('div')
div.classList.add('foo-')
div.classList.add('bar')
document.body.appendChild(div)
document.querySelector('.foo-.bar')
// > <div class="foo- bar"></div>
So we should definitely fix this so it matches querySelector's behavior. We'll look into this as soon as we can 👍
I'm going to use this issue to document any other valid compound selectors that aren't being identified correctly. I'm testing these against what document.querySelector allows in the latest version of Chrome, FWIW.
'[foo="true"].bar'
'[foo="true"][bar="true"]'
.foo#_bar
Also broken,
test.only('weird-but-not-that-weird input names', t => {
const $ = mount(<input type="checkbox" name="hours[]" value="0" />);
t.is($.find('[name="hours[]"]').length, 1);
});
Compound selector is unable to handle if className starts with _ or - it seems. I just hit this one..
it.only('Selector Bug', () => {
const wrapper = shallow(
<div className='abc'>
<div className='_startsWithUnderscore'/>
<div className='nounderscore'/>
</div>
);
should(wrapper.find('div.nounderscore').length).be.exactly(1); //passes
should(wrapper.find('.nounderscore').length).be.exactly(1); //passes
should(wrapper.find('._startsWithUnderscore').length).be.exactly(1); //passes
//below fails
should(wrapper.find('div._startsWithUnderscore').length).be.exactly(1);
});
a quick look this seems to be where the issue is https://github.com/airbnb/enzyme/blob/master/src/Utils.js#L179
Just discovered this same issue attempting to test CSS Modules also.
The regex here only covers selectors beginning and ending with an alpha character
https://github.com/airbnb/enzyme/blob/master/src/Utils.js#L179
However the spec allows for much more than that.
In CSS, identifiers (including element names, classes, and IDs in selectors) can contain only the characters [a-zA-Z0-9] and ISO 10646 characters U+00A0 and higher, plus the hyphen (-) and the underscore (_); they cannot start with a digit, two hyphens, or a hyphen followed by a digit. Identifiers can also contain escaped characters and any ISO 10646 character as a numeric code (see next item). For instance, the identifier "B&W?" may be written as "B&W\?" or "B\26 W\3F".
https://www.w3.org/TR/CSS2/syndata.html#value-def-identifier
Unrealistic to cover the spec as it's not really "regular". But perhaps we can widen the gamut? Happy to submit PR if anyone has suggestions on what a nice middle ground to cover is?
As a side note, those hoping to test cssmodules, a workaround is to generate a valid local scope string. I'm using css-modules-require-hook in my test-setup.js
import hook from 'css-modules-require-hook';
import sass from 'node-sass';
hook({
extensions: [ '.scss' ],
preprocessCss: data => sass.renderSync({ data }).css,
generateScopedName: '[name]__[local]',
});
I've run into an issue with not being able to find compound selectors. I thought it might be similar to @dannyshaw's issue since I'm using a setup similar to his, but after removing the underscores from the class names I'm still running into the issue.
If my component looks like this:
<button>
<i className={ classNames(styles.a, styles.b, styles.c) } />
</button>
I can't select it:
expect(button().find(`.${styles.icon}`).length).to.eq(1);
I've been able to get around this by using findWhere.
button().findWhere(n => n.hasClass(styles.icon))
@aweary is this covered by v3?
@ljharb I just verified that rst-selector-parser correctly parses class names with leading _ or -. So this should be resolved in v3!
Most helpful comment
@ljharb I just verified that
rst-selector-parsercorrectly parses class names with leading_or-. So this should be resolved in v3!