The problem is that when I send "RUNNING" I'm still getting a 200 instead of a 400.
it seems that you are using the string(!) "RUNNING" as value in your request payload as such:
{ appState: "RUNNING" }
In this case, IsEnum
and NotEquals
both regard the payload as valid.
Why is that?
First of all numeric enums are reverse mapped by typescript so your enum is internally (as javascript object) represented as follows:
{
'0': 'SUCCESS',
'1': 'ERROR',
'2': 'RUNNING',
'SUCCESS': 0,
'ERROR': 1,
'RUNNING': 2
}
Now class-validator's isEnum()
is coded as follows:
isEnum(value: unknown, entity: any): boolean {
const enumValues = Object.keys(entity)
.map(k => entity[k]);
return enumValues.indexOf(value) >= 0;
}
and since the enum is reverse-mapped isEnum('RUNNNING', AppState)
will return true.
At the same time NotEquals
, which is coded as such...
notEquals(value: unknown, comparison: unknown): boolean {
return value !== comparison;
}
will compare the string 'RUNNING' against AppState.RUNNING
(which equates to 2
) and also conclude that this is valid since 'RUNNING' != 2
.
So there you have it why the payload { appState: "RUNNING" }
will result in a 200 instead of a 400 status code.
How can I prevent this behaviour?
The enum value AppState.RUNNING
equates to 2
so when you make a request, you should use the numeric value of 2
in your payload:
{ appState: 2 }
In the above case, the class-validator's NotEquals
validator will then correctly deny the request with the response containing:
"constraints": {
"notEquals": "appState should not be equal to 2"
}