test(select, ngOptions): add more tests for "required" with "empty" or "unknown" option

This commit is contained in:
Martin Staffa
2016-08-09 22:06:55 +02:00
committed by Martin Staffa
parent 080357e906
commit 8d7c7f4a8e
3 changed files with 234 additions and 57 deletions
-1
View File
@@ -704,7 +704,6 @@ var ngOptionsDirective = ['$compile', '$document', '$parse', function($compile,
ngModelCtrl.$render();
}
}
}
}
+110 -17
View File
@@ -2,12 +2,13 @@
describe('ngOptions', function() {
var scope, formElement, element, $compile, linkLog;
var scope, formElement, element, $compile, linkLog, ngModelCtrl;
function compile(html) {
formElement = jqLite('<form name="form">' + html + '</form>');
element = formElement.find('select');
$compile(formElement)(scope);
ngModelCtrl = element.controller('ngModel');
scope.$apply();
}
@@ -181,6 +182,7 @@ describe('ngOptions', function() {
afterEach(function() {
scope.$destroy(); //disables unknown option work during destruction
dealoc(formElement);
ngModelCtrl = null;
});
function createSelect(attrs, blank, unknown) {
@@ -2925,42 +2927,68 @@ describe('ngOptions', function() {
});
describe('ngRequired', function() {
describe('required state', function() {
it('should allow bindings on ngRequired', function() {
it('should set the error if the empty option is selected', function() {
createSelect({
'ng-model': 'selection',
'ng-options': 'item for item in values',
'required': ''
}, true);
scope.$apply(function() {
scope.values = ['a', 'b'];
scope.selection = scope.values[0];
});
expect(element).toBeValid();
expect(ngModelCtrl.$error.required).toBeFalsy();
var options = element.find('option');
// view -> model
browserTrigger(options[0], 'click');
expect(element).toBeInvalid();
expect(ngModelCtrl.$error.required).toBeTruthy();
browserTrigger(options[1], 'click');
expect(element).toBeValid();
expect(ngModelCtrl.$error.required).toBeFalsy();
// model -> view
scope.$apply('selection = "unmatched value"');
expect(options[0]).toBeMarkedAsSelected();
expect(element).toBeInvalid();
expect(ngModelCtrl.$error.required).toBeTruthy();
});
it('should validate with empty option and bound ngRequired', function() {
createSelect({
'ng-model': 'value',
'ng-options': 'item.name for item in values',
'ng-required': 'required'
}, true);
scope.$apply(function() {
scope.values = [{name: 'A', id: 1}, {name: 'B', id: 2}];
scope.required = false;
});
element.val('');
browserTrigger(element, 'change');
var options = element.find('option');
browserTrigger(options[0], 'click');
expect(element).toBeValid();
scope.$apply(function() {
scope.required = true;
});
scope.$apply('required = true');
expect(element).toBeInvalid();
scope.$apply(function() {
scope.value = scope.values[0];
});
scope.$apply('value = values[0]');
expect(element).toBeValid();
element.val('');
browserTrigger(element, 'change');
browserTrigger(options[0], 'click');
expect(element).toBeInvalid();
scope.$apply(function() {
scope.required = false;
});
scope.$apply('required = false');
expect(element).toBeValid();
});
@@ -2989,6 +3017,43 @@ describe('ngOptions', function() {
});
it('should NOT set the error if the empty option is present but required attribute is not',
function() {
scope.$apply(function() {
scope.values = ['a', 'b'];
});
createSingleSelect();
expect(element).toBeValid();
expect(element).toBePristine();
expect(ngModelCtrl.$error.required).toBeFalsy();
}
);
it('should NOT set the error if the unknown option is selected', function() {
createSelect({
'ng-model': 'selection',
'ng-options': 'item for item in values',
'required': ''
});
scope.$apply(function() {
scope.values = ['a', 'b'];
scope.selection = 'a';
});
expect(element).toBeValid();
expect(ngModelCtrl.$error.required).toBeFalsy();
scope.$apply('selection = "c"');
expect(element).toEqualSelect(['?'], 'string:a', 'string:b');
expect(element).toBeValid();
expect(ngModelCtrl.$error.required).toBeFalsy();
});
it('should allow falsy values as values', function() {
createSelect({
'ng-model': 'value',
@@ -3009,6 +3074,34 @@ describe('ngOptions', function() {
expect(element).toBeValid();
expect(scope.value).toBe(false);
});
it('should validate after option list was updated', function() {
createSelect({
'ng-model': 'selection',
'ng-options': 'item for item in values',
'required': ''
}, true);
scope.$apply(function() {
scope.values = ['A', 'B'];
scope.selection = scope.values[0];
});
expect(element).toEqualSelect('', ['string:A'], 'string:B');
expect(element).toBeValid();
expect(ngModelCtrl.$error.required).toBeFalsy();
scope.$apply(function() {
scope.values = ['C', 'D'];
});
expect(element).toEqualSelect([''], 'string:C', 'string:D');
expect(element).toBeInvalid();
expect(ngModelCtrl.$error.required).toBeTruthy();
// ngModel sets undefined for invalid values
expect(scope.selection).toBeUndefined();
});
});
describe('required and empty option', function() {
+124 -39
View File
@@ -7,6 +7,7 @@ describe('select', function() {
formElement = jqLite('<form name="form">' + html + '</form>');
element = formElement.find('select');
$compile(formElement)(scope);
ngModelCtrl = element.controller('ngModel');
scope.$digest();
}
@@ -79,6 +80,7 @@ describe('select', function() {
afterEach(function() {
scope.$destroy(); //disables unknown option work during destruction
dealoc(formElement);
ngModelCtrl = null;
});
@@ -190,55 +192,109 @@ describe('select', function() {
});
it('should require', function() {
compile(
'<select name="select" ng-model="selection" required ng-change="change()">' +
'<option value=""></option>' +
'<option value="c">C</option>' +
'</select>');
describe('required state', function() {
scope.change = function() {
scope.log += 'change;';
};
it('should set the error if the empty option is selected', function() {
compile(
'<select name="select" ng-model="selection" required>' +
'<option value=""></option>' +
'<option value="a">A</option>' +
'<option value="b">B</option>' +
'</select>');
scope.$apply(function() {
scope.log = '';
scope.selection = 'c';
scope.$apply(function() {
scope.selection = 'a';
});
expect(element).toBeValid();
expect(ngModelCtrl.$error.required).toBeFalsy();
var options = element.find('option');
// view -> model
browserTrigger(options[0], 'click');
expect(element).toBeInvalid();
expect(ngModelCtrl.$error.required).toBeTruthy();
browserTrigger(options[1], 'click');
expect(element).toBeValid();
expect(ngModelCtrl.$error.required).toBeFalsy();
// model -> view
scope.$apply('selection = null');
options = element.find('option');
expect(options[0]).toBeMarkedAsSelected();
expect(element).toBeInvalid();
expect(ngModelCtrl.$error.required).toBeTruthy();
});
expect(scope.form.select.$error.required).toBeFalsy();
expect(element).toBeValid();
expect(element).toBePristine();
scope.$apply(function() {
scope.selection = '';
it('should validate with empty option and bound ngRequired', function() {
compile(
'<select name="select" ng-model="selection" ng-required="required">' +
'<option value=""></option>' +
'<option value="a">A</option>' +
'<option value="b">B</option>' +
'</select>');
scope.$apply(function() {
scope.required = false;
});
var options = element.find('option');
browserTrigger(options[0], 'click');
expect(element).toBeValid();
scope.$apply('required = true');
expect(element).toBeInvalid();
scope.$apply('selection = "a"');
expect(element).toBeValid();
expect(element).toEqualSelect('', ['a'], 'b');
browserTrigger(options[0], 'click');
expect(element).toBeInvalid();
scope.$apply('required = false');
expect(element).toBeValid();
});
expect(scope.form.select.$error.required).toBeTruthy();
expect(element).toBeInvalid();
expect(element).toBePristine();
expect(scope.log).toEqual('');
element[0].value = 'c';
browserTrigger(element, 'change');
expect(element).toBeValid();
expect(element).toBeDirty();
expect(scope.log).toEqual('change;');
it('should not be invalid if no required attribute is present', function() {
compile(
'<select name="select" ng-model="selection">' +
'<option value=""></option>' +
'<option value="c">C</option>' +
'</select>');
expect(element).toBeValid();
expect(element).toBePristine();
});
it('should NOT set the error if the unknown option is selected', function() {
compile(
'<select name="select" ng-model="selection" required>' +
'<option value="a">A</option>' +
'<option value="b">B</option>' +
'</select>');
scope.$apply(function() {
scope.selection = 'a';
});
expect(element).toBeValid();
expect(ngModelCtrl.$error.required).toBeFalsy();
scope.$apply('selection = "c"');
expect(element).toEqualSelect([unknownValue('c')], 'a', 'b');
expect(element).toBeValid();
expect(ngModelCtrl.$error.required).toBeFalsy();
});
});
it('should not be invalid if no require', function() {
compile(
'<select name="select" ng-model="selection">' +
'<option value=""></option>' +
'<option value="c">C</option>' +
'</select>');
expect(element).toBeValid();
expect(element).toBePristine();
});
it('should work with repeated value options', function() {
scope.robots = ['c3p0', 'r2d2'];
scope.robot = 'r2d2';
@@ -2358,6 +2414,35 @@ describe('select', function() {
expect(previouslySelectedOptionElement).not.toBe(optionElements[0]);
});
it('should validate when the options change', function() {
scope.values = ['A', 'B'];
scope.selection = 'A';
compile(
'<select ng-model="selection" required>' +
'<option value="">--select--</option>' +
'<option ng-repeat="option in values" value="{{option}}">{{option}}</option>' +
'</select>'
);
expect(element).toEqualSelect('', ['A'], 'B');
expect(element).toBeValid();
expect(ngModelCtrl.$error.required).toBeFalsy();
scope.$apply(function() {
// Only when new objects are used, ngRepeat re-creates the element from scratch
scope.values = ['B', 'C'];
});
expect(element).toEqualSelect([''], 'B', 'C');
expect(element).toBeInvalid();
expect(ngModelCtrl.$error.required).toBeTruthy();
// ngModel sets undefined for invalid values
expect(scope.selection).toBeUndefined();
});
});