All causes = null when validating v8n().schema using testAll
maxgalbu opened this issue · 5 comments
function recursiveFindCause(validationError, parentField = "") {
for (const cause of validationError.cause) {
if (Array.isArray(cause.cause)) {
recursiveFindCause(cause, cause.target);
} else {
console.log("%s%s cause: %s", parentField ? parentField + "." : "",
cause.target, JSON.stringify(cause.cause));
}
}
}
const validJsonSchema = v8n().schema({
placement_code: v8n().string(),
section_code: v8n().string(),
device_code: v8n().string(),
country_code: v8n().string(),
language_code: v8n().string(),
ad_blocker: v8n().boolean(),
params: v8n().schema({
token: v8n().string(),
currency_code: v8n().string(),
user_country_code: v8n().string(),
user_id: v8n().string(),
check_in_date: v8n().string(),
check_out_date: v8n().string(),
destination: v8n().string(),
destination_latitude: v8n().string(),
destination_longitude: v8n().string(),
rooms: v8n().array().every.schema({
adults: v8n().number(),
children: v8n().number(),
}),
cbuster: v8n().string(),
custom_fields: v8n().schema({})
}),
is_test: v8n().boolean(),
partner: v8n().schema({
name: v8n().string(),
iframe_blocked: v8n().passesAnyOf(v8n().number(), v8n().boolean()),
network_code: v8n().string(),
code: v8n().string(),
net_value: v8n().string(),
virtual_value: v8n().string(),
}),
client_code: v8n().string(),
});
const validationErrors = validJsonSchema.testAll(json);
if (validationErrors.length) {
recursiveFindCause(validationErrors[0]);
}
When json
is { "placement_code": "hello", "device_code": true, "params": 1 }
, this code outputs:
[Thu Oct 29 2020 08:01:46] [LOG] section_code cause: null
[Thu Oct 29 2020 08:01:46] [LOG] device_code cause: null
[Thu Oct 29 2020 08:01:46] [LOG] country_code cause: null
[Thu Oct 29 2020 08:01:46] [LOG] language_code cause: null
[Thu Oct 29 2020 08:01:46] [LOG] ad_blocker cause: null
[Thu Oct 29 2020 08:01:46] [LOG] params.token cause: null
[Thu Oct 29 2020 08:01:46] [LOG] params.currency_code cause: null
[Thu Oct 29 2020 08:01:46] [LOG] params.user_country_code cause: null
[Thu Oct 29 2020 08:01:46] [LOG] params.user_id cause: null
[Thu Oct 29 2020 08:01:46] [LOG] params.check_in_date cause: null
[Thu Oct 29 2020 08:01:46] [LOG] params.check_out_date cause: null
[Thu Oct 29 2020 08:01:46] [LOG] params.destination cause: null
[Thu Oct 29 2020 08:01:46] [LOG] params.destination_latitude cause: null
[Thu Oct 29 2020 08:01:46] [LOG] params.destination_longitude cause: null
[Thu Oct 29 2020 08:01:46] [LOG] params.rooms cause: null
[Thu Oct 29 2020 08:01:46] [LOG] params.cbuster cause: null
[Thu Oct 29 2020 08:01:46] [LOG] is_test cause: null
[Thu Oct 29 2020 08:01:46] [LOG] partner.name cause: null
[Thu Oct 29 2020 08:01:46] [LOG] partner.iframe_blocked cause: null
[Thu Oct 29 2020 08:01:46] [LOG] partner.network_code cause: null
[Thu Oct 29 2020 08:01:46] [LOG] partner.code cause: null
[Thu Oct 29 2020 08:01:46] [LOG] partner.net_value cause: null
[Thu Oct 29 2020 08:01:46] [LOG] partner.virtual_value cause: null
[Thu Oct 29 2020 08:01:46] [LOG] client_code cause: null
What's wrong with that code?
Hey @maxgalbu
Actually, there's nothing wrong with your code.
The cause
of a ValidationError
is just an Error
instance, that could happen during the validation process. What's happening, in this case, is that you are recursively going to the leaf cause
, and at that level there's no value for the cause in a normal validation process (without excpetions). You can check the https://imbrn.github.io/v8n/api/#validationerror for more details about that.
But in your case, maybe you can use the cause.rule.name
to see what validation rule has failed.
Hi @imbrn,
seeing what validation rule has failed could help, but I'd like to know why it failed, e.g. params
is an integer instead of an object. Something that can help a person in spotting the issue.
The rule could tell me params
should be an object but then i need to go and see the type of params
myself in order to see what's wrong...
While I see what you're saying, @maxgalbu, v8n doesn't actually check that schema
properties are objects. The validation doesn't fail because params
is 1
, but rather because params.tokens
is undefined
.
What would happen if params.token
is integer instead of string? would that result in cause != null
?
Well one of the nested causes you get with that would be this:
...
[
{
"rule": {
"name": "string",
"args": [],
"modifiers": []
},
"value": 1,
"cause": null,
"target": "token"
}
]
...
To explain the above: The cause
here is null
, because this error is not caused by some other error. This error described exactly what went wrong with the target. The target key token was validated using a rule called string
. Its value was 1
. There is no further cause to this, but you are trying to display this error's cause in your function. This is already the root cause. In words: There was an error validating the value 1
for the key 'token' using the string
rule.
So you do get the information that it validated a string with a value of 1
and failed. But that is only one of the reasons it fails. A schema validation works like an interface, as I mentioned in #179, so all the keys defined in it must match whatever validation is given. You don't define any keys as optional
, so validating your large schema against a very small subset of it will cause lots of errors and nested errors. v8n never gives any error messages, it only gives ValidationError
objects, which you can interpret for error messages. If the error above would be the only one, it would be easy to tell that the reason for a failure was an integer for a string validation.
I'm not sure what you're asking for then. You have lots of non-null causes, but the inner most nested causes will always be null, because the root cause obviously doesn't have another cause.