-
-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Support all attribute selector operators #1157
Conversation
packages/enzyme/src/Utils.js
Outdated
@@ -219,23 +219,17 @@ export function AND(fns) { | |||
return x => fnsReversed.every(fn => fn(x)); | |||
} | |||
|
|||
export function nodeHasProperty(node, propKey, propValue) { | |||
export function nodeHasMatchingProperty(node, propKey, matcher) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could probably just inline this in matchAttributeSelector
since its only used once, and its not exported for testing like nodeHasProperty
was
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds like a good idea, the less we export the better
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome!
describe('selectors', () => { | ||
tests.forEach(({ describeMethod, name, renderMethod }) => { | ||
before(() => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is "before all"; could we use beforeEach
instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could, but "before all" is the intention here, since expectAttributeMatch
only needs to be initialized once per renderMethod
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fair; beforeAll tends to cause test flakiness in my experience
packages/enzyme/src/Utils.js
Outdated
@@ -219,23 +219,17 @@ export function AND(fns) { | |||
return x => fnsReversed.every(fn => fn(x)); | |||
} | |||
|
|||
export function nodeHasProperty(node, propKey, propValue) { | |||
export function nodeHasMatchingProperty(node, propKey, matcher) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds like a good idea, the less we export the better
packages/enzyme/src/selectors.js
Outdated
return nodeHasMatchingProperty(node, token.name, (nodePropValue, nodeProps) => { | ||
const { operator, value } = token; | ||
if (token.type === ATTRIBUTE_PRESENCE) { | ||
return Object.prototype.hasOwnProperty.call(nodeProps, token.name); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please use the has
module for this
packages/enzyme/src/selectors.js
Outdated
* [type^="image"] matches type="imageobject" | ||
*/ | ||
case PREFIX_ATTRIBUTE_OPERATOR: | ||
return value === '' ? false : nodePropValue.substr(0, value.length) === value; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we use slice
instead of substr
here?
packages/enzyme/src/selectors.js
Outdated
* [type$="image"] matches type="imageobject" | ||
*/ | ||
case SUFFIX_ATTRIBUTE_OPERATOR: | ||
return value === '' ? false : nodePropValue.substr(-value.length) === value; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also here?
a9c3776
to
bb08320
Compare
@ljharb feedback has been addressed 👌 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
bb08320
to
c64dfe0
Compare
Hi @aweary - I've been meaning to put in a PR for this, looks like you beat me to it! Thought it'd be a good opportunity to see how a more experienced dev went about the same task. Hope you don't mind me commenting on a couple of bits 🙂 |
expectAttributeMatch(<div rel="foo bar baz" />, '[rel~="baz"]', true); | ||
expectAttributeMatch(<div rel="foo bar baz" />, '[rel~="foo"]', true); | ||
expectAttributeMatch(<div rel="foo bar baz" />, '[rel~="foo bar"]', false); | ||
expectAttributeMatch(<div rel={1} />, '[rel~=1]', false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct me if I'm wrong - shouldn't this return true? I think ~=
should still match if it's exactly equal, with no whitespace.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jack-lewin this implementation only supports matching strings with these partial match operators, so all other types will return false
. If you want to match exactly equal values you should use =
expectAttributeMatch(<div data-foo={Infinity} />, '[data-foo=+Infinity]', true); | ||
expectAttributeMatch(<div data-foo={Infinity} />, '[data-foo=-Infinity]', false); | ||
expectAttributeMatch(<div data-foo={Infinity} />, '[data-foo=NaN]', false); | ||
expectAttributeMatch(<div data-foo={0} />, '[data-foo=Infinity]', false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like this test is duplicated at the bottom of the it
block - should one of them be testing -Infinity
, as per the old tests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think so, thanks!
* [rel~="copyright"] matches rel="copyright other" | ||
*/ | ||
case WHITELIST_ATTRIBUTE_OPERATOR: | ||
return nodePropValue.split(' ').indexOf(value) !== -1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would throw an error if nodePropValue
isn't a string - is it safe to assume that if someone's using ~=
, they're testing a string? Or would it be safer to return false if not?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's an earlier check that tests for non-string values, so we can safely assume that nodePropValue
and value
are both strings in this case.
is it safe to assume that if someone's using ~=, they're testing a string?
Yupp, that's exactly the assumption! These operators don't make a whole lot of sense with other values like numbers or objects.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I must've missed that. It makes a lot more sense now, thanks for explaining!
packages/enzyme/src/selectors.js
Outdated
@@ -32,6 +34,13 @@ const ATTRIBUTE_VALUE = 'attributeValueSelector'; | |||
const PSEUDO_CLASS = 'pseudoClassSelector'; | |||
const PSEUDO_ELEMENT = 'pseudoElementSelector'; | |||
|
|||
const EXACT_ATTRIBUTE_OPERATOR = '='; | |||
const WHITELIST_ATTRIBUTE_OPERATOR = '~='; | |||
const HYPEN_ATTRIBUTE_OPERATOR = '|='; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this a typo? I wouldn't expect this to be called "hyphen attribute operator", but i have also never heard of "hypen" so i'm pretty sure that's what this is attempting to be called?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lelandrichardson Yeah "hypen" is a typo, it should be hyphen. I wasn't really sure what to call it, the spec doesn't provide canonical names and it's kind of a weird operator. Any suggestions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm - it can also be a whole word, not just a hyphenated section. maybe "hyphenated attribute operator" is still the best name tho
@aweary If this can be rebased and existing comments addressed, we can probably re-review it and get it in :-) |
c64dfe0
to
9d9a3a8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
packages/enzyme/src/selectors.js
Outdated
return is(nodePropValue, value); | ||
/** | ||
* Represents an element with the att attribute whose value is a whitespace-separated | ||
* list of words, one of which is exactly |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this trailing space is breaking the linter
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Woops! Fixed 👌
I'll merge this tomorrow if there's no objections. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
8340c6b
to
dec1505
Compare
nodeHasProperty
in favor ofnodeHasMatchingProperty
nodeHasProperty
utility. This decouples the tests from the internal implementation and also makes them more robust. I discovered Unable to parse selectors with numeric values in exponential notation #1155 while doing this.