Permalink
Browse files

Refurbished validationmessages

Number fields got "Required" insted of "Value is not a number" since the
input[type="number"] stopped the value being written to the model and we
had higher precedence on tv4 error messages. This is no longer the case
we show some ordinary angular validation messages as well.

This fixes #322

Also fixed some small bugs regarding the error messages. Often
`viewValue` is what you want in the error message.

Plus a start with protractor.
  • Loading branch information...
1 parent dbb7d17 commit 57002611a1684ba179438f447a2b4337a92611a1 @davidlgj davidlgj committed Apr 17, 2015
View
@@ -1,4 +1,5 @@
{
"preset": "google",
- "maximumLineLength": 100
+ "maximumLineLength": 100,
+ "disallowMultipleLineBreaks": false
}
View
@@ -260,6 +260,7 @@ The context variables available to you are:
| error | The error code |
| title | Title of the field |
| value | The model value |
+| viewValue | The view value (probably the one you want) |
| form | form definition object for this field |
| schema | schema for this field |
@@ -273,11 +273,12 @@
}).error(function() {
$scope.loadedData = 'dummy';
$scope.error = 'Failed to load gist.';
+ $scope.selectedTest = $scope.tests[0];
});
+ } else {
+ $scope.selectedTest = $scope.tests[0];
}
- $scope.selectedTest = $scope.tests[0];
-
$scope.$watch('selectedTest',function(val){
if (val) {
$http.get(val.data).then(function(res) {setNewData(res.data);});
@@ -0,0 +1,38 @@
+var gulp = require('gulp');
+
+// The protractor task
+var protractor = require('gulp-protractor');
+
+// Start a standalone server
+var webdriver_standalone = protractor.webdriver_standalone;
+
+// Download and update the selenium driver
+var webdriver_update = protractor.webdriver_update;
+
+// Downloads the selenium webdriver
+gulp.task('webdriver-update', webdriver_update);
+
+// Start the standalone selenium server
+// NOTE: This is not needed if you reference the
+// seleniumServerJar in your protractor.conf.js
+gulp.task('webdriver-standalone', webdriver_standalone);
+
+
+// Setting up the test task
+gulp.task('protractor', ['webdriver-update'], function(cb) {
+ gulp.src(['test/protractor/specs/**/*.js']).pipe(protractor.protractor({
+ configFile: 'test/protractor/conf.js',
+ })).on('error', function(e) {
+ console.log(e);
+ }).on('end', cb);
+});
+
+['validation-messages', 'custom-validation'].forEach(function(name) {
+ gulp.task('protractor:' + name, ['webdriver-update'], function(cb) {
+ gulp.src(['test/protractor/specs/' + name + '.js']).pipe(protractor.protractor({
+ configFile: 'test/protractor/conf.js',
+ })).on('error', function(e) {
+ console.log(e);
+ }).on('end', cb);
+ });
+});
View
@@ -38,6 +38,7 @@
"gulp-concat": "^2.2.0",
"gulp-jscs": "^1.1.0",
"gulp-minify-html": "^0.1.1",
+ "gulp-protractor": "^1.0.0",
"gulp-rename": "^1.2.0",
"gulp-uglify": "^0.2.1",
"karma": "^0.12.0",
@@ -49,6 +50,7 @@
"karma-phantomjs-launcher": "^0.1.4",
"mocha": "^1.18.0",
"mocha-lcov-reporter": "0.0.1",
+ "protractor": "^2.0.0",
"sinon": "^1.9.0",
"sinon-chai": "^2.5.0",
"streamqueue": "0.0.5"
@@ -27,24 +27,13 @@ angular.module('schemaForm').directive('sfMessage',
// We only show one error.
// TODO: Make that optional
- // tv4- errors take precedence
var error = errors[0];
- if (errors.length > 1) {
-
- error = errors.reduce(function(prev, value) {
- if (prev && prev.indexOf('tv4-') === 0) {
- return prev;
- }
- return value;
- });
- console.log('reduced',errors, error)
-
- }
if (error) {
element.html(sfErrorMessage.interpolate(
error,
scope.ngModel.$modelValue,
+ scope.ngModel.$viewValue,
scope.form,
scope.options && scope.options.validationMessage
));
@@ -159,6 +159,7 @@ angular.module('schemaForm').provider('schemaFormDecorators',
return sfErrorMessage.interpolate(
(schemaError && schemaError.code + '') || 'default',
(scope.ngModel && scope.ngModel.$modelValue) || '',
+ (scope.ngModel && scope.ngModel.$viewValue) || '',
scope.form,
scope.options && scope.options.validationMessage
);
@@ -14,25 +14,25 @@ angular.module('schemaForm').provider('sfErrorMessage', function() {
12: 'Data is valid against more than one schema from "oneOf"',
13: 'Data matches schema from "not"',
// Numeric errors
- 100: 'Value {{value}} is not a multiple of {{schema.multipleOf}}',
- 101: 'Value {{value}} is less than minimum {{schema.minimum}}',
- 102: 'Value {{value}} is equal to exclusive minimum {{schema.minimum}}',
- 103: 'Value {{value}} is greater than maximum {{schema.maximum}}',
- 104: 'Value {{value}} is equal to exclusive maximum {{schema.maximum}}',
- 105: 'Value {{value}} is not a valid number',
+ 100: 'Value is not a multiple of {{schema.divisibleBy}}',
+ 101: '{{viewValue}} is less than the allowed minimum of {{schema.minimum}}',
+ 102: '{{viewValue}} is equal to the exclusive minimum {{schema.minimum}}',
+ 103: '{{viewValue}} is greater than the allowed maximum of {{schema.maximum}}',
+ 104: '{{viewValue}} is equal to the exclusive maximum {{schema.maximum}}',
+ 105: 'Value is not a valid number',
// String errors
- 200: 'String is too short ({{value.length}} chars), minimum {{schema.minimum}}',
- 201: 'String is too long ({{value.length}} chars), maximum {{schema.maximum}}',
+ 200: 'String is too short ({{viewValue.length}} chars), minimum {{schema.minLength}}',
+ 201: 'String is too long ({{viewValue.length}} chars), maximum {{schema.maxLength}}',
202: 'String does not match pattern: {{schema.pattern}}',
// Object errors
- 300: 'Too few properties defined, minimum {{schema.minimum}}',
- 301: 'Too many properties defined, maximum {{schema.maximum}}',
+ 300: 'Too few properties defined, minimum {{schema.minProperties}}',
+ 301: 'Too many properties defined, maximum {{schema.maxProperties}}',
302: 'Required',
303: 'Additional properties not allowed',
304: 'Dependency failed - key must exist',
// Array errors
- 400: 'Array is too short ({{value.length}}), minimum {{schema.minimum}}',
- 401: 'Array is too long ({{value.length}}), maximum {{schema.maximum}}',
+ 400: 'Array is too short ({{value.length}}), minimum {{schema.maxItems}}',
+ 401: 'Array is too long ({{value.length}}), maximum {{schema.minItems}}',
402: 'Array items are not unique',
403: 'Additional items not allowed',
// Format errors
@@ -44,6 +44,15 @@ angular.module('schemaForm').provider('sfErrorMessage', function() {
1000: 'Unknown property (not in schema)'
};
+ // In some cases we get hit with an angular validation error
+ defaultMessages.number = defaultMessages[105];
+ defaultMessages.required = defaultMessages[302];
+ defaultMessages.min = defaultMessages[101];
+ defaultMessages.max = defaultMessages[103];
+ defaultMessages.maxlength = defaultMessages[201];
+ defaultMessages.minlength = defaultMessages[200];
+ defaultMessages.pattern = defaultMessages[202];
+
this.setDefaultMessages = function(messages) {
defaultMessages = messages;
};
@@ -68,12 +77,14 @@ angular.module('schemaForm').provider('sfErrorMessage', function() {
* @param {string} error the error code, i.e. tv4-xxx for tv4 errors, otherwise it's whats on
* ngModel.$error for custom errors.
* @param {Any} value the actual model value.
+ * @param {Any} viewValue the viewValue
* @param {Object} form a form definition object for this field
* @param {Object} global the global validation messages object (even though its called global
* its actually just shared in one instance of sf-schema)
* @return {string} The error message.
*/
- service.interpolate = function(error, value, form, global) {
+ service.interpolate = function(error, value, viewValue, form, global) {
+ console.log(error, value, viewValue)
global = global || {};
var validationMessage = form.validationMessage || {};
@@ -99,6 +110,7 @@ angular.module('schemaForm').provider('sfErrorMessage', function() {
var context = {
error: error,
value: value,
+ viewValue: viewValue,
form: form,
schema: form.schema,
title: form.title || (form.schema && form.schema.title)
@@ -1,4 +1,3 @@
exports.config = {
- seleniumAddress: 'http://localhost:4444/wd/hub',
- specs: ['custom-validation.js']
+ seleniumAddress: 'http://localhost:4444/wd/hub'
}
@@ -0,0 +1,66 @@
+/* global browser, it, describe, element, by */
+
+describe('Schema Form validation messages', function() {
+
+ describe('#string', function() {
+ var URL = 'http://localhost:8080/examples/bootstrap-example.html#/86fb7505a8ab6a43bc70';
+
+ it('should not complain if it gets a normal string', function() {
+ browser.get(URL);
+ var input = element.all(by.css('form[name=ngform] input')).first();
+ input.sendKeys('string');
+
+ expect(input.getAttribute('value')).toEqual('string');
+ expect(input.evaluate('ngModel.$valid')).toEqual(true);
+
+ });
+
+
+ var validationMessageTestBuider = function(nr, value, validationMessage) {
+ it('should say "' + validationMessage + '" when input is ' + value, function() {
+ browser.get(URL);
+ var input = element.all(by.css('form[name=ngform] input')).get(nr);
+ input.sendKeys(value);
+
+ var message = element.all(by.css('form[name=ngform] div[sf-message]')).get(nr);
+ expect(input.evaluate('ngModel.$valid')).toEqual(false);
+ expect(message.getText()).toEqual(validationMessage);
+
+ });
+ };
+
+ var stringTests = {
+ 's': 'String is too short (1 chars), minimum 3',
+ 'tooo long string': 'String is too long (11 chars), maximum 10',
+ 'foo 66': 'String does not match pattern: ^[a-zA-Z ]+$'
+ };
+
+ Object.keys(stringTests).forEach(function(value) {
+ validationMessageTestBuider(0, value, stringTests[value]);
+ });
+
+
+ var integerTests = {
+ '3': '3 is less than the allowed minimum of 6',
+ '66': '66 is greater than the allowed maximum of 50',
+ '11': 'Value is not a multiple of 3',
+ 'aaa': 'Value is not a valid number'
+ };
+
+ Object.keys(integerTests).forEach(function(value) {
+ validationMessageTestBuider(1, value, integerTests[value]);
+ });
+
+
+ it('should say "Required" when fields are required', function() {
+ browser.get(URL);
+ element.all(by.css('form[name=ngform]')).submit();
+ var input = element.all(by.css('form[name=ngform] input')).get(1);
+
+ var message = element.all(by.css('form[name=ngform] div[sf-message]')).get(1);
+ expect(input.evaluate('ngModel.$valid')).toEqual(false);
+ expect(message.getText()).toEqual('Required');
+
+ });
+ });
+});
@@ -10,6 +10,7 @@ describe('schemaFormServices', function() {
var result = sfErrorMessage.interpolate(
'foobar-error', //error
'foobar', //value
+ 'foobar', //view value
{schema: {title: 'Foo'}}, //form
{'default': 'Oh noes!'}
);
@@ -25,6 +26,7 @@ describe('schemaFormServices', function() {
var result = sfErrorMessage.interpolate(
'foobar-error', //error
'foobar', //value
+ 'foobar', //view value
{validationMessage: {'default': 'Oh yes!'}, schema: {title: 'Foo'}}, //form
{'default': 'Oh noes!'}
);
@@ -40,6 +42,7 @@ describe('schemaFormServices', function() {
var result = sfErrorMessage.interpolate(
'foobar-error', //error
'foobar', //value
+ 'foobar', //view value
{schema: {title: 'Foo'}}, //form
{'default': 'Oh noes!', 'foobar-error': 'Aw chucks!'}
);
@@ -54,6 +57,7 @@ describe('schemaFormServices', function() {
var result = sfErrorMessage.interpolate(
'foobar-error', //error
'foobar', //value
+ 'foobar', //view value
{schema: {title: 'Foo'}, validationMessage: {'foobar-error': 'Noooooo!'}}, //form
{'default': 'Oh noes!', 'foobar-error': 'Aw chucks!'}
);
@@ -68,6 +72,7 @@ describe('schemaFormServices', function() {
var result = sfErrorMessage.interpolate(
'foobar-error', //error
'foobar', //value
+ 'foobar', //view value
{
schema: {title: 'Foo'},
validationMessage: {
@@ -87,6 +92,7 @@ describe('schemaFormServices', function() {
var result = sfErrorMessage.interpolate(
'foobar-error', //error
'foobar', //value
+ 'foobar', //view value
{
schema: {title: 'Foo'},
validationMessage: {
@@ -101,6 +107,7 @@ describe('schemaFormServices', function() {
result = sfErrorMessage.interpolate(
'foobar-error', //error
'foobar', //value
+ 'foobar', //view value
{
title: 'Bar',
schema: {title: 'Foo'},
@@ -121,6 +128,7 @@ describe('schemaFormServices', function() {
var result = sfErrorMessage.interpolate(
'foobar-error', //error
'foobar', //value
+ 'foobar', //view value
{
schema: {title: 'Foo'},
validationMessage: 'Huh?'
@@ -140,6 +148,7 @@ describe('schemaFormServices', function() {
var result = sfErrorMessage.interpolate(
'foobar-error', //error
'foobar', //value
+ 'foobar', //view value
{
schema: {title: 'Foo'},
validationMessage: {
@@ -174,6 +183,7 @@ describe('schemaFormServices', function() {
var result = sfErrorMessage.interpolate(
'foobar-error', //error
'foobar', //value
+ 'foobar', //view value
{
schema: {title: 'Foo'},
validationMessage: msgFn
@@ -201,7 +211,8 @@ describe('schemaFormServices', function() {
var result = sfErrorMessage.interpolate(
'tv4-302', //error
- 'foobar', //value
+ 'foobar', //value
+ 'foobar', //view value
{
schema: {title: 'Foo'},
validationMessage: {302: 'tv4 error!'}

0 comments on commit 5700261

Please sign in to comment.