@@ -7,6 +7,7 @@ describe('select', function() {
7
7
formElement = jqLite ( '<form name="form">' + html + '</form>' ) ;
8
8
element = formElement . find ( 'select' ) ;
9
9
$compile ( formElement ) ( scope ) ;
10
+ ngModelCtrl = element . controller ( 'ngModel' ) ;
10
11
scope . $digest ( ) ;
11
12
}
12
13
@@ -79,6 +80,7 @@ describe('select', function() {
79
80
afterEach ( function ( ) {
80
81
scope . $destroy ( ) ; //disables unknown option work during destruction
81
82
dealoc ( formElement ) ;
83
+ ngModelCtrl = null ;
82
84
} ) ;
83
85
84
86
@@ -190,54 +192,108 @@ describe('select', function() {
190
192
} ) ;
191
193
192
194
193
- it ( 'should require' , function ( ) {
194
- compile (
195
- '<select name="select" ng-model="selection" required ng-change="change()">' +
196
- '<option value=""></option>' +
197
- '<option value="c">C</option>' +
198
- '</select>' ) ;
195
+ describe ( 'required state' , function ( ) {
199
196
200
- scope . change = function ( ) {
201
- scope . log += 'change;' ;
202
- } ;
197
+ it ( 'should set the error if the empty option is selected' , function ( ) {
198
+ compile (
199
+ '<select name="select" ng-model="selection" required>' +
200
+ '<option value=""></option>' +
201
+ '<option value="a">A</option>' +
202
+ '<option value="b">B</option>' +
203
+ '</select>' ) ;
203
204
204
- scope . $apply ( function ( ) {
205
- scope . log = '' ;
206
- scope . selection = 'c' ;
205
+ scope . $apply ( function ( ) {
206
+ scope . selection = 'a' ;
207
+ } ) ;
208
+
209
+ expect ( element ) . toBeValid ( ) ;
210
+ expect ( ngModelCtrl . $error . required ) . toBeFalsy ( ) ;
211
+
212
+ var options = element . find ( 'option' ) ;
213
+
214
+ // view -> model
215
+ browserTrigger ( options [ 0 ] , 'click' ) ;
216
+ expect ( element ) . toBeInvalid ( ) ;
217
+ expect ( ngModelCtrl . $error . required ) . toBeTruthy ( ) ;
218
+
219
+ browserTrigger ( options [ 1 ] , 'click' ) ;
220
+ expect ( element ) . toBeValid ( ) ;
221
+ expect ( ngModelCtrl . $error . required ) . toBeFalsy ( ) ;
222
+
223
+ // model -> view
224
+ scope . $apply ( 'selection = null' ) ;
225
+ options = element . find ( 'option' ) ;
226
+ expect ( options [ 0 ] ) . toBeMarkedAsSelected ( ) ;
227
+ expect ( element ) . toBeInvalid ( ) ;
228
+ expect ( ngModelCtrl . $error . required ) . toBeTruthy ( ) ;
207
229
} ) ;
208
230
209
- expect ( scope . form . select . $error . required ) . toBeFalsy ( ) ;
210
- expect ( element ) . toBeValid ( ) ;
211
- expect ( element ) . toBePristine ( ) ;
212
231
213
- scope . $apply ( function ( ) {
214
- scope . selection = '' ;
232
+ it ( 'should validate with empty option and bound ngRequired' , function ( ) {
233
+ compile (
234
+ '<select name="select" ng-model="selection" ng-required="required">' +
235
+ '<option value=""></option>' +
236
+ '<option value="a">A</option>' +
237
+ '<option value="b">B</option>' +
238
+ '</select>' ) ;
239
+
240
+ scope . $apply ( function ( ) {
241
+ scope . required = false ;
242
+ } ) ;
243
+
244
+ var options = element . find ( 'option' ) ;
245
+
246
+ browserTrigger ( options [ 0 ] , 'click' ) ;
247
+ expect ( element ) . toBeValid ( ) ;
248
+
249
+ scope . $apply ( 'required = true' ) ;
250
+ expect ( element ) . toBeInvalid ( ) ;
251
+
252
+ scope . $apply ( 'selection = "a"' ) ;
253
+ expect ( element ) . toBeValid ( ) ;
254
+ expect ( element ) . toEqualSelect ( '' , [ 'a' ] , 'b' ) ;
255
+
256
+ browserTrigger ( options [ 0 ] , 'click' ) ;
257
+ expect ( element ) . toBeInvalid ( ) ;
258
+
259
+ scope . $apply ( 'required = false' ) ;
260
+ expect ( element ) . toBeValid ( ) ;
215
261
} ) ;
216
262
217
- expect ( scope . form . select . $error . required ) . toBeTruthy ( ) ;
218
- expect ( element ) . toBeInvalid ( ) ;
219
- expect ( element ) . toBePristine ( ) ;
220
- expect ( scope . log ) . toEqual ( '' ) ;
221
263
222
- element [ 0 ] . value = 'c' ;
223
- browserTrigger ( element , 'change' ) ;
224
- expect ( element ) . toBeValid ( ) ;
225
- expect ( element ) . toBeDirty ( ) ;
226
- expect ( scope . log ) . toEqual ( 'change;' ) ;
227
- } ) ;
264
+ it ( 'should not be invalid if no required attribute is present' , function ( ) {
265
+ compile (
266
+ '<select name="select" ng-model="selection">' +
267
+ '<option value=""></option>' +
268
+ '<option value="c">C</option>' +
269
+ '</select>' ) ;
228
270
271
+ expect ( element ) . toBeValid ( ) ;
272
+ expect ( element ) . toBePristine ( ) ;
273
+ } ) ;
229
274
230
- it ( 'should not be invalid if no require' , function ( ) {
231
- compile (
232
- '<select name="select" ng-model="selection">' +
233
- '<option value=""></option>' +
234
- '<option value="c">C</option>' +
235
- '</select>' ) ;
236
275
237
- expect ( element ) . toBeValid ( ) ;
238
- expect ( element ) . toBePristine ( ) ;
239
- } ) ;
276
+ it ( 'should NOT set the error if the unknown option is selected' , function ( ) {
277
+ compile (
278
+ '<select name="select" ng-model="selection" required>' +
279
+ '<option value="a">A</option>' +
280
+ '<option value="b">B</option>' +
281
+ '</select>' ) ;
240
282
283
+ scope . $apply ( function ( ) {
284
+ scope . selection = 'a' ;
285
+ } ) ;
286
+
287
+ expect ( element ) . toBeValid ( ) ;
288
+ expect ( ngModelCtrl . $error . required ) . toBeFalsy ( ) ;
289
+
290
+ scope . $apply ( 'selection = "c"' ) ;
291
+ expect ( element ) . toEqualSelect ( [ unknownValue ( 'c' ) ] , 'a' , 'b' ) ;
292
+ expect ( element ) . toBeValid ( ) ;
293
+ expect ( ngModelCtrl . $error . required ) . toBeFalsy ( ) ;
294
+ } ) ;
295
+
296
+ } ) ;
241
297
242
298
it ( 'should work with repeated value options' , function ( ) {
243
299
scope . robots = [ 'c3p0' , 'r2d2' ] ;
@@ -2358,6 +2414,35 @@ describe('select', function() {
2358
2414
expect ( previouslySelectedOptionElement ) . not . toBe ( optionElements [ 0 ] ) ;
2359
2415
} ) ;
2360
2416
2417
+
2418
+ it ( 'should validate when the options change' , function ( ) {
2419
+ scope . values = [ 'A' , 'B' ] ;
2420
+ scope . selection = 'A' ;
2421
+
2422
+ compile (
2423
+ '<select ng-model="selection" required>' +
2424
+ '<option value="">--select--</option>' +
2425
+ '<option ng-repeat="option in values" value="{{option}}">{{option}}</option>' +
2426
+ '</select>'
2427
+ ) ;
2428
+
2429
+ expect ( element ) . toEqualSelect ( '' , [ 'A' ] , 'B' ) ;
2430
+ expect ( element ) . toBeValid ( ) ;
2431
+ expect ( ngModelCtrl . $error . required ) . toBeFalsy ( ) ;
2432
+
2433
+ scope . $apply ( function ( ) {
2434
+ // Only when new objects are used, ngRepeat re-creates the element from scratch
2435
+ scope . values = [ 'B' , 'C' ] ;
2436
+ } ) ;
2437
+
2438
+ expect ( element ) . toEqualSelect ( [ '' ] , 'B' , 'C' ) ;
2439
+ expect ( element ) . toBeInvalid ( ) ;
2440
+ expect ( ngModelCtrl . $error . required ) . toBeTruthy ( ) ;
2441
+ // ngModel sets undefined for invalid values
2442
+ expect ( scope . selection ) . toBeUndefined ( ) ;
2443
+ } ) ;
2444
+
2445
+
2361
2446
} ) ;
2362
2447
2363
2448
0 commit comments