diff --git a/cases/io-ts.ts b/cases/io-ts.ts index 630b666e5..41e0c5949 100644 --- a/cases/io-ts.ts +++ b/cases/io-ts.ts @@ -1,4 +1,6 @@ import * as t from 'io-ts'; +import { pipe } from 'fp-ts/function'; +import { fold } from 'fp-ts/Either'; import { Case } from './abstract'; const dataType = t.type({ @@ -19,12 +21,14 @@ export class IoTsCase extends Case implements Case { name = 'io-ts'; validate() { - const { data } = this; - - if (dataType.is(data)) { - return data; - } - - throw new Error('Invalid'); + return pipe( + dataType.decode(this.data), + fold( + errors => { + throw errors; + }, + a => a + ) + ); } } diff --git a/test/__snapshots__/abstract.test.ts.snap b/test/__snapshots__/abstract.test.ts.snap index c0595a561..1fec98536 100644 --- a/test/__snapshots__/abstract.test.ts.snap +++ b/test/__snapshots__/abstract.test.ts.snap @@ -249,11 +249,466 @@ exports[`Case Class: decoders should fail validation when type is wrong 1`] = ` }] `; -exports[`Case Class: io-ts should fail validation when deeply nested type is wrong 1`] = `[Error: Invalid]`; +exports[`Case Class: io-ts should fail validation when deeply nested type is wrong 1`] = ` +Array [ + Object { + "context": Array [ + Object { + "actual": Object { + "boolean": true, + "deeplyNested": Object { + "bool": "foo", + "foo": "bar", + "num": 1, + }, + "longString": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Vivendum intellegat et qui, ei denique consequuntur vix. Semper aeterno percipit ut his, sea ex utinam referrentur repudiandae. No epicuri hendrerit consetetur sit, sit dicta adipiscing ex, in facete detracto deterruisset duo. Quot populo ad qui. Sit fugit nostrum et. Ad per diam dicant interesset, lorem iusto sensibus ut sed. No dicam aperiam vis. Pri posse graeco definitiones cu, id eam populo quaestio adipiscing, usu quod malorum te. Ex nam agam veri, dicunt efficiantur ad qui, ad legere adversarium sit. Commune platonem mel id, brute adipiscing duo an. Vivendum intellegat et qui, ei denique consequuntur vix. Offendit eleifend moderatius ex vix, quem odio mazim et qui, purto expetendis cotidieque quo cu, veri persius vituperata ei nec. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.", + "maxNumber": 1.7976931348623157e+308, + "negNumber": -1, + "number": 1, + "string": "string", + }, + "key": "", + "type": InterfaceType { + "_tag": "InterfaceType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "{ number: Int, negNumber: number, maxNumber: number, string: string, longString: string, boolean: boolean, deeplyNested: { foo: string, num: number, bool: boolean } }", + "props": Object { + "boolean": BooleanType { + "_tag": "BooleanType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "boolean", + "validate": [Function], + }, + "deeplyNested": InterfaceType { + "_tag": "InterfaceType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "{ foo: string, num: number, bool: boolean }", + "props": Object { + "bool": BooleanType { + "_tag": "BooleanType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "boolean", + "validate": [Function], + }, + "foo": StringType { + "_tag": "StringType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "string", + "validate": [Function], + }, + "num": NumberType { + "_tag": "NumberType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "number", + "validate": [Function], + }, + }, + "validate": [Function], + }, + "longString": StringType { + "_tag": "StringType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "string", + "validate": [Function], + }, + "maxNumber": NumberType { + "_tag": "NumberType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "number", + "validate": [Function], + }, + "negNumber": NumberType { + "_tag": "NumberType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "number", + "validate": [Function], + }, + "number": RefinementType { + "_tag": "RefinementType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "Int", + "predicate": [Function], + "type": NumberType { + "_tag": "NumberType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "number", + "validate": [Function], + }, + "validate": [Function], + }, + "string": StringType { + "_tag": "StringType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "string", + "validate": [Function], + }, + }, + "validate": [Function], + }, + }, + Object { + "actual": Object { + "bool": "foo", + "foo": "bar", + "num": 1, + }, + "key": "deeplyNested", + "type": InterfaceType { + "_tag": "InterfaceType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "{ foo: string, num: number, bool: boolean }", + "props": Object { + "bool": BooleanType { + "_tag": "BooleanType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "boolean", + "validate": [Function], + }, + "foo": StringType { + "_tag": "StringType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "string", + "validate": [Function], + }, + "num": NumberType { + "_tag": "NumberType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "number", + "validate": [Function], + }, + }, + "validate": [Function], + }, + }, + Object { + "actual": "foo", + "key": "bool", + "type": BooleanType { + "_tag": "BooleanType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "boolean", + "validate": [Function], + }, + }, + ], + "message": undefined, + "value": "foo", + }, +] +`; -exports[`Case Class: io-ts should fail validation when prop is missing 1`] = `[Error: Invalid]`; +exports[`Case Class: io-ts should fail validation when prop is missing 1`] = ` +Array [ + Object { + "context": Array [ + Object { + "actual": Object { + "deeplyNested": Object { + "bool": false, + "foo": "bar", + "num": 1, + }, + "longString": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Vivendum intellegat et qui, ei denique consequuntur vix. Semper aeterno percipit ut his, sea ex utinam referrentur repudiandae. No epicuri hendrerit consetetur sit, sit dicta adipiscing ex, in facete detracto deterruisset duo. Quot populo ad qui. Sit fugit nostrum et. Ad per diam dicant interesset, lorem iusto sensibus ut sed. No dicam aperiam vis. Pri posse graeco definitiones cu, id eam populo quaestio adipiscing, usu quod malorum te. Ex nam agam veri, dicunt efficiantur ad qui, ad legere adversarium sit. Commune platonem mel id, brute adipiscing duo an. Vivendum intellegat et qui, ei denique consequuntur vix. Offendit eleifend moderatius ex vix, quem odio mazim et qui, purto expetendis cotidieque quo cu, veri persius vituperata ei nec. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.", + "maxNumber": 1.7976931348623157e+308, + "negNumber": -1, + "number": 1, + "string": "string", + }, + "key": "", + "type": InterfaceType { + "_tag": "InterfaceType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "{ number: Int, negNumber: number, maxNumber: number, string: string, longString: string, boolean: boolean, deeplyNested: { foo: string, num: number, bool: boolean } }", + "props": Object { + "boolean": BooleanType { + "_tag": "BooleanType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "boolean", + "validate": [Function], + }, + "deeplyNested": InterfaceType { + "_tag": "InterfaceType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "{ foo: string, num: number, bool: boolean }", + "props": Object { + "bool": BooleanType { + "_tag": "BooleanType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "boolean", + "validate": [Function], + }, + "foo": StringType { + "_tag": "StringType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "string", + "validate": [Function], + }, + "num": NumberType { + "_tag": "NumberType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "number", + "validate": [Function], + }, + }, + "validate": [Function], + }, + "longString": StringType { + "_tag": "StringType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "string", + "validate": [Function], + }, + "maxNumber": NumberType { + "_tag": "NumberType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "number", + "validate": [Function], + }, + "negNumber": NumberType { + "_tag": "NumberType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "number", + "validate": [Function], + }, + "number": RefinementType { + "_tag": "RefinementType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "Int", + "predicate": [Function], + "type": NumberType { + "_tag": "NumberType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "number", + "validate": [Function], + }, + "validate": [Function], + }, + "string": StringType { + "_tag": "StringType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "string", + "validate": [Function], + }, + }, + "validate": [Function], + }, + }, + Object { + "actual": undefined, + "key": "boolean", + "type": BooleanType { + "_tag": "BooleanType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "boolean", + "validate": [Function], + }, + }, + ], + "message": undefined, + "value": undefined, + }, +] +`; -exports[`Case Class: io-ts should fail validation when type is wrong 1`] = `[Error: Invalid]`; +exports[`Case Class: io-ts should fail validation when type is wrong 1`] = ` +Array [ + Object { + "context": Array [ + Object { + "actual": Object { + "boolean": "foo", + "deeplyNested": Object { + "bool": false, + "foo": "bar", + "num": 1, + }, + "longString": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Vivendum intellegat et qui, ei denique consequuntur vix. Semper aeterno percipit ut his, sea ex utinam referrentur repudiandae. No epicuri hendrerit consetetur sit, sit dicta adipiscing ex, in facete detracto deterruisset duo. Quot populo ad qui. Sit fugit nostrum et. Ad per diam dicant interesset, lorem iusto sensibus ut sed. No dicam aperiam vis. Pri posse graeco definitiones cu, id eam populo quaestio adipiscing, usu quod malorum te. Ex nam agam veri, dicunt efficiantur ad qui, ad legere adversarium sit. Commune platonem mel id, brute adipiscing duo an. Vivendum intellegat et qui, ei denique consequuntur vix. Offendit eleifend moderatius ex vix, quem odio mazim et qui, purto expetendis cotidieque quo cu, veri persius vituperata ei nec. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.", + "maxNumber": 1.7976931348623157e+308, + "negNumber": -1, + "number": 1, + "string": "string", + }, + "key": "", + "type": InterfaceType { + "_tag": "InterfaceType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "{ number: Int, negNumber: number, maxNumber: number, string: string, longString: string, boolean: boolean, deeplyNested: { foo: string, num: number, bool: boolean } }", + "props": Object { + "boolean": BooleanType { + "_tag": "BooleanType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "boolean", + "validate": [Function], + }, + "deeplyNested": InterfaceType { + "_tag": "InterfaceType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "{ foo: string, num: number, bool: boolean }", + "props": Object { + "bool": BooleanType { + "_tag": "BooleanType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "boolean", + "validate": [Function], + }, + "foo": StringType { + "_tag": "StringType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "string", + "validate": [Function], + }, + "num": NumberType { + "_tag": "NumberType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "number", + "validate": [Function], + }, + }, + "validate": [Function], + }, + "longString": StringType { + "_tag": "StringType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "string", + "validate": [Function], + }, + "maxNumber": NumberType { + "_tag": "NumberType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "number", + "validate": [Function], + }, + "negNumber": NumberType { + "_tag": "NumberType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "number", + "validate": [Function], + }, + "number": RefinementType { + "_tag": "RefinementType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "Int", + "predicate": [Function], + "type": NumberType { + "_tag": "NumberType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "number", + "validate": [Function], + }, + "validate": [Function], + }, + "string": StringType { + "_tag": "StringType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "string", + "validate": [Function], + }, + }, + "validate": [Function], + }, + }, + Object { + "actual": "foo", + "key": "boolean", + "type": BooleanType { + "_tag": "BooleanType", + "decode": [Function], + "encode": [Function], + "is": [Function], + "name": "boolean", + "validate": [Function], + }, + }, + ], + "message": undefined, + "value": "foo", + }, +] +`; exports[`Case Class: jointz should fail validation when deeply nested type is wrong 1`] = ` Array [