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

feat(assertObjectMatchSpec): Compare object keys when doing a full match #56

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

leguellec
Copy link
Contributor

resolves #44

As proposed by @plouc, the current way to fully match a json object to a given spec, was a bit too naïve. The introduced changes now handles the comparison based on object keys and spec keys. In consequences, a spec can now have multiple matcher on an object fields without impact on a full match.

})

test('should allow to count nested objects properties', () => {
test('should allow to build an array of object propertieswith nested objects properties', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
test('should allow to build an array of object propertieswith nested objects properties', () => {
test('should allow to build an array of object properties with nested objects properties', () => {

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

*
* @param {Object} object
* @return {number}
*/
exports.countNestedProperties = (object) => {
let propertiesCount = 0
exports.buildObjectKeysArray = (object, dottedObjectKeys = [], currentPath = '') => {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: what about something like objectKeysDeep? Feels more aligned with the native API and other tools like lodash.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yup, better name for sure

*
* @param {Object} object
* @return {number}
*/
exports.countNestedProperties = (object) => {
let propertiesCount = 0
exports.buildObjectKeysArray = (object, dottedObjectKeys = [], currentPath = '') => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
exports.buildObjectKeysArray = (object, dottedObjectKeys = [], currentPath = '') => {
exports.buildObjectKeysArray = (object, keysAccumulator = [], parentPath = '') => {

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

*
* @param {Object} object
* @return {number}
*/
exports.countNestedProperties = (object) => {
let propertiesCount = 0
exports.buildObjectKeysArray = (object, dottedObjectKeys = [], currentPath = '') => {
Object.keys(object).forEach((key) => {
if (!_.isEmpty(object[key]) && typeof object[key] === 'object') {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
if (!_.isEmpty(object[key]) && typeof object[key] === 'object') {
if (!_.isEmpty(object[key]) && _.isPlainObject(object[key])) {

Copy link
Contributor Author

Choose a reason for hiding this comment

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

A better test for sure, but as we also take into account nested arrays, i also added a condition for it, which impact your next comment :)

*
* @param {Object} object
* @return {number}
*/
exports.countNestedProperties = (object) => {
let propertiesCount = 0
exports.buildObjectKeysArray = (object, dottedObjectKeys = [], currentPath = '') => {
Object.keys(object).forEach((key) => {
Copy link
Contributor

@plouc plouc Dec 18, 2020

Choose a reason for hiding this comment

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

I think we could add a guard and throw with a meaningful message in case object is actually not an Object, what do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

With new conditions, if an object (or an array) is passed, you will get a result, otherwise an empty array is returned, and the exact assertions between spec and object will fail. Maybe not the best way to do it, should need some improvement, but the recursive nature of objectKeysDeep, will force us to detect if it's the first iteration and then validate the given input. Maybe should we check object correctness in assertObjectMatchSpec ?

Copy link
Contributor

Choose a reason for hiding this comment

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

Good point! Yea, we could do this in assertObjectMatchSpec.

Comment on lines 31 to 34
* Make an array of keys from an object.
* Use a dot notation
* Only empty object keys are taken into account
* For subobjects only keys are taken into account
Copy link
Contributor

@plouc plouc Dec 18, 2020

Choose a reason for hiding this comment

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

Suggested change
* Make an array of keys from an object.
* Use a dot notation
* Only empty object keys are taken into account
* For subobjects only keys are taken into account
* Acts as `Object.keys()`, but runs recursively,
* another difference is that when one of the key refers to
* a non-empty object, it's gonna be ignored.
*
* Keys for nested objects are prefixed with their parent key.
*
* Also note that this is not fully interoperable with `lodash.get`
* for example as keys themselves can contain dots or special characters.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@@ -13,17 +17,17 @@ afterAll(() => {

beforeEach(() => {})

test('should allow to count object properties', () => {
test('should allow to build an array of object properties', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd suggest to add a test where we pass an invalid object, and also a test where properties contain dots or spaces.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've added some, may need rework depending on what we decide :)

@@ -208,11 +229,12 @@ exports.assertObjectMatchSpec = (object, spec, exact = false) => {

// We check we have exactly the same number of properties as expected
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// We check we have exactly the same number of properties as expected
// We check we have exactly the same properties as expected

Copy link
Contributor

Choose a reason for hiding this comment

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

Or just remove this comment

@pebie pebie force-pushed the master branch 3 times, most recently from 2a1f5cd to 7fa350d Compare January 14, 2022 13:46
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.

assertObjectMatchSpec improvement
4 participants