Skip to content

Commit

Permalink
feat: option singleError, closes #5
Browse files Browse the repository at this point in the history
  • Loading branch information
epoberezkin committed May 9, 2017
1 parent 7f91997 commit d28036c
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 26 deletions.
7 changes: 6 additions & 1 deletion README.md
Expand Up @@ -201,11 +201,16 @@ Defaults:

```javascript
{
keepErrors: false
keepErrors: false,
singleError: false
}
```

- _keepErrors_: keep original errors. Default is to remove matched errors (they will still be available in `params.errors` property of generated error). If an error was matched and included in the error generated by `errorMessage` keyword it will have property `emUsed: true`.
- _singleError_: create one error for all keywords used in `errorMessage` keyword (error messages defined for properties and items are not merged because they have different dataPaths). Multiple error messages are concatenated. Option values:
- `false` (default): create multiple errors, one for each message
- `true`: create single error, messages are concatenated using `"; "`
- non-empty string: this string is used as a separator to concatenate messages


## License
Expand Down
8 changes: 3 additions & 5 deletions SPEC.md
Expand Up @@ -93,10 +93,8 @@ Example:

All errors that "errorMessage" keyword processes determined by keyword value, as described above.

Each appearance of "errorMessage" keyword can generate either multiple or a single error message, depending on the option "multiple" (true/false, default is false?). // DONE only multiple errors, TODO: single error
Each appearance of "errorMessage" keyword can generate either multiple or a single error message, depending on the option "multiple" (true/false, default is false?). // DONE

If a single message is generated, option "separator" (a string, default is ', ' - same as in errorsText method) defines how to join multiple messages into a single string. // TODO
If a single message is generated, option "separator" (a string, default is ', ' - same as in errorsText method) defines how to join multiple messages into a single string. // DONE

Option "prefix" can be used to prepend error message with "property" name or "dataPath"? // TODO?

Option "mode" determines whether the errors are replaced by "errorMessage" errors or they are kept ("replace"/"append", default is "replace"). // DONE replace, append - TODO
Option "mode" determines whether the errors are replaced by "errorMessage" errors or they are kept ("replace"/"append", default is "replace"). // DONE
69 changes: 51 additions & 18 deletions lib/dot/errorMessage.jst
Expand Up @@ -69,6 +69,12 @@
};
#}}

{{## def.em_errorMessage:
{{=$key}} in {{=$templates}}
? {{=$templates}}[{{=$key}}] ()
: validate.schema{{=$schemaPath}}[{{=$key}}]
#}}


{{? it.createErrors !== false }}
{{
Expand All @@ -86,6 +92,8 @@
, $matches = '_em_matches' + $lvl
, $isArray = '_em_isArray' + $lvl
, $errors = '_em_errors' + $lvl
, $message = '_em_message' + $lvl
, $paramsErrors = '_em_paramsErrors' + $lvl
, $templates = '_em_templates' + $lvl
, $errSchemaPathString = it.util.toQuotedString(it.errSchemaPath);
}}
Expand Down Expand Up @@ -162,25 +170,50 @@
{{=$i}}++;
}
}
for (var {{=$key}} in {{=$errors}}) {
if ({{=$errors}}[{{=$key}}].length) {
var err = {
keyword: '{{=$keyword}}'
, dataPath: {{=$dataPath}}
, schemaPath: {{=$errSchemaPathString}} + '/{{=$keyword}}'
, params: { errors: {{=$errors}}[{{=$key}}] }
, message: {{=$key}} in {{=$templates}}
? {{=$templates}}[{{=$key}}] ()
: validate.schema{{=$schemaPath}}[{{=$key}}]
{{? it.opts.verbose }}
, schema: validate.schema{{=$schemaPath}}
, parentSchema: validate.schema{{=it.schemaPath}}
, data: {{=$data}}
{{?}}
};
{{# def._addError:'custom' }}

{{? $config.options.singleError }}
var {{=$message}} = '';
var {{=$paramsErrors}} = [];
{{?}}

for (var {{=$key}} in {{=$errors}}) {
if ({{=$errors}}[{{=$key}}].length) {

{{? $config.options.singleError }}
if ({{=$message}}) {
{{=$message}} += {{? typeof $config.options.singleError == 'string' }}
{{= it.util.toQuotedString($config.options.singleError) }}
{{??}}
'; '
{{?}};
}
{{=$message}} += {{# def.em_errorMessage }};
{{=$paramsErrors}} = {{=$paramsErrors}}.concat({{=$errors}}[{{=$key}}]);
}
}
}
{{??}}
var {{=$message}} = {{# def.em_errorMessage }};
var {{=$paramsErrors}} = {{=$errors}}[{{=$key}}];
{{?}}

var err = {
keyword: '{{=$keyword}}'
, dataPath: {{=$dataPath}}
, schemaPath: {{=$errSchemaPathString}} + '/{{=$keyword}}'
, params: { errors: {{=$paramsErrors}} }
, message: {{=$message}}
{{? it.opts.verbose }}
, schema: validate.schema{{=$schemaPath}}
, parentSchema: validate.schema{{=it.schemaPath}}
, data: {{=$data}}
{{?}}
};
{{# def._addError:'custom' }}

{{? !$config.options.singleError }}
}
}
{{?}}
{{?}}

{{? $hasProperties || $hasItems }}
Expand Down
59 changes: 57 additions & 2 deletions spec/options.spec.js
Expand Up @@ -10,10 +10,13 @@ describe('options', function() {

beforeEach(function() {
ajv = new Ajv({allErrors: true, jsonPointers: true});
ajvErrors(ajv, {keepErrors: true});
});

describe('keepErrors: true', function() {
describe('keepErrors = true', function() {
beforeEach(function() {
ajvErrors(ajv, {keepErrors: true});
});

describe('errorMessage is a string', function() {
it('should keep matched errors and mark them with {emUsed: true} property', function() {
var schema = {
Expand Down Expand Up @@ -138,6 +141,58 @@ describe('options', function() {
});


describe('singleError', function() {
describe('= true', function() {
it('should generate a single error for all keywords', function() {
ajvErrors(ajv, {singleError: true});
testSingleErrors('; ');
});
});

describe('= separator', function() {
it('should generate a single error for all keywords using separator', function() {
ajvErrors(ajv, {singleError: '\n'});
testSingleErrors('\n');
});
});

function testSingleErrors(separator) {
var schema = {
type: 'number',
minimum: 2,
maximum: 10,
multipleOf: 2,
errorMessage: {
type: 'should be number',
minimum: 'should be >= 2',
maximum: 'should be <= 10',
multipleOf: 'should be multipleOf 2'
}
};

var validate = ajv.compile(schema);
assert.strictEqual(validate(4), true);
assert.strictEqual(validate(11), false);

var expectedKeywords = ['maximum', 'multipleOf'];
var expectedMessage = expectedKeywords
.map(function (keyword) {
return schema.errorMessage[keyword];
})
.join(separator);

assertErrors(validate, [
{
keyword: 'errorMessage',
message: expectedMessage,
dataPath: '',
errors: expectedKeywords
}
]);
}
});


function assertErrors(validate, expectedErrors) {
assert.strictEqual(validate.errors.length, expectedErrors.length);

Expand Down

0 comments on commit d28036c

Please sign in to comment.