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

Refactor ownProperty #810

Merged
merged 2 commits into from
Sep 29, 2016
Merged

Refactor ownProperty #810

merged 2 commits into from
Sep 29, 2016

Conversation

meeber
Copy link
Contributor

@meeber meeber commented Sep 28, 2016

This PR is split into two commits. The first commit addresses a small issue with the failed assertion error message being inconsistent across property-related assertions. Sometimes the message was "expected blah to have a property..." and other times it was "expected blah to have property". I settled on the second style because otherwise the logic gets more complex having to deal with changing between "a" or "an" depending on if the next word in the message starts with a vowel (such as "own").

The second commit makes the following changes:

  • Add own flag
  • Make ownProperty and haveOwnProperty aliases of own.property
  • Add deep support to own.property
  • Add assert.deepOwnPropertyVal
  • Add assert.notDeepOwnPropertyVal

Closes #795.

@meeber meeber changed the title Refactor own property Refactor ownProperty Sep 28, 2016
@vieiralucas
Copy link
Member

So, chai will only throw if own is used alongside nested flags when a property assertion is made.

Which means that there is "nothing wrong" with this:

expect('test').to.have.own.nested.length(4);

I'm ok with that.

@meeber, this is awesome work. I can not say anything but LGTM

Copy link
Member

@lucasfcosta lucasfcosta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @meeber, excellent work (as always 😄)
The whole logic and implementation looks complete on every interface and on the core, however I suggested some minor details on comments just to make sure we're being clear and also one more test to assure we're unable to use own and nested together.
Also, what do you think about changing those multiple combined ternary operators into if/else clauses?

Please let me know if you disagree with anything I said.
Thanks for this PR 😄

, value = isNested
? pathInfo.value
: obj[name];
, hasProperty = isOwn ? Object.prototype.hasOwnProperty.call(obj, name)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I like all these ternary operators.
What do you guys think about using if and else clauses?
This is totally understandable, but making this behavior more clear might make these conditions look better and more easily understandable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But all these nested ternaries like you :(

I'll change :(

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hahahahaha, I see no problem in keeping them there, it's just a matter of personal taste, would you like to keep them?
If you do, please don't be afraid to say it, there's no problem if you prefer that way 😄

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I'd rather be sad :(

Plus I checked @keithamus's eslint config and he doesn't like nested ternaries either :(

* Asserts that `object` has a property named by `property` with value given
* by `value`. `property` can use dot- and bracket-notation for nested
* reference. Uses a strict equality check (===).
* Asserts that `object` has a direct property named by `property`.
Copy link
Member

@lucasfcosta lucasfcosta Sep 28, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that only saying "direct property" isn't enough to make this explanation clear, maybe we could add (non-inherited) after the word direct just to make sure we're being clear.

I don't think this is needed in the other methods where we mention inherited properties, since that contrast already explains everything by itself.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. I actually had something to the effect of "but not inherited" in a previous iteration, but ended up removing it because the way I had it worded made it sound like the assertion would fail if the object had an inherited property with the given name, whereas it's allowed to have an inherited property with the given name as long as it also has a direct property with the same name. I should be able to reword it to not sound ambiguous though.

/**
* ### .notOwnProperty(object, property, [message])
*
* Asserts that `object` does _not_ have a direct property named by `property`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here as on L1183.

/**
* ### .ownPropertyVal(object, property, value, [message])
*
* Asserts that `object` has a direct property named by `property` and a value
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here as on L1183.

* Asserts that `object` does _not_ have a property named by `property` with
* value given by `value`. `property` can use dot- and bracket-notation for
* nested reference. Uses a strict equality check (===).
* Asserts that `object` does _not_ have a direct property named by `property`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here as on L1183.

* Asserts that `object` has a property named by `property` with a value given
* by `value`. `property` can use dot- and bracket-notation for nested
* reference. Uses a deep equality check.
* Asserts that `object` has a direct property named by `property` and a value
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here as on L1183.

* Asserts that `object` does _not_ have a property named by `property` with
* value given by `value`. `property` can use dot- and bracket-notation for
* nested reference. Uses a deep equality check.
* Asserts that `object` does _not_ have a direct property named by `property`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here as on L1183.

expect({ 'foo.bar': 'baz' })
.to.have.nested.property('foo.bar');
}, "expected { 'foo.bar': 'baz' } to have a nested property 'foo.bar'");
}, "expected { foo: { bar: 'baz' } } to have property 'foo.bar'");
});

it('property(name, val)', function(){
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO it would be good to have tests to see if we're really unable to use both own and nested together.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed!

err(function(){
({ 'foo.bar': 'baz' }).should.have.nested.property('foo.bar');
}, "expected { 'foo.bar': 'baz' } to have a nested property 'foo.bar'");
}, "expected 'asd' to have property 'foo'");
});

it('property(name, val)', function(){
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO it would be good to have tests to see if we're really unable to use both own and nested together.

- Add `own` flag
- Make `ownProperty` and `haveOwnProperty` aliases of `own.property`
- Add `deep` support to `own.property`
- Add `assert.deepOwnPropertyVal`
- Add `assert.notDeepOwnPropertyVal`
@meeber
Copy link
Contributor Author

meeber commented Sep 28, 2016

Pushed new version with better comments, more tests, and fewer glorious ternaries.

@lucasfcosta
Copy link
Member

LGTM!
Awesome work @meeber, I'll leave this here for you to merge if you want to use the ternaries we had before 😄
If you are happy with the current version of this please feel free to hit the merge button!

@meeber
Copy link
Contributor Author

meeber commented Sep 28, 2016

@lucasfcosta Thanks for reviewing! Good catches :D

I'll leave this open another day for @keithamus and/or @vieiralucas to look at since I made some changes.

I like it fine without the fabulous ternaries, just giving you a hard time :D

@meeber meeber merged commit 5dd96a0 into chaijs:master Sep 29, 2016
@meeber meeber deleted the refactor-own-property branch September 29, 2016 20:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants