diff --git a/dist/knockout.validation.js b/dist/knockout.validation.js index 1dc95ece..3d68fe25 100644 --- a/dist/knockout.validation.js +++ b/dist/knockout.validation.js @@ -525,7 +525,7 @@ kv.configuration = configuration; // } // )}; // - if (params && (params.message || params.onlyIf || params.severity)) { //if it has a message, condition, or severity object, then its an object literal to use + if (params && (params.message || params.onlyIf || (params.severity && !ko.isObservable(params.severity)))) { //if it has a message, condition, or severity object, then its an object literal to use return kv.addRule(observable, { rule: ruleName, message: params.message, @@ -1207,7 +1207,7 @@ ko.extenders['validatable'] = function (observable, options) { throttleEvaluation : options.throttle || config.throttle }; - observable.error = ko.observable(null); // holds the error message, we only need one since we stop processing validators when one is invalid and has and has a severity of 1 + observable.error = ko.observable(null); // holds the error message, we only need one since we stop processing validators when one is invalid and has a severity of 1 observable.severity = ko.observable(1); // observable.rules: diff --git a/src/api.js b/src/api.js index e590af2a..a0a07e75 100644 --- a/src/api.js +++ b/src/api.js @@ -327,8 +327,8 @@ // } // )}; // - if (params && (params.message || params.onlyIf || params.severity)) { //if it has a message, condition, or severity object, then its an object literal to use - return kv.addRule(observable, { + if (params && (params.message || params.onlyIf || (params.severity && !ko.isObservable(params.severity)))) { //if it has a message, condition, or severity object, then its an object literal to use + return ko.validation.addRule(observable, { rule: ruleName, message: params.message, params: utils.isEmptyVal(params.params) ? true : params.params, @@ -336,7 +336,7 @@ condition: params.onlyIf }); } else { - return kv.addRule(observable, { + return ko.validation.addRule(observable, { rule: ruleName, params: params, severity: 1 diff --git a/src/extenders.js b/src/extenders.js index f0bc6025..ec59aa80 100644 --- a/src/extenders.js +++ b/src/extenders.js @@ -42,7 +42,7 @@ ko.extenders['validatable'] = function (observable, options) { throttleEvaluation : options.throttle || config.throttle }; - observable.error = ko.observable(null); // holds the error message, we only need one since we stop processing validators when one is invalid and has and has a severity of 1 + observable.error = ko.observable(null); // holds the error message, we only need one since we stop processing validators when one is invalid and has a severity of 1 observable.severity = ko.observable(1); // observable.rules: @@ -133,9 +133,9 @@ function validateSync(observable, rule, ctx) { if (!rule.validator(observable(), (ctx.params === undefined ? true : ko.utils.unwrapObservable(ctx.params)))) { // default param is true, eg. required = true //not valid, so format the error message and stick it in the 'error' variable - observable.setError(kv.formatMessage( + observable.setError(ko.validation.formatMessage( ctx.message || rule.message, - unwrap(ctx.params), + ko.utils.unwrapObservable(ctx.params), observable), ctx.severity || rule.severity); return ctx.severity === 1 ? false : "warning"; } else { @@ -185,7 +185,7 @@ function validateAsync(observable, rule, ctx) { }); } -kv.validateObservable = function (observable) { +ko.validation.validateObservable = function (observable) { var i = 0, rule, // the rule validator to execute ctx, // the current Rule Context for the loop @@ -205,7 +205,7 @@ kv.validateObservable = function (observable) { } //get the core Rule to use for validation - rule = ctx.rule ? kv.rules[ctx.rule] : ctx; + rule = ctx.rule ? ko.validation.rules[ctx.rule] : ctx; if (rule['async'] || ctx['async']) { //run async validation diff --git a/test/api-tests.js b/test/api-tests.js index 24fbcb9b..56691ea4 100644 --- a/test/api-tests.js +++ b/test/api-tests.js @@ -766,7 +766,10 @@ QUnit.test('setRules applies rules to all properties', function(assert) { }, grandchild: { property3: { - number: true + number: true, + required: { + severity: 2 + } } }, ignoredDefinition: { required: true } @@ -799,22 +802,23 @@ QUnit.test('setRules applies rules to all properties', function(assert) { //check that all rules have been applied assert.deepEqual(target.property1.rules(), [ - { rule: 'required', params: true }, - { rule: 'min', params: 10 }, - { rule: 'max', params: 99 } + { rule: 'required', params: true, severity: 1 }, + { rule: 'min', params: 10, severity: 1 }, + { rule: 'max', params: 99, severity: 1 } ]); assert.deepEqual(target.child.property2.rules(), [ - { rule: 'pattern', message: 'Only AlphaNumeric please', params: '^[a-z0-9].$', condition: undefined } + { rule: 'pattern', message: 'Only AlphaNumeric please', params: '^[a-z0-9].$', condition: undefined, severity: 1 } ]); assert.deepEqual(target.child.grandchild.property3.rules(), [ - { rule: 'number', params: true } + { rule: 'number', params: true, severity: 1 }, + { rule: 'required', condition: undefined, message: undefined, params: true, severity: 2 } ]); for (var i = 0; i < target.nestedArray().length; i++) { assert.deepEqual(target.nestedArray()[i].property4.rules(), [ - { rule: 'email', params: true } + { rule: 'email', params: true, severity: 1 } ]); } @@ -827,6 +831,27 @@ QUnit.test('setRules applies rules to all properties', function(assert) { assert.ok(!target.nestedArray()[2].ignoredProperty.rules); }); +QUnit.test('setRules work correctly when params is validatedObservable', function(assert) { + var equalityComparison = ko.observable().extend({ min: 2 }); + + var definition = { + property1: { + equal: equalityComparison + } + }; + + var target = { + property1: ko.observable() + }; + + ko.validation.setRules(target, definition); + + //check that all rules have been applied + assert.deepEqual(target.property1.rules(), [ + { rule: 'equal', params: equalityComparison, severity: 1 } + ]); +}); + QUnit.test('Issue #461 - validatedObservable works with nested view models if grouping.deep is true', function(assert) { ko.validation.init({grouping: {deep: true}}, true); diff --git a/test/validation-tests.js b/test/validation-tests.js index d63d1eea..4242812a 100644 --- a/test/validation-tests.js +++ b/test/validation-tests.js @@ -433,3 +433,59 @@ QUnit.test('message parameter receives params and observable when async', functi }); //#endregion + +//#region Severity tests + +QUnit.module('Severity tests'); + +QUnit.test('isValid returns false for warning severity', function(assert) { + var testObj = ko.observable('something').extend({ + required: { + severity: 2 + } + }); + testObj(''); + assert.equal(testObj.isValid(), false); + assert.equal(testObj.severity(), 2, 'Severity should equal severity defined in required-validation'); +}); + +QUnit.test('default severity is 1', function(assert) { + var testObj = ko.observable('something').extend({ + required: true + }); + testObj(''); + assert.equal(testObj.isValid(), false); + assert.equal(testObj.severity(), 1, 'Severity should be 1 when not defined'); +}); + +QUnit.test('Lowest invalid rule severity is returned', function(assert) { + var testObj = ko.observable('something').extend({ + minLength: { + params: 200, + severity: 3 + }, + email: { + severity: 2 + }, + required: { + severity: 1, + params: true + } + }); + testObj('test'); + assert.equal(testObj.isValid(), false); + assert.equal(testObj.severity(), 2, 'Lowest broken rule severity should be 2'); +}); + +QUnit.test('Lowest invalid rule severity for default severity is returned', function(assert) { + var testObj = ko.observable('something').extend({ + required: { + severity: 2 + }, + equal: 'cant be this.' + }); + testObj(''); + assert.equal(testObj.isValid(), false); + assert.equal(testObj.severity(), 1, 'Default severity for broken rule should be 1'); +}); +//#endregion