diff options
| author | Misko Hevery | 2011-09-08 13:56:29 -0700 | 
|---|---|---|
| committer | Igor Minar | 2011-10-11 11:01:45 -0700 | 
| commit | 4f78fd692c0ec51241476e6be9a4df06cd62fdd6 (patch) | |
| tree | 91f70bb89b9c095126fbc093f51cedbac5cb0c78 /test/widgetsSpec.js | |
| parent | df6d2ba3266de405ad6c2f270f24569355706e76 (diff) | |
| download | angular.js-4f78fd692c0ec51241476e6be9a4df06cd62fdd6.tar.bz2 | |
feat(forms): new and improved forms
Diffstat (limited to 'test/widgetsSpec.js')
| -rw-r--r-- | test/widgetsSpec.js | 820 | 
1 files changed, 5 insertions, 815 deletions
| diff --git a/test/widgetsSpec.js b/test/widgetsSpec.js index 02d0ef71..9361d28d 100644 --- a/test/widgetsSpec.js +++ b/test/widgetsSpec.js @@ -1,7 +1,7 @@  'use strict'; -describe("widget", function() { -  var compile, element, scope; +describe("widget", function(){ +  var compile = null, element = null, scope = null;    beforeEach(function() {      scope = null; @@ -24,397 +24,8 @@ describe("widget", function() {    }); -  describe("input", function() { - -    describe("text", function() { -      it('should input-text auto init and handle keydown/change events', function() { -        compile('<input type="Text" name="name" value="Misko" ng:change="count = count + 1" ng:init="count=0"/>'); -        expect(scope.name).toEqual("Misko"); -        expect(scope.count).toEqual(0); - -        scope.name = 'Adam'; -        scope.$digest(); -        expect(element.val()).toEqual("Adam"); - -        element.val('Shyam'); -        browserTrigger(element, 'keydown'); -        // keydown event must be deferred -        expect(scope.name).toEqual('Adam'); -        scope.$service('$browser').defer.flush(); -        expect(scope.name).toEqual('Shyam'); -        expect(scope.count).toEqual(1); - -        element.val('Kai'); -        browserTrigger(element, 'change'); -        expect(scope.name).toEqual('Kai'); -        expect(scope.count).toEqual(2); -      }); - -      it('should not trigger eval if value does not change', function() { -        compile('<input type="Text" name="name" value="Misko" ng:change="count = count + 1" ng:init="count=0"/>'); -        expect(scope.name).toEqual("Misko"); -        expect(scope.count).toEqual(0); -        browserTrigger(element, 'keydown'); -        expect(scope.name).toEqual("Misko"); -        expect(scope.count).toEqual(0); -      }); - -      it('should allow complex refernce binding', function() { -        compile('<div ng:init="obj={abc:{}}">'+ -                  '<input type="Text" name="obj[\'abc\'].name" value="Misko""/>'+ -                '</div>'); -        expect(scope.obj['abc'].name).toEqual('Misko'); -      }); - - -      describe("ng:format", function() { -        it("should format text", function() { -          compile('<input type="Text" name="list" value="a,b,c" ng:format="list"/>'); -          expect(scope.list).toEqual(['a', 'b', 'c']); - -          scope.list = ['x', 'y', 'z']; -          scope.$digest(); -          expect(element.val()).toEqual("x, y, z"); - -          element.val('1, 2, 3'); -          browserTrigger(element); -          expect(scope.list).toEqual(['1', '2', '3']); -        }); - -        it("should come up blank if null", function() { -          compile('<input type="text" name="age" ng:format="number" ng:init="age=null"/>'); -          expect(scope.age).toBeNull(); -          expect(scope.$element[0].value).toEqual(''); -        }); - -        it("should show incorect text while number does not parse", function() { -          compile('<input type="text" name="age" ng:format="number"/>'); -          scope.age = 123; -          scope.$digest(); -          scope.$element.val('123X'); -          browserTrigger(scope.$element, 'change'); -          expect(scope.$element.val()).toEqual('123X'); -          expect(scope.age).toEqual(123); -          expect(scope.$element).toBeInvalid(); -        }); - -        it("should clober incorect text if model changes", function() { -          compile('<input type="text" name="age" ng:format="number" value="123X"/>'); -          scope.age = 456; -          scope.$digest(); -          expect(scope.$element.val()).toEqual('456'); -        }); - -        it("should not clober text if model changes due to itself", function() { -          compile('<input type="text" name="list" ng:format="list" value="a"/>'); - -          scope.$element.val('a '); -          browserTrigger(scope.$element, 'change'); -          expect(scope.$element.val()).toEqual('a '); -          expect(scope.list).toEqual(['a']); - -          scope.$element.val('a ,'); -          browserTrigger(scope.$element, 'change'); -          expect(scope.$element.val()).toEqual('a ,'); -          expect(scope.list).toEqual(['a']); - -          scope.$element.val('a , '); -          browserTrigger(scope.$element, 'change'); -          expect(scope.$element.val()).toEqual('a , '); -          expect(scope.list).toEqual(['a']); - -          scope.$element.val('a , b'); -          browserTrigger(scope.$element, 'change'); -          expect(scope.$element.val()).toEqual('a , b'); -          expect(scope.list).toEqual(['a', 'b']); -        }); - -        it("should come up blank when no value specifiend", function() { -          compile('<input type="text" name="age" ng:format="number"/>'); -          scope.$digest(); -          expect(scope.$element.val()).toEqual(''); -          expect(scope.age).toEqual(null); -        }); -      }); - - -      describe("checkbox", function() { -        it("should format booleans", function() { -          compile('<input type="checkbox" name="name" ng:init="name=false"/>'); -          expect(scope.name).toEqual(false); -          expect(scope.$element[0].checked).toEqual(false); -        }); - -        it('should support type="checkbox"', function() { -          compile('<input type="checkBox" name="checkbox" checked ng:change="action = true"/>'); -          expect(scope.checkbox).toEqual(true); -          browserTrigger(element); -          expect(scope.checkbox).toEqual(false); -          expect(scope.action).toEqual(true); -          browserTrigger(element); -          expect(scope.checkbox).toEqual(true); -        }); - -        it("should use ng:format", function() { -          angularFormatter('testFormat', { -            parse: function(value) { -              return value ? "Worked" : "Failed"; -            }, - -            format: function(value) { -              if (value == undefined) return value; -              return value == "Worked"; -            } - -          }); -          compile('<input type="checkbox" name="state" ng:format="testFormat" checked/>'); -          expect(scope.state).toEqual("Worked"); -          expect(scope.$element[0].checked).toEqual(true); - -          browserTrigger(scope.$element); -          expect(scope.state).toEqual("Failed"); -          expect(scope.$element[0].checked).toEqual(false); - -          scope.state = "Worked"; -          scope.$digest(); -          expect(scope.state).toEqual("Worked"); -          expect(scope.$element[0].checked).toEqual(true); -        }); -      }); - - -      describe("ng:validate", function() { -        it("should process ng:validate", function() { -          compile('<input type="text" name="price" value="abc" ng:validate="number"/>', -                  jqLite(document.body)); -          expect(element.hasClass('ng-validation-error')).toBeTruthy(); -          expect(element.attr('ng-validation-error')).toEqual('Not a number'); - -          scope.price =  '123'; -          scope.$digest(); -          expect(element.hasClass('ng-validation-error')).toBeFalsy(); -          expect(element.attr('ng-validation-error')).toBeFalsy(); - -          element.val('x'); -          browserTrigger(element); -          expect(element.hasClass('ng-validation-error')).toBeTruthy(); -          expect(element.attr('ng-validation-error')).toEqual('Not a number'); -        }); - -        it('should not blow up for validation with bound attributes', function() { -          compile('<input type="text" name="price" boo="{{abc}}" ng:required/>'); -          expect(element.hasClass('ng-validation-error')).toBeTruthy(); -          expect(element.attr('ng-validation-error')).toEqual('Required'); - -          scope.price =  '123'; -          scope.$digest(); -          expect(element.hasClass('ng-validation-error')).toBeFalsy(); -          expect(element.attr('ng-validation-error')).toBeFalsy(); -        }); - -        it("should not call validator if undefined/empty", function() { -          var lastValue = "NOT_CALLED"; -          angularValidator.myValidator = function(value) {lastValue = value;}; -          compile('<input type="text" name="url" ng:validate="myValidator"/>'); -          expect(lastValue).toEqual("NOT_CALLED"); - -          scope.url = 'http://server'; -          scope.$digest(); -          expect(lastValue).toEqual("http://server"); - -          delete angularValidator.myValidator; -        }); -      }); -    }); - - -    it("should ignore disabled widgets", function() { -      compile('<input type="text" name="price" ng:required disabled/>'); -      expect(element.hasClass('ng-validation-error')).toBeFalsy(); -      expect(element.attr('ng-validation-error')).toBeFalsy(); -    }); - -    it("should ignore readonly widgets", function() { -      compile('<input type="text" name="price" ng:required readonly/>'); -      expect(element.hasClass('ng-validation-error')).toBeFalsy(); -      expect(element.attr('ng-validation-error')).toBeFalsy(); -    }); - -    it("should process ng:required", function() { -      compile('<input type="text" name="price" ng:required/>', jqLite(document.body)); -      expect(element.hasClass('ng-validation-error')).toBeTruthy(); -      expect(element.attr('ng-validation-error')).toEqual('Required'); - -      scope.price =  'xxx'; -      scope.$digest(); -      expect(element.hasClass('ng-validation-error')).toBeFalsy(); -      expect(element.attr('ng-validation-error')).toBeFalsy(); - -      element.val(''); -      browserTrigger(element); -      expect(element.hasClass('ng-validation-error')).toBeTruthy(); -      expect(element.attr('ng-validation-error')).toEqual('Required'); -    }); - -    it('should allow conditions on ng:required', function() { -      compile('<input type="text" name="price" ng:required="ineedz"/>', -              jqLite(document.body)); -      scope.ineedz =  false; -      scope.$digest(); -      expect(element.hasClass('ng-validation-error')).toBeFalsy(); -      expect(element.attr('ng-validation-error')).toBeFalsy(); - -      scope.price =  'xxx'; -      scope.$digest(); -      expect(element.hasClass('ng-validation-error')).toBeFalsy(); -      expect(element.attr('ng-validation-error')).toBeFalsy(); - -      scope.price =  ''; -      scope.ineedz =  true; -      scope.$digest(); -      expect(element.hasClass('ng-validation-error')).toBeTruthy(); -      expect(element.attr('ng-validation-error')).toEqual('Required'); - -      element.val('abc'); -      browserTrigger(element); -      expect(element.hasClass('ng-validation-error')).toBeFalsy(); -      expect(element.attr('ng-validation-error')).toBeFalsy(); -    }); - -    it("should process ng:required2", function() { -      compile('<textarea name="name">Misko</textarea>'); -      expect(scope.name).toEqual("Misko"); - -      scope.name =  'Adam'; -      scope.$digest(); -      expect(element.val()).toEqual("Adam"); - -      element.val('Shyam'); -      browserTrigger(element); -      expect(scope.name).toEqual('Shyam'); - -      element.val('Kai'); -      browserTrigger(element); -      expect(scope.name).toEqual('Kai'); -    }); - - -    describe('radio', function() { -      it('should support type="radio"', function() { -        compile('<div>' + -            '<input type="radio" name="chose" value="A" ng:change="clicked = 1"/>' + -            '<input type="radio" name="chose" value="B" checked ng:change="clicked = 2"/>' + -            '<input type="radio" name="chose" value="C" ng:change="clicked = 3"/>' + -        '</div>'); -        var a = element[0].childNodes[0]; -        var b = element[0].childNodes[1]; -        expect(b.name.split('@')[1]).toEqual('chose'); -        expect(scope.chose).toEqual('B'); -        scope.chose = 'A'; -        scope.$digest(); -        expect(a.checked).toEqual(true); - -        scope.chose = 'B'; -        scope.$digest(); -        expect(a.checked).toEqual(false); -        expect(b.checked).toEqual(true); -        expect(scope.clicked).not.toBeDefined(); - -        browserTrigger(a); -        expect(scope.chose).toEqual('A'); -        expect(scope.clicked).toEqual(1); -      }); - -      it('should honor model over html checked keyword after', function() { -        compile('<div ng:init="choose=\'C\'">' + -            '<input type="radio" name="choose" value="A""/>' + -            '<input type="radio" name="choose" value="B" checked/>' + -            '<input type="radio" name="choose" value="C"/>' + -        '</div>'); - -        expect(scope.choose).toEqual('C'); -      }); - -      it('should honor model over html checked keyword before', function() { -        compile('<div ng:init="choose=\'A\'">' + -            '<input type="radio" name="choose" value="A""/>' + -            '<input type="radio" name="choose" value="B" checked/>' + -            '<input type="radio" name="choose" value="C"/>' + -        '</div>'); - -        expect(scope.choose).toEqual('A'); -      }); - -    }); - - -    describe('select-one', function() { -      it('should initialize to selected', function() { -        compile( -            '<select name="selection">' + -                '<option>A</option>' + -                '<option selected>B</option>' + -            '</select>'); -        expect(scope.selection).toEqual('B'); -        scope.selection = 'A'; -        scope.$digest(); -        expect(scope.selection).toEqual('A'); -        expect(element[0].childNodes[0].selected).toEqual(true); -      }); - -      it('should compile children of a select without a name, but not create a model for it', -          function() { -        compile('<select>' + -                  '<option selected="true">{{a}}</option>' + -                  '<option value="">{{b}}</option>' + -                  '<option>C</option>' + -                '</select>'); -        scope.a = 'foo'; -        scope.b = 'bar'; -        scope.$digest(); - -        expect(scope.$element.text()).toBe('foobarC'); -      }); -    }); - - -    describe('select-multiple', function() { -      it('should support type="select-multiple"', function() { -        compile('<select name="selection" multiple>' + -                  '<option>A</option>' + -                  '<option selected>B</option>' + -                '</select>'); -        expect(scope.selection).toEqual(['B']); -        scope.selection = ['A']; -        scope.$digest(); -        expect(element[0].childNodes[0].selected).toEqual(true); -      }); -    }); - - -    it('should ignore text widget which have no name', function() { -      compile('<input type="text"/>'); -      expect(scope.$element.attr('ng-exception')).toBeFalsy(); -      expect(scope.$element.hasClass('ng-exception')).toBeFalsy(); -    }); - -    it('should ignore checkbox widget which have no name', function() { -      compile('<input type="checkbox"/>'); -      expect(scope.$element.attr('ng-exception')).toBeFalsy(); -      expect(scope.$element.hasClass('ng-exception')).toBeFalsy(); -    }); - -    it('should report error on assignment error', function() { -      expect(function() { -        compile('<input type="text" name="throw \'\'" value="x"/>'); -      }).toThrow("Syntax Error: Token '''' is an unexpected token at column 7 of the expression [throw ''] starting at ['']."); -      $logMock.error.logs.shift(); -    }); -  }); - - -  describe('ng:switch', function() { -    it('should switch on value change', function() { +  describe('ng:switch', function(){ +    it('should switch on value change', function(){        compile('<ng:switch on="select">' +            '<div ng:switch-when="1">first:{{name}}</div>' +            '<div ng:switch-when="2">second:{{name}}</div>' + @@ -458,6 +69,7 @@ describe("widget", function() {        expect(scope.$element.text()).toEqual('works');        dealoc(scope);      }); +    }); @@ -577,428 +189,6 @@ describe("widget", function() {    }); -  describe('ng:options', function() { -    var select, scope; - -    function createSelect(attrs, blank, unknown) { -      var html = '<select'; -      forEach(attrs, function(value, key) { -        if (isBoolean(value)) { -          if (value) html += ' ' + key; -        } else { -          html+= ' ' + key + '="' + value + '"'; -        } -      }); -      html += '>' + -        (blank ? '<option value="">blank</option>' : '') + -        (unknown ? '<option value="?">unknown</option>' : '') + -      '</select>'; -      select = jqLite(html); -      scope = compile(select); -    } - -    function createSingleSelect(blank, unknown) { -      createSelect({ -        'name':'selected', -        'ng:options':'value.name for value in values' -      }, blank, unknown); -    } - -    function createMultiSelect(blank, unknown) { -      createSelect({ -        'name':'selected', -        'multiple':true, -        'ng:options':'value.name for value in values' -      }, blank, unknown); -    } - -    afterEach(function() { -      dealoc(select); -      dealoc(scope); -    }); - -    it('should throw when not formated "? for ? in ?"', function() { -      expect(function() { -        compile('<select name="selected" ng:options="i dont parse"></select>'); -      }).toThrow("Expected ng:options in form of '_select_ (as _label_)? for (_key_,)?_value_ in" + -                 " _collection_' but got 'i dont parse'."); -    }); - -    it('should render a list', function() { -      createSingleSelect(); -      scope.values = [{name:'A'}, {name:'B'}, {name:'C'}]; -      scope.selected = scope.values[0]; -      scope.$digest(); -      var options = select.find('option'); -      expect(options.length).toEqual(3); -      expect(sortedHtml(options[0])).toEqual('<option value="0">A</option>'); -      expect(sortedHtml(options[1])).toEqual('<option value="1">B</option>'); -      expect(sortedHtml(options[2])).toEqual('<option value="2">C</option>'); -    }); - -    it('should render an object', function() { -      createSelect({ -        'name':'selected', -        'ng:options': 'value as key for (key, value) in object' -      }); -      scope.object = {'red':'FF0000', 'green':'00FF00', 'blue':'0000FF'}; -      scope.selected = scope.object.red; -      scope.$digest(); -      var options = select.find('option'); -      expect(options.length).toEqual(3); -      expect(sortedHtml(options[0])).toEqual('<option value="blue">blue</option>'); -      expect(sortedHtml(options[1])).toEqual('<option value="green">green</option>'); -      expect(sortedHtml(options[2])).toEqual('<option value="red">red</option>'); -      expect(options[2].selected).toEqual(true); - -      scope.object.azur = '8888FF'; -      scope.$digest(); -      options = select.find('option'); -      expect(options[3].selected).toEqual(true); -    }); - -    it('should grow list', function() { -      createSingleSelect(); -      scope.values = []; -      scope.$digest(); -      expect(select.find('option').length).toEqual(1); // because we add special empty option -      expect(sortedHtml(select.find('option')[0])).toEqual('<option value="?"></option>'); - -      scope.values.push({name:'A'}); -      scope.selected = scope.values[0]; -      scope.$digest(); -      expect(select.find('option').length).toEqual(1); -      expect(sortedHtml(select.find('option')[0])).toEqual('<option value="0">A</option>'); - -      scope.values.push({name:'B'}); -      scope.$digest(); -      expect(select.find('option').length).toEqual(2); -      expect(sortedHtml(select.find('option')[0])).toEqual('<option value="0">A</option>'); -      expect(sortedHtml(select.find('option')[1])).toEqual('<option value="1">B</option>'); -    }); - -    it('should shrink list', function() { -      createSingleSelect(); -      scope.values = [{name:'A'}, {name:'B'}, {name:'C'}]; -      scope.selected = scope.values[0]; -      scope.$digest(); -      expect(select.find('option').length).toEqual(3); - -      scope.values.pop(); -      scope.$digest(); -      expect(select.find('option').length).toEqual(2); -      expect(sortedHtml(select.find('option')[0])).toEqual('<option value="0">A</option>'); -      expect(sortedHtml(select.find('option')[1])).toEqual('<option value="1">B</option>'); - -      scope.values.pop(); -      scope.$digest(); -      expect(select.find('option').length).toEqual(1); -      expect(sortedHtml(select.find('option')[0])).toEqual('<option value="0">A</option>'); - -      scope.values.pop(); -      scope.selected = null; -      scope.$digest(); -      expect(select.find('option').length).toEqual(1); // we add back the special empty option -    }); - -    it('should shrink and then grow list', function() { -      createSingleSelect(); -      scope.values = [{name:'A'}, {name:'B'}, {name:'C'}]; -      scope.selected = scope.values[0]; -      scope.$digest(); -      expect(select.find('option').length).toEqual(3); - -      scope.values = [{name:'1'}, {name:'2'}]; -      scope.selected = scope.values[0]; -      scope.$digest(); -      expect(select.find('option').length).toEqual(2); - -      scope.values = [{name:'A'}, {name:'B'}, {name:'C'}]; -      scope.selected = scope.values[0]; -      scope.$digest(); -      expect(select.find('option').length).toEqual(3); -    }); - -    it('should update list', function() { -      createSingleSelect(); -      scope.values = [{name:'A'}, {name:'B'}, {name:'C'}]; -      scope.selected = scope.values[0]; -      scope.$digest(); - -      scope.values = [{name:'B'}, {name:'C'}, {name:'D'}]; -      scope.selected = scope.values[0]; -      scope.$digest(); -      var options = select.find('option'); -      expect(options.length).toEqual(3); -      expect(sortedHtml(options[0])).toEqual('<option value="0">B</option>'); -      expect(sortedHtml(options[1])).toEqual('<option value="1">C</option>'); -      expect(sortedHtml(options[2])).toEqual('<option value="2">D</option>'); -    }); - -    it('should preserve existing options', function() { -      createSingleSelect(true); - -      scope.$digest(); -      expect(select.find('option').length).toEqual(1); - -      scope.values = [{name:'A'}]; -      scope.selected = scope.values[0]; -      scope.$digest(); -      expect(select.find('option').length).toEqual(2); -      expect(jqLite(select.find('option')[0]).text()).toEqual('blank'); -      expect(jqLite(select.find('option')[1]).text()).toEqual('A'); - -      scope.values = []; -      scope.selected = null; -      scope.$digest(); -      expect(select.find('option').length).toEqual(1); -      expect(jqLite(select.find('option')[0]).text()).toEqual('blank'); -    }); - - -    describe('binding', function() { -      it('should bind to scope value', function() { -        createSingleSelect(); -        scope.values = [{name:'A'}, {name:'B'}]; -        scope.selected = scope.values[0]; -        scope.$digest(); -        expect(select.val()).toEqual('0'); - -        scope.selected = scope.values[1]; -        scope.$digest(); -        expect(select.val()).toEqual('1'); -      }); - - -      it('should bind to scope value and group', function() { -        createSelect({ -          'name':'selected', -          'ng:options':'item.name group by item.group for item in values' -        }); -        scope.values = [{name:'A'}, -                        {name:'B', group:'first'}, -                        {name:'C', group:'second'}, -                        {name:'D', group:'first'}, -                        {name:'E', group:'second'}]; -        scope.selected = scope.values[3]; -        scope.$digest(); -        expect(select.val()).toEqual('3'); - -        var first = jqLite(select.find('optgroup')[0]); -        var b = jqLite(first.find('option')[0]); -        var d = jqLite(first.find('option')[1]); -        expect(first.attr('label')).toEqual('first'); -        expect(b.text()).toEqual('B'); -        expect(d.text()).toEqual('D'); - -        var second = jqLite(select.find('optgroup')[1]); -        var c = jqLite(second.find('option')[0]); -        var e = jqLite(second.find('option')[1]); -        expect(second.attr('label')).toEqual('second'); -        expect(c.text()).toEqual('C'); -        expect(e.text()).toEqual('E'); - -        scope.selected = scope.values[0]; -        scope.$digest(); -        expect(select.val()).toEqual('0'); -      }); - -      it('should bind to scope value through experession', function() { -        createSelect({'name':'selected', 'ng:options':'item.id as item.name for item in values'}); -        scope.values = [{id:10, name:'A'}, {id:20, name:'B'}]; -        scope.selected = scope.values[0].id; -        scope.$digest(); -        expect(select.val()).toEqual('0'); - -        scope.selected = scope.values[1].id; -        scope.$digest(); -        expect(select.val()).toEqual('1'); -      }); - -      it('should bind to object key', function() { -        createSelect({ -          'name':'selected', -          'ng:options':'key as value for (key, value) in object' -        }); -        scope.object = {'red':'FF0000', 'green':'00FF00', 'blue':'0000FF'}; -        scope.selected = 'green'; -        scope.$digest(); -        expect(select.val()).toEqual('green'); - -        scope.selected = 'blue'; -        scope.$digest(); -        expect(select.val()).toEqual('blue'); -      }); - -      it('should bind to object value', function() { -        createSelect({ -          name:'selected', -          'ng:options':'value as key for (key, value) in object' -        }); -        scope.object = {'red':'FF0000', 'green':'00FF00', 'blue':'0000FF'}; -        scope.selected = '00FF00'; -        scope.$digest(); -        expect(select.val()).toEqual('green'); - -        scope.selected = '0000FF'; -        scope.$digest(); -        expect(select.val()).toEqual('blue'); -      }); - -      it('should insert a blank option if bound to null', function() { -        createSingleSelect(); -        scope.values = [{name:'A'}]; -        scope.selected = null; -        scope.$digest(); -        expect(select.find('option').length).toEqual(2); -        expect(select.val()).toEqual(''); -        expect(jqLite(select.find('option')[0]).val()).toEqual(''); - -        scope.selected = scope.values[0]; -        scope.$digest(); -        expect(select.val()).toEqual('0'); -        expect(select.find('option').length).toEqual(1); -      }); - -      it('should reuse blank option if bound to null', function() { -        createSingleSelect(true); -        scope.values = [{name:'A'}]; -        scope.selected = null; -        scope.$digest(); -        expect(select.find('option').length).toEqual(2); -        expect(select.val()).toEqual(''); -        expect(jqLite(select.find('option')[0]).val()).toEqual(''); - -        scope.selected = scope.values[0]; -        scope.$digest(); -        expect(select.val()).toEqual('0'); -        expect(select.find('option').length).toEqual(2); -      }); - -      it('should insert a unknown option if bound to something not in the list', function() { -        createSingleSelect(); -        scope.values = [{name:'A'}]; -        scope.selected = {}; -        scope.$digest(); -        expect(select.find('option').length).toEqual(2); -        expect(select.val()).toEqual('?'); -        expect(jqLite(select.find('option')[0]).val()).toEqual('?'); - -        scope.selected = scope.values[0]; -        scope.$digest(); -        expect(select.val()).toEqual('0'); -        expect(select.find('option').length).toEqual(1); -      }); -    }); - - -    describe('on change', function() { -      it('should update model on change', function() { -        createSingleSelect(); -        scope.values = [{name:'A'}, {name:'B'}]; -        scope.selected = scope.values[0]; -        scope.$digest(); -        expect(select.val()).toEqual('0'); - -        select.val('1'); -        browserTrigger(select, 'change'); -        expect(scope.selected).toEqual(scope.values[1]); -      }); - -      it('should fire ng:change if present', function() { -        createSelect({ -          name:'selected', -          'ng:options':'value for value in values', -          'ng:change':'log = log + selected.name' -        }); -        scope.values = [{name:'A'}, {name:'B'}]; -        scope.selected = scope.values[0]; -        scope.log = ''; -        scope.$digest(); -        expect(scope.log).toEqual(''); - -        select.val('1'); -        browserTrigger(select, 'change'); -        expect(scope.log).toEqual('B'); -        expect(scope.selected).toEqual(scope.values[1]); - -        // ignore change event when the model doesn't change -        browserTrigger(select, 'change'); -        expect(scope.log).toEqual('B'); -        expect(scope.selected).toEqual(scope.values[1]); - -        select.val('0'); -        browserTrigger(select, 'change'); -        expect(scope.log).toEqual('BA'); -        expect(scope.selected).toEqual(scope.values[0]); -      }); - -      it('should update model on change through expression', function() { -        createSelect({name:'selected', 'ng:options':'item.id as item.name for item in values'}); -        scope.values = [{id:10, name:'A'}, {id:20, name:'B'}]; -        scope.selected = scope.values[0].id; -        scope.$digest(); -        expect(select.val()).toEqual('0'); - -        select.val('1'); -        browserTrigger(select, 'change'); -        expect(scope.selected).toEqual(scope.values[1].id); -      }); - -      it('should update model to null on change', function() { -        createSingleSelect(true); -        scope.values = [{name:'A'}, {name:'B'}]; -        scope.selected = scope.values[0]; -        select.val('0'); -        scope.$digest(); - -        select.val(''); -        browserTrigger(select, 'change'); -        expect(scope.selected).toEqual(null); -      }); -    }); - - -    describe('select-many', function() { -      it('should read multiple selection', function() { -        createMultiSelect(); -        scope.values = [{name:'A'}, {name:'B'}]; - -        scope.selected = []; -        scope.$digest(); -        expect(select.find('option').length).toEqual(2); -        expect(select.find('option')[0].selected).toBe(false); -        expect(select.find('option')[1].selected).toBe(false); - -        scope.selected.push(scope.values[1]); -        scope.$digest(); -        expect(select.find('option').length).toEqual(2); -        expect(select.find('option')[0].selected).toEqual(false); -        expect(select.find('option')[1].selected).toEqual(true); - -        scope.selected.push(scope.values[0]); -        scope.$digest(); -        expect(select.find('option').length).toEqual(2); -        expect(select.find('option')[0].selected).toEqual(true); -        expect(select.find('option')[1].selected).toEqual(true); -      }); - -      it('should update model on change', function() { -        createMultiSelect(); -        scope.values = [{name:'A'}, {name:'B'}]; - -        scope.selected = []; -        scope.$digest(); -        select.find('option')[0].selected = true; - -        browserTrigger(select, 'change'); -        expect(scope.selected).toEqual([scope.values[0]]); -      }); -    }); - -  }); - -    describe('@ng:repeat', function() {      it('should ng:repeat over array', function() {        var scope = compile('<ul><li ng:repeat="item in items" ng:init="suffix = \';\'" ng:bind="item + suffix"></li></ul>'); | 
