From ccf4f5cc03d4d326d32ca6809f3ec036422721a9 Mon Sep 17 00:00:00 2001 From: Jakob Voss Date: Wed, 24 Jan 2024 09:43:47 +0100 Subject: [PATCH] Extend error objects --- lib/validate.js | 49 ++++++++++++++++++--------------- test/suite/README.md | 2 +- test/suite/codes.json | 6 ++-- test/suite/deprecated.json | 4 +-- test/suite/flags.json | 4 +-- test/suite/ignore_unknown.json | 2 +- test/suite/indicators.json | 6 +++- test/suite/positions.json | 2 +- test/suite/subfields.json | 8 +++--- test/suite/types.json | 8 +++--- test/suite/validate-values.json | 8 +++--- test/suite/validator.json | 10 +++---- 12 files changed, 59 insertions(+), 50 deletions(-) diff --git a/lib/validate.js b/lib/validate.js index bbbdeec..26be523 100644 --- a/lib/validate.js +++ b/lib/validate.js @@ -101,14 +101,15 @@ export class Validator { const { fields, types } = record for (let field of fields) { - var id = schedule.identifier(field) + const id = schedule.identifier(field) + const { tag, occurrence, subfields } = field // count if (id in schedule) { fieldCount.visit(id) - if (subfieldCount && field.subfields && schedule[id].subfields) { - for (let i=0; i { + const path = { id, tag: field.tag } + if (field.occurrence) path.occurrence = field.occurrence if (Array.isArray(field.subfields)) { // variable field - return validateSubfields(field.subfields, definition.subfields, options, id) + return validateSubfields(field, definition.subfields, options, id) } else if (options.invalidFieldValue) { // fixed field - return validateValue(field.value, definition, options, types, { id }) + return validateValue(field.value, definition, options, types, path) } else { return [] } @@ -209,11 +211,11 @@ const validateIndicators = (field, definition, options, id) => { if (!options.invalidIndicator) return [] const errors = [] for (let indicator of ["indicator1", "indicator2"]) { - const path = { id, indicator } + const path = { tag: field.tag, id, indicator } if (indicator in field !== indicator in definition) { errors.push({ - message: `Existence mismatch of ${loc(path)}.`, - error: "invalidIndicator", + message: `Existence mismatch of ${loc(path)}`, + error: "invalidIndicator", ...path, }) } else if (indicator in field) { const { codes, pattern } = definition[indicator] ?? { codes: { " ": {} } } @@ -225,7 +227,7 @@ const validateIndicators = (field, definition, options, id) => { } // See https://format.gbv.de/schema/avram/specification#field-validation -export const validateSubfields = (subfields, schedule, options, id) => { +const validateSubfields = ({ tag, subfields }, schedule, options, id) => { if (!options.invalidSubfield) return [] const errors = [] @@ -234,7 +236,7 @@ export const validateSubfields = (subfields, schedule, options, id) => { for (let i=0; i { } if (options.missingSubfield) { - errors.push(...visitor.missing().map(subfield => ({ - error: "missingSubfield", - message: `missing ${loc({id, subfield})}`, - id, subfield, - }))) + errors.push(...visitor.missing().map(subfield => { + const path = { id, tag, subfield } + return { + error: "missingSubfield", + message: `missing ${loc(path)}`, + ...path, + } + })) } return errors @@ -295,7 +300,7 @@ export const validateValue = (value, definition, options, recordTypes, path) => } // See https://format.gbv.de/schema/avram/specification#value-validation -export const validatePattern = (value, pattern, path) => { +const validatePattern = (value, pattern, path) => { if (pattern) { const regexp = new RegExp(pattern, "u") if (!regexp.test(value)) { @@ -310,7 +315,7 @@ export const validatePattern = (value, pattern, path) => { } // See https://format.gbv.de/schema/avram/specification#validation-with-codelist -export const validateCode = (value, codes, options = {}, path = {}, len=null) => { +const validateCode = (value, codes, options = {}, path = {}, len=null) => { const { undefinedCode, undefinedCodelist, codelists } = options const isIndicator = "indicator" in path @@ -355,7 +360,7 @@ export const validateCode = (value, codes, options = {}, path = {}, len=null) => } : { error: "undefinedCode", message: `value '${value}' is not defined in codelist in ${loc(path)}`, - value, ...path, + ...path, value, } return [ error ] diff --git a/test/suite/README.md b/test/suite/README.md index 0597321..6db05a9 100644 --- a/test/suite/README.md +++ b/test/suite/README.md @@ -27,7 +27,7 @@ Each test is an object with keys: * `code` subfield code an error was found in * `tag` tag of the field an error was found in * `occurrence` occurrence of the field an error was found in - * `identifier` field identifier from the field schedule for the field an error was found in + * `id` field identifier from the field schedule for the field an error was found in * `pattern` regular expression that was violated * `value` malformed or disallowed value that caused an error diff --git a/test/suite/codes.json b/test/suite/codes.json index 20a12a4..e4d63bf 100644 --- a/test/suite/codes.json +++ b/test/suite/codes.json @@ -35,13 +35,13 @@ { "error": "undefinedCode", "message": "value 'deu' is not defined in codelist in field lang", - "id": "lang", + "id": "lang", "tag": "lang", "value": "deu" }, { "error": "undefinedCode", "message": "value 'y' is not defined in codelist in field bool", - "id": "bool", + "id": "bool", "tag": "bool", "value": "y" }, { @@ -69,7 +69,7 @@ { "error": "undefinedCode", "message": "value 'y' is not defined in codelist in field bool", - "id": "bool", + "id": "bool", "tag": "bool", "value": "y" } ] diff --git a/test/suite/deprecated.json b/test/suite/deprecated.json index b3e56f2..ec4623c 100644 --- a/test/suite/deprecated.json +++ b/test/suite/deprecated.json @@ -26,7 +26,7 @@ { "record": [ { "tag": "old", "value": "1" } ], "errors": [ { - "error": "deprecatedField", "id": "old", + "error": "deprecatedField", "tag": "old", "id": "old", "message": "field old is deprecated" } ] }, @@ -36,7 +36,7 @@ "errors": [ { "error": "deprecatedSubfield", "message": "field sub subfield o is deprecated", - "id": "sub", + "id": "sub", "tag": "sub", "subfield": "o" } ] } diff --git a/test/suite/flags.json b/test/suite/flags.json index b305219..ec07140 100644 --- a/test/suite/flags.json +++ b/test/suite/flags.json @@ -30,14 +30,14 @@ { "error": "invalidFlag", "message": "value 'x' is not defined in flags in field a position 0-1", - "id": "a", + "id": "a", "tag": "a", "position": "0-1", "value": "x" }, { "error": "invalidFlag", "message": "value 'y' is not defined in flags in field a position 2-7", - "id": "a", + "id": "a", "tag": "a", "position": "2-7", "value": "y" } diff --git a/test/suite/ignore_unknown.json b/test/suite/ignore_unknown.json index 688402f..8797753 100644 --- a/test/suite/ignore_unknown.json +++ b/test/suite/ignore_unknown.json @@ -18,7 +18,7 @@ { "error": "undefinedSubfield", "message": "unknown field known subfield a", - "id": "known", + "id": "known", "tag": "known", "subfield": "a" }, { diff --git a/test/suite/indicators.json b/test/suite/indicators.json index 19c21cd..64a414e 100644 --- a/test/suite/indicators.json +++ b/test/suite/indicators.json @@ -42,6 +42,7 @@ { "error": "patternMismatch", "message": "value '0' does not match regex pattern '[^0-9]' in field 210 indicator2", + "tag": "210", "id": "210", "indicator": "indicator2", "pattern": "[^0-9]", @@ -57,12 +58,15 @@ "errors": [ { "error": "invalidIndicator", - "message": "Existence mismatch of field 010 indicator1." + "message": "Existence mismatch of field 010 indicator1", + "tag": "010", "id": "010", + "indicator": "indicator1" }, { "error": "invalidIndicator", "message": "value 'x' in field 010 indicator2 is not defined in codelist", "id": "010", + "tag": "010", "indicator": "indicator2", "value": "x" } diff --git a/test/suite/positions.json b/test/suite/positions.json index 196e343..749365f 100644 --- a/test/suite/positions.json +++ b/test/suite/positions.json @@ -25,7 +25,7 @@ "errors": [{ "error": "invalidPosition", "message": "field x position 01-2 does not exist", - "id": "x", + "id": "x", "tag": "x", "position": "01-2", "value": "a" }] diff --git a/test/suite/subfields.json b/test/suite/subfields.json index 4d6b2e1..d78fb8a 100644 --- a/test/suite/subfields.json +++ b/test/suite/subfields.json @@ -24,7 +24,7 @@ { "error": "missingSubfield", "message": "missing field _ subfield 0", - "id": "_", + "id": "_", "tag": "_", "subfield": "0" } ] @@ -37,7 +37,7 @@ { "error": "nonrepeatableSubfield", "message": "field _ subfield 0 must not be repeated", - "id": "_", + "id": "_", "tag": "_", "subfield": "0" } ] @@ -50,13 +50,13 @@ { "error": "undefinedSubfield", "message": "unknown field _ subfield x", - "id": "_", + "id": "_", "tag": "_", "subfield": "x" }, { "error": "missingSubfield", "message": "missing field _ subfield 0", - "id": "_", + "id": "_", "tag": "_", "subfield": "0" } ] diff --git a/test/suite/types.json b/test/suite/types.json index 5224e67..2087b83 100644 --- a/test/suite/types.json +++ b/test/suite/types.json @@ -30,14 +30,14 @@ { "error": "patternMismatch", "message": "value '9' does not match regex pattern '[a-z]' in field A", - "id": "A", + "id": "A", "tag": "A", "pattern": "[a-z]", "value": "9" }, { "error": "undefinedCode", "message": "value '9' is not defined in codelist in field A", - "id": "A", + "id": "A", "tag": "A", "value": "9" } ] @@ -51,7 +51,7 @@ { "error": "patternMismatch", "message": "value 'x' does not match regex pattern '0' in field A position 0", - "id": "A", + "id": "A", "tag": "A", "pattern": "0", "value": "x", "position": "0" @@ -59,7 +59,7 @@ { "error": "patternMismatch", "message": "value 'x' does not match regex pattern '[0-9]' in field A", - "id": "A", + "id": "A", "tag": "A", "pattern": "[0-9]", "value": "x" } diff --git a/test/suite/validate-values.json b/test/suite/validate-values.json index ce88d85..74aa4e8 100644 --- a/test/suite/validate-values.json +++ b/test/suite/validate-values.json @@ -20,7 +20,7 @@ { "error": "patternMismatch", "message": "value 'x' does not match regex pattern '[0-9]' in field _", - "id": "_", + "id": "_", "tag": "_", "pattern": "[0-9]", "value": "x" } @@ -37,7 +37,7 @@ { "error": "undefinedCode", "message": "value 'x' is not defined in codelist in field _", - "id": "_", + "id": "_", "tag": "_", "value": "x" } ] @@ -75,7 +75,7 @@ { "error": "patternMismatch", "message": "value '9' does not match regex pattern '[a-z]' in field _ position 00", - "id": "_", + "id": "_", "tag": "_", "position": "00", "pattern": "[a-z]", "value": "9" @@ -83,7 +83,7 @@ { "error": "invalidPosition", "message": "field _ position 01-02 does not exist", - "id": "_", + "id": "_", "tag": "_", "position": "01-02", "value": "9a" } diff --git a/test/suite/validator.json b/test/suite/validator.json index 4ce0aa4..0901363 100644 --- a/test/suite/validator.json +++ b/test/suite/validator.json @@ -23,18 +23,18 @@ { "error": "missingSubfield", "message": "missing field A subfield x", - "id": "A", + "id": "A", "tag": "A", "subfield": "x" }, { "message": "value '1' does not match regex pattern '^[a-z]$' in field A subfield x", "error": "patternMismatch", - "id": "A", + "id": "A", "tag": "A", "subfield": "x", "pattern": "^[a-z]$", "value": "1" }, - { "identifier": "A", "message": "Field 'A' must not be repeated.", "error": "nonrepeatableField" }, + { "tag": "A", "id": "A", "message": "Field 'A' must not be repeated.", "error": "nonrepeatableField" }, { "tag": "Y", "occurrence": "1", "message": "Unknown field 'Y/1'.", "error": "undefinedField" } ] },{ @@ -60,12 +60,12 @@ { "error": "undefinedCode", "message": "value 'z' is not defined in codelist in field B", - "id": "B", + "id": "B", "tag": "B", "value": "z" },{ "error": "undefinedCode", "message": "value ' ' is not defined in codelist in field C subfield z", - "id": "C", + "id": "C", "tag": "C", "subfield": "z", "value": " " },