Support for checking nested properties
sazzer opened this issue · 10 comments
I might have missed it - apologies if so - but it would be very useful to support testing nested properties. Something like:
const value = {
a: {
b: {
c: 1
},
d: {
c: 2
}
}
};
expect(value, 'to have deep property', 'a.b.c', 1);
I'd use:
expect(value, 'to satisfy', { a: { b: { c: 1 } } });
But it's quite easy to implement to have deep property
as a shorthand for that:
expect.addAssertion(
'<object> to have deep property <string> <any>',
(expect, subject, deepPropertyName, value) =>
expect(
subject,
'to satisfy',
deepPropertyName
.split('.')
.reverse()
.reduce((acc, propertyName) => ({ [propertyName]: acc }), value)
)
);
It produces a nice diff when there's a mismatch because to satisfy
comes with one:
expected { a: { b: { c: 1 }, d: { c: 2 } } } to have deep property 'a.b.c', 2
{
a: {
b: {
c: 1 // should equal 2
},
d: { c: 2 }
}
}
'to satisfy' is perfect. I as surprised it wasn't an option when I looked.
In that case, can I suggest linking this from the docs for 'to have property' for people like me? :-)
Sent from my HUAWEI WAS-LX1A using FastHub
Do other assertion libraries support the a.b.c
syntax, or how did you get the idea?
Oh, I see. A PR for adding that to the docs would be welcome. Here's the relevant file: https://github.com/unexpectedjs/unexpected/blob/master/documentation/assertions/object/to-have-property.md
Just a quick note to mention that jest-expect also has this and calls it key-paths. You can use it to assert the presence of a key in a structure but also validate the value by supplying a second argument.
This seems like a pretty useful feature, maybe we should support it.
Since .
is also a valid character in field names, it would create ambiguity. When I (very briefly) worked with MongoDB I remember being angry about a.b.c
in query objects meaning nested fields, which made it impossible to query a property with .
in the name.
Yes you are probably right that the convenience is not worth ambiguity.
Let's just document why it doesn't work, as the OP suggested. Added here: #575