|
1 | 1 | 'use strict';
|
2 | 2 |
|
3 |
| -describe('select', function() { |
4 |
| - var scope, formElement, element, $compile, ngModelCtrl, selectCtrl, renderSpy; |
| 3 | +ddescribe('select', function() { |
| 4 | + var scope, formElement, element, $compile, ngModelCtrl, selectCtrl, renderSpy, optionAttributesList = []; |
5 | 5 |
|
6 | 6 | function compile(html) {
|
7 | 7 | formElement = jqLite('<form name="form">' + html + '</form>');
|
@@ -55,6 +55,18 @@ describe('select', function() {
|
55 | 55 | '</option>'
|
56 | 56 | };
|
57 | 57 | });
|
| 58 | + |
| 59 | + $compileProvider.directive('exposeAttributes', function() { |
| 60 | + return { |
| 61 | + require: '^^select', |
| 62 | + link: { |
| 63 | + pre: function(scope, element, attrs, ctrl) { |
| 64 | + optionAttributesList.push(attrs); |
| 65 | + } |
| 66 | + } |
| 67 | + }; |
| 68 | + }); |
| 69 | + |
58 | 70 | }));
|
59 | 71 |
|
60 | 72 | beforeEach(inject(function($rootScope, _$compile_) {
|
@@ -1210,5 +1222,126 @@ describe('select', function() {
|
1210 | 1222 | }).toThrowMinErr('ng','badname', 'hasOwnProperty is not a valid "option value" name');
|
1211 | 1223 | });
|
1212 | 1224 |
|
| 1225 | + describe('with ngValue', function() { |
| 1226 | + |
| 1227 | + they('should set the option attribute and select it for value $prop', [ |
| 1228 | + 'string', |
| 1229 | + undefined, |
| 1230 | + 1, |
| 1231 | + true, |
| 1232 | + null, |
| 1233 | + {prop: 'value'}, |
| 1234 | + ['a'], |
| 1235 | + NaN |
| 1236 | + ], function(prop) { |
| 1237 | + scope.option1 = prop; |
| 1238 | + scope.selected = 'NOMATCH'; |
| 1239 | + |
| 1240 | + compile('<select ng-model="selected">' + |
| 1241 | + '<option ng-value="option1">{{option1}}</option>' + |
| 1242 | + '</select>'); |
| 1243 | + |
| 1244 | + scope.$digest(); |
| 1245 | + expect(element.find('option').eq(0).val()).toBe('? string:NOMATCH ?'); |
| 1246 | + |
| 1247 | + scope.selected = prop; |
| 1248 | + scope.$digest(); |
| 1249 | + |
| 1250 | + expect(element.find('option').eq(0).val()).toBe(hashKey(prop)); |
| 1251 | + |
| 1252 | + // Reset |
| 1253 | + scope.selected = false; |
| 1254 | + scope.$digest(); |
| 1255 | + |
| 1256 | + expect(element.find('option').eq(0).val()).toBe('? boolean:false ?'); |
| 1257 | + |
| 1258 | + browserTrigger(element.find('option').eq(0)); |
| 1259 | + if (Number.isNaN(prop)) { |
| 1260 | + expect(scope.selected).toBeNaN(); |
| 1261 | + } else { |
| 1262 | + expect(scope.selected).toBe(prop); |
| 1263 | + } |
| 1264 | + }); |
| 1265 | + |
| 1266 | + |
| 1267 | + tthey('should update the option attribute and select it for value $prop', [ |
| 1268 | + 'string', |
| 1269 | + // undefined, |
| 1270 | + // 1, |
| 1271 | + // true, |
| 1272 | + // null, |
| 1273 | + // {prop: 'value'}, |
| 1274 | + // ['a'], |
| 1275 | + // NaN |
| 1276 | + ], function(prop) { |
| 1277 | + scope.option = prop; |
| 1278 | + scope.selected = 'NOMATCH'; |
| 1279 | + |
| 1280 | + compile('<select ng-model="selected">' + |
| 1281 | + '<option ng-value="option">{{option}}</option>' + |
| 1282 | + '</select>'); |
| 1283 | + |
| 1284 | + var selectController = element.controller('select'); |
| 1285 | + spyOn(selectController, 'removeOption').andCallThrough(); |
| 1286 | + |
| 1287 | + scope.$digest(); |
| 1288 | + expect(selectController.removeOption).not.toHaveBeenCalled(); |
| 1289 | + expect(element.find('option').eq(0).val()).toBe('? string:NOMATCH ?'); |
| 1290 | + |
| 1291 | + scope.selected = prop; |
| 1292 | + scope.$digest(); |
| 1293 | + |
| 1294 | + expect(element.find('option').eq(0).val()).toBe(hashKey(prop)); |
| 1295 | + |
| 1296 | + scope.option = 'UPDATEDVALUE'; |
| 1297 | + scope.$digest(); |
| 1298 | + |
| 1299 | + expect(selectController.removeOption.calls.length).toBe(1); |
| 1300 | + |
| 1301 | + // Updating the option value currently does not update the select model |
| 1302 | + if (Number.isNaN(prop)) { |
| 1303 | + expect(selectController.removeOption.calls[0].args[0]).toBeNaN(); |
| 1304 | + expect(scope.selected).toBeNaN(); |
| 1305 | + } else { |
| 1306 | + expect(selectController.removeOption.calls[0].args[0]).toBe(prop); |
| 1307 | + expect(scope.selected).toBe(prop); |
| 1308 | + } |
| 1309 | + |
| 1310 | + expect(element.find('option').eq(0).prop('selected')).toBe(true); |
| 1311 | + expect(element.find('option').eq(1).val()).toBe('string:UPDATEDVALUE'); |
| 1312 | + |
| 1313 | + scope.selected = 'UPDATEDVALUE'; |
| 1314 | + scope.$digest(); |
| 1315 | + |
| 1316 | + expect(element.find('option').eq(0).prop('selected')).toBe(true); |
| 1317 | + expect(element.find('option').eq(0).val()).toBe('string:UPDATEDVALUE'); |
| 1318 | + }); |
| 1319 | + |
| 1320 | + it('should interact with custom attribute $observe and $set calls', function() { |
| 1321 | + var log = [], optionAttr; |
| 1322 | + |
| 1323 | + compile('<select ng-model="selected">' + |
| 1324 | + '<option expose-attributes ng-value="option">{{option}}</option>' + |
| 1325 | + '</select>'); |
| 1326 | + |
| 1327 | + optionAttr = optionAttributesList[0]; |
| 1328 | + optionAttr.$observe('value', function(newVal) { |
| 1329 | + log.push(newVal); |
| 1330 | + }); |
| 1331 | + |
| 1332 | + scope.option = 'init'; |
| 1333 | + scope.$digest(); |
| 1334 | + |
| 1335 | + expect(log[0]).toBe('init'); |
| 1336 | + expect(element.find('option').eq(1).val()).toBe('string:init'); |
| 1337 | + |
| 1338 | + optionAttr.$set('value', 'update'); |
| 1339 | + expect(log[1]).toBe('update'); |
| 1340 | + expect(element.find('option').eq(1).val()).toBe('string:update'); |
| 1341 | + |
| 1342 | + }); |
| 1343 | + |
| 1344 | + }); |
| 1345 | + |
1213 | 1346 | });
|
1214 | 1347 | });
|
0 commit comments