diff options
| author | Misko Hevery | 2011-03-23 09:33:29 -0700 | 
|---|---|---|
| committer | Vojta Jina | 2011-08-02 01:00:03 +0200 | 
| commit | 8f0dcbab804180828d6859b1340c86cf161209fb (patch) | |
| tree | d13d47d47a1889cb7c96a87cecacd2e25307d51c /test/widgetsSpec.js | |
| parent | 1f4b417184ce53af15474de065400f8a686430c5 (diff) | |
| download | angular.js-8f0dcbab804180828d6859b1340c86cf161209fb.tar.bz2 | |
feat(scope): new and improved scope implementation
- Speed improvements (about 4x on flush phase)
- Memory improvements (uses no function closures)
- Break $eval into $apply, $dispatch, $flush
- Introduced $watch and $observe
Breaks angular.equals() use === instead of ==
Breaks angular.scope() does not take parent as first argument
Breaks scope.$watch() takes scope as first argument
Breaks scope.$set(), scope.$get are removed
Breaks scope.$config is removed
Breaks $route.onChange callback has not "this" bounded
Diffstat (limited to 'test/widgetsSpec.js')
| -rw-r--r-- | test/widgetsSpec.js | 348 | 
1 files changed, 184 insertions, 164 deletions
diff --git a/test/widgetsSpec.js b/test/widgetsSpec.js index 225f0a1f..978392ec 100644 --- a/test/widgetsSpec.js +++ b/test/widgetsSpec.js @@ -13,7 +13,9 @@ describe("widget", function(){        } else {          element = jqLite(html);        } -      return scope = angular.compile(element)(); +      scope = angular.compile(element)(); +      scope.$apply(); +      return scope;      };    }); @@ -26,25 +28,25 @@ describe("widget", 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.$get('name')).toEqual("Misko"); -        expect(scope.$get('count')).toEqual(0); +        expect(scope.name).toEqual("Misko"); +        expect(scope.count).toEqual(0); -        scope.$set('name', 'Adam'); -        scope.$eval(); +        scope.name = 'Adam'; +        scope.$digest();          expect(element.val()).toEqual("Adam");          element.val('Shyam');          browserTrigger(element, 'keydown');          // keydown event must be deferred -        expect(scope.$get('name')).toEqual('Adam'); +        expect(scope.name).toEqual('Adam');          scope.$service('$browser').defer.flush(); -        expect(scope.$get('name')).toEqual('Shyam'); -        expect(scope.$get('count')).toEqual(1); +        expect(scope.name).toEqual('Shyam'); +        expect(scope.count).toEqual(1);          element.val('Kai');          browserTrigger(element, 'change'); -        expect(scope.$get('name')).toEqual('Kai'); -        expect(scope.$get('count')).toEqual(2); +        expect(scope.name).toEqual('Kai'); +        expect(scope.count).toEqual(2);        });        it('should not trigger eval if value does not change', function(){ @@ -67,15 +69,15 @@ describe("widget", function(){          it("should format text", function(){            compile('<input type="Text" name="list" value="a,b,c" ng:format="list"/>'); -          expect(scope.$get('list')).toEqual(['a', 'b', 'c']); +          expect(scope.list).toEqual(['a', 'b', 'c']); -          scope.$set('list', ['x', 'y', 'z']); -          scope.$eval(); +          scope.list = ['x', 'y', 'z']; +          scope.$digest();            expect(element.val()).toEqual("x, y, z");            element.val('1, 2, 3');            browserTrigger(element); -          expect(scope.$get('list')).toEqual(['1', '2', '3']); +          expect(scope.list).toEqual(['1', '2', '3']);          });          it("should come up blank if null", function(){ @@ -87,7 +89,7 @@ describe("widget", function(){          it("should show incorect text while number does not parse", function(){            compile('<input type="text" name="age" ng:format="number"/>');            scope.age = 123; -          scope.$eval(); +          scope.$digest();            scope.$element.val('123X');            browserTrigger(scope.$element, 'change');            expect(scope.$element.val()).toEqual('123X'); @@ -98,11 +100,11 @@ describe("widget", function(){          it("should clober incorect text if model changes", function(){            compile('<input type="text" name="age" ng:format="number" value="123X"/>');            scope.age = 456; -          scope.$eval(); +          scope.$digest();            expect(scope.$element.val()).toEqual('456');          }); -        it("should not clober text if model changes doe to itself", function(){ +        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 '); @@ -128,7 +130,7 @@ describe("widget", function(){          it("should come up blank when no value specifiend", function(){            compile('<input type="text" name="age" ng:format="number"/>'); -          scope.$eval(); +          scope.$digest();            expect(scope.$element.val()).toEqual('');            expect(scope.age).toEqual(null);          }); @@ -173,7 +175,7 @@ describe("widget", function(){            expect(scope.$element[0].checked).toEqual(false);            scope.state = "Worked"; -          scope.$eval(); +          scope.$digest();            expect(scope.state).toEqual("Worked");            expect(scope.$element[0].checked).toEqual(true);          }); @@ -186,8 +188,8 @@ describe("widget", function(){            expect(element.hasClass('ng-validation-error')).toBeTruthy();            expect(element.attr('ng-validation-error')).toEqual('Not a number'); -          scope.$set('price', '123'); -          scope.$eval(); +          scope.price =  '123'; +          scope.$digest();            expect(element.hasClass('ng-validation-error')).toBeFalsy();            expect(element.attr('ng-validation-error')).toBeFalsy(); @@ -202,8 +204,8 @@ describe("widget", function(){            expect(element.hasClass('ng-validation-error')).toBeTruthy();            expect(element.attr('ng-validation-error')).toEqual('Required'); -          scope.$set('price', '123'); -          scope.$eval(); +          scope.price =  '123'; +          scope.$digest();            expect(element.hasClass('ng-validation-error')).toBeFalsy();            expect(element.attr('ng-validation-error')).toBeFalsy();          }); @@ -215,7 +217,7 @@ describe("widget", function(){            expect(lastValue).toEqual("NOT_CALLED");            scope.url = 'http://server'; -          scope.$eval(); +          scope.$digest();            expect(lastValue).toEqual("http://server");            delete angularValidator.myValidator; @@ -240,8 +242,8 @@ describe("widget", function(){        expect(element.hasClass('ng-validation-error')).toBeTruthy();        expect(element.attr('ng-validation-error')).toEqual('Required'); -      scope.$set('price', 'xxx'); -      scope.$eval(); +      scope.price =  'xxx'; +      scope.$digest();        expect(element.hasClass('ng-validation-error')).toBeFalsy();        expect(element.attr('ng-validation-error')).toBeFalsy(); @@ -254,19 +256,19 @@ describe("widget", function(){      it('should allow conditions on ng:required', function() {        compile('<input type="text" name="price" ng:required="ineedz"/>',                jqLite(document.body)); -      scope.$set('ineedz', false); -      scope.$eval(); +      scope.ineedz =  false; +      scope.$digest();        expect(element.hasClass('ng-validation-error')).toBeFalsy();        expect(element.attr('ng-validation-error')).toBeFalsy(); -      scope.$set('price', 'xxx'); -      scope.$eval(); +      scope.price =  'xxx'; +      scope.$digest();        expect(element.hasClass('ng-validation-error')).toBeFalsy();        expect(element.attr('ng-validation-error')).toBeFalsy(); -      scope.$set('price', ''); -      scope.$set('ineedz', true); -      scope.$eval(); +      scope.price =  ''; +      scope.ineedz =  true; +      scope.$digest();        expect(element.hasClass('ng-validation-error')).toBeTruthy();        expect(element.attr('ng-validation-error')).toEqual('Required'); @@ -278,31 +280,31 @@ describe("widget", function(){      it("should process ng:required2", function() {        compile('<textarea name="name">Misko</textarea>'); -      expect(scope.$get('name')).toEqual("Misko"); +      expect(scope.name).toEqual("Misko"); -      scope.$set('name', 'Adam'); -      scope.$eval(); +      scope.name =  'Adam'; +      scope.$digest();        expect(element.val()).toEqual("Adam");        element.val('Shyam');        browserTrigger(element); -      expect(scope.$get('name')).toEqual('Shyam'); +      expect(scope.name).toEqual('Shyam');        element.val('Kai');        browserTrigger(element); -      expect(scope.$get('name')).toEqual('Kai'); +      expect(scope.name).toEqual('Kai');      });      it('should call ng:change on button click', function(){        compile('<input type="button" value="Click Me" ng:change="clicked = true"/>');        browserTrigger(element); -      expect(scope.$get('clicked')).toEqual(true); +      expect(scope.clicked).toEqual(true);      });      it('should support button alias', function(){        compile('<button ng:change="clicked = true">Click {{"Me"}}.</button>');        browserTrigger(element); -      expect(scope.$get('clicked')).toEqual(true); +      expect(scope.clicked).toEqual(true);        expect(scope.$element.text()).toEqual("Click Me.");      }); @@ -319,11 +321,11 @@ describe("widget", function(){          expect(b.name.split('@')[1]).toEqual('chose');          expect(scope.chose).toEqual('B');          scope.chose = 'A'; -        scope.$eval(); +        scope.$digest();          expect(a.checked).toEqual(true);          scope.chose = 'B'; -        scope.$eval(); +        scope.$digest();          expect(a.checked).toEqual(false);          expect(b.checked).toEqual(true);          expect(scope.clicked).not.toBeDefined(); @@ -364,12 +366,11 @@ describe("widget", function(){              '</select>');          expect(scope.selection).toEqual('B');          scope.selection = 'A'; -        scope.$eval(); +        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>' + @@ -379,7 +380,7 @@ describe("widget", function(){                  '</select>');          scope.a = 'foo';          scope.b = 'bar'; -        scope.$eval(); +        scope.$flush();          expect(scope.$element.text()).toBe('foobarC');        }); @@ -394,9 +395,10 @@ describe("widget", function(){                  '</select>');          expect(scope.selection).toEqual(['B']);          scope.selection = ['A']; -        scope.$eval(); +        scope.$digest();          expect(element[0].childNodes[0].selected).toEqual(true);        }); +      });      it('should ignore text widget which have no name', function(){ @@ -412,19 +414,12 @@ describe("widget", function(){      });      it('should report error on assignment error', function(){ -      compile('<input type="text" name="throw \'\'" value="x"/>'); -      expect(element.hasClass('ng-exception')).toBeTruthy(); -      expect(scope.$service('$log').error.logs.shift()[0]). -        toMatchError(/Syntax Error: Token '''' is an unexpected token/); +      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();      }); -    it('should report error on ng:change exception', function(){ -      compile('<button ng:change="a-2=x">click</button>'); -      browserTrigger(element); -      expect(element.hasClass('ng-exception')).toBeTruthy(); -      expect(scope.$service('$log').error.logs.shift()[0]). -        toMatchError(/Syntax Error: Token '=' implies assignment but \[a-2\] can not be assigned to/); -    });    });    describe('ng:switch', function(){ @@ -436,43 +431,38 @@ describe("widget", function(){          '</ng:switch>');        expect(element.html()).toEqual('');        scope.select = 1; -      scope.$eval(); +      scope.$apply();        expect(element.text()).toEqual('first:');        scope.name="shyam"; -      scope.$eval(); +      scope.$apply();        expect(element.text()).toEqual('first:shyam');        scope.select = 2; -      scope.$eval(); +      scope.$apply();        expect(element.text()).toEqual('second:shyam');        scope.name = 'misko'; -      scope.$eval(); +      scope.$apply();        expect(element.text()).toEqual('second:misko');        scope.select = true; -      scope.$eval(); +      scope.$apply();        expect(element.text()).toEqual('true:misko');      }); -    it("should compare stringified versions", function(){ -      var switchWidget = angular.widget('ng:switch'); -      expect(switchWidget.equals(true, 'true')).toEqual(true); -    }); -      it('should switch on switch-when-default', function(){        compile('<ng:switch on="select">' + -          '<div ng:switch-when="1">one</div>' + -          '<div ng:switch-default>other</div>' + -        '</ng:switch>'); -      scope.$eval(); +                '<div ng:switch-when="1">one</div>' + +                '<div ng:switch-default>other</div>' + +              '</ng:switch>'); +      scope.$apply();        expect(element.text()).toEqual('other');        scope.select = 1; -      scope.$eval(); +      scope.$apply();        expect(element.text()).toEqual('one');      });      it('should call change on switch', function(){        var scope = angular.compile('<ng:switch on="url" change="name=\'works\'"><div ng:switch-when="a">{{name}}</div></ng:switch>')();        scope.url = 'a'; -      scope.$eval(); +      scope.$apply();        expect(scope.name).toEqual(undefined);        expect(scope.$element.text()).toEqual('works');        dealoc(scope); @@ -483,11 +473,11 @@ describe("widget", function(){      it('should include on external file', function() {        var element = jqLite('<ng:include src="url" scope="childScope"></ng:include>');        var scope = angular.compile(element)(); -      scope.childScope = createScope(); +      scope.childScope = scope.$new();        scope.childScope.name = 'misko';        scope.url = 'myUrl';        scope.$service('$xhr.cache').data.myUrl = {value:'{{name}}'}; -      scope.$eval(); +      scope.$flush();        expect(element.text()).toEqual('misko');        dealoc(scope);      }); @@ -495,16 +485,16 @@ describe("widget", function(){      it('should remove previously included text if a falsy value is bound to src', function() {        var element = jqLite('<ng:include src="url" scope="childScope"></ng:include>');        var scope = angular.compile(element)(); -      scope.childScope = createScope(); +      scope.childScope = scope.$new();        scope.childScope.name = 'igor';        scope.url = 'myUrl';        scope.$service('$xhr.cache').data.myUrl = {value:'{{name}}'}; -      scope.$eval(); +      scope.$flush();        expect(element.text()).toEqual('igor');        scope.url = undefined; -      scope.$eval(); +      scope.$flush();        expect(element.text()).toEqual('');        dealoc(scope); @@ -515,11 +505,14 @@ describe("widget", function(){        var scope = angular.compile(element)();        scope.url = 'myUrl';        scope.$service('$xhr.cache').data.myUrl = {value:'{{c=c+1}}'}; -      scope.$eval(); - -      // this one should really be just '1', but due to lack of real events things are not working -      // properly. see discussion at: http://is.gd/ighKk -      expect(element.text()).toEqual('4'); +      scope.$flush(); +      // TODO(misko): because we are using scope==this, the eval gets registered +      // during the flush phase and hence does not get called. +      // I don't think passing 'this' makes sense. Does having scope on ng:include makes sense? +      // should we make scope="this" ilegal? +      scope.$flush(); + +      expect(element.text()).toEqual('1');        dealoc(element);      }); @@ -531,11 +524,28 @@ describe("widget", function(){        scope.url = 'myUrl';        scope.$service('$xhr.cache').data.myUrl = {value:'my partial'}; -      scope.$eval(); +      scope.$flush();        expect(element.text()).toEqual('my partial');        expect(scope.loaded).toBe(true);        dealoc(element);      }); + +    it('should destroy old scope', function(){ +      var element = jqLite('<ng:include src="url"></ng:include>'); +      var scope = angular.compile(element)(); + +      expect(scope.$$childHead).toBeFalsy(); + +      scope.url = 'myUrl'; +      scope.$service('$xhr.cache').data.myUrl = {value:'my partial'}; +      scope.$flush(); +      expect(scope.$$childHead).toBeTruthy(); + +      scope.url = null; +      scope.$flush(); +      expect(scope.$$childHead).toBeFalsy(); +      dealoc(element); +    });    });    describe('a', function() { @@ -624,7 +634,7 @@ describe("widget", function(){        createSingleSelect();        scope.values = [{name:'A'}, {name:'B'}, {name:'C'}];        scope.selected = scope.values[0]; -      scope.$eval(); +      scope.$flush();        var options = select.find('option');        expect(options.length).toEqual(3);        expect(sortedHtml(options[0])).toEqual('<option value="0">A</option>'); @@ -639,7 +649,7 @@ describe("widget", function(){        });        scope.object = {'red':'FF0000', 'green':'00FF00', 'blue':'0000FF'};        scope.selected = scope.object.red; -      scope.$eval(); +      scope.$flush();        var options = select.find('option');        expect(options.length).toEqual(3);        expect(sortedHtml(options[0])).toEqual('<option value="blue">blue</option>'); @@ -648,7 +658,7 @@ describe("widget", function(){        expect(options[2].selected).toEqual(true);        scope.object.azur = '8888FF'; -      scope.$eval(); +      scope.$flush();        options = select.find('option');        expect(options[3].selected).toEqual(true);      }); @@ -656,18 +666,18 @@ describe("widget", function(){      it('should grow list', function(){        createSingleSelect();        scope.values = []; -      scope.$eval(); +      scope.$flush();        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.$eval(); +      scope.$flush();        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.$eval(); +      scope.$flush();        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>'); @@ -677,23 +687,23 @@ describe("widget", function(){        createSingleSelect();        scope.values = [{name:'A'}, {name:'B'}, {name:'C'}];        scope.selected = scope.values[0]; -      scope.$eval(); +      scope.$flush();        expect(select.find('option').length).toEqual(3);        scope.values.pop(); -      scope.$eval(); +      scope.$flush();        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.$eval(); +      scope.$flush();        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.$eval(); +      scope.$flush();        expect(select.find('option').length).toEqual(1); // we add back the special empty option      }); @@ -701,17 +711,17 @@ describe("widget", function(){        createSingleSelect();        scope.values = [{name:'A'}, {name:'B'}, {name:'C'}];        scope.selected = scope.values[0]; -      scope.$eval(); +      scope.$flush();        expect(select.find('option').length).toEqual(3);        scope.values = [{name:'1'}, {name:'2'}];        scope.selected = scope.values[0]; -      scope.$eval(); +      scope.$flush();        expect(select.find('option').length).toEqual(2);        scope.values = [{name:'A'}, {name:'B'}, {name:'C'}];        scope.selected = scope.values[0]; -      scope.$eval(); +      scope.$flush();        expect(select.find('option').length).toEqual(3);      }); @@ -719,11 +729,11 @@ describe("widget", function(){        createSingleSelect();        scope.values = [{name:'A'}, {name:'B'}, {name:'C'}];        scope.selected = scope.values[0]; -      scope.$eval(); +      scope.$flush();        scope.values = [{name:'B'}, {name:'C'}, {name:'D'}];        scope.selected = scope.values[0]; -      scope.$eval(); +      scope.$flush();        var options = select.find('option');        expect(options.length).toEqual(3);        expect(sortedHtml(options[0])).toEqual('<option value="0">B</option>'); @@ -734,19 +744,19 @@ describe("widget", function(){      it('should preserve existing options', function(){        createSingleSelect(true); -      scope.$eval(); +      scope.$flush();        expect(select.find('option').length).toEqual(1);        scope.values = [{name:'A'}];        scope.selected = scope.values[0]; -      scope.$eval(); +      scope.$flush();        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.$eval(); +      scope.$flush();        expect(select.find('option').length).toEqual(1);        expect(jqLite(select.find('option')[0]).text()).toEqual('blank');      }); @@ -756,11 +766,11 @@ describe("widget", function(){          createSingleSelect();          scope.values = [{name:'A'}, {name:'B'}];          scope.selected = scope.values[0]; -        scope.$eval(); +        scope.$flush();          expect(select.val()).toEqual('0');          scope.selected = scope.values[1]; -        scope.$eval(); +        scope.$flush();          expect(select.val()).toEqual('1');        }); @@ -775,7 +785,7 @@ describe("widget", function(){                          {name:'D', group:'first'},                          {name:'E', group:'second'}];          scope.selected = scope.values[3]; -        scope.$eval(); +        scope.$flush();          expect(select.val()).toEqual('3');          var first = jqLite(select.find('optgroup')[0]); @@ -793,7 +803,7 @@ describe("widget", function(){          expect(e.text()).toEqual('E');          scope.selected = scope.values[0]; -        scope.$eval(); +        scope.$flush();          expect(select.val()).toEqual('0');        }); @@ -801,11 +811,11 @@ describe("widget", 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.$eval(); +        scope.$flush();          expect(select.val()).toEqual('0');          scope.selected = scope.values[1].id; -        scope.$eval(); +        scope.$flush();          expect(select.val()).toEqual('1');        }); @@ -816,11 +826,11 @@ describe("widget", function(){          });          scope.object = {'red':'FF0000', 'green':'00FF00', 'blue':'0000FF'};          scope.selected = 'green'; -        scope.$eval(); +        scope.$flush();          expect(select.val()).toEqual('green');          scope.selected = 'blue'; -        scope.$eval(); +        scope.$flush();          expect(select.val()).toEqual('blue');        }); @@ -831,11 +841,11 @@ describe("widget", function(){          });          scope.object = {'red':'FF0000', 'green':'00FF00', 'blue':'0000FF'};          scope.selected = '00FF00'; -        scope.$eval(); +        scope.$flush();          expect(select.val()).toEqual('green');          scope.selected = '0000FF'; -        scope.$eval(); +        scope.$flush();          expect(select.val()).toEqual('blue');        }); @@ -843,13 +853,13 @@ describe("widget", function(){          createSingleSelect();          scope.values = [{name:'A'}];          scope.selected = null; -        scope.$eval(); +        scope.$flush();          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.$eval(); +        scope.$flush();          expect(select.val()).toEqual('0');          expect(select.find('option').length).toEqual(1);        }); @@ -858,13 +868,13 @@ describe("widget", function(){          createSingleSelect(true);          scope.values = [{name:'A'}];          scope.selected = null; -        scope.$eval(); +        scope.$flush();          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.$eval(); +        scope.$flush();          expect(select.val()).toEqual('0');          expect(select.find('option').length).toEqual(2);        }); @@ -873,13 +883,13 @@ describe("widget", function(){          createSingleSelect();          scope.values = [{name:'A'}];          scope.selected = {}; -        scope.$eval(); +        scope.$flush();          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.$eval(); +        scope.$flush();          expect(select.val()).toEqual('0');          expect(select.find('option').length).toEqual(1);        }); @@ -890,7 +900,7 @@ describe("widget", function(){          createSingleSelect();          scope.values = [{name:'A'}, {name:'B'}];          scope.selected = scope.values[0]; -        scope.$eval(); +        scope.$flush();          expect(select.val()).toEqual('0');          select.val('1'); @@ -907,7 +917,7 @@ describe("widget", function(){          scope.values = [{name:'A'}, {name:'B'}];          scope.selected = scope.values[0];          scope.count = 0; -        scope.$eval(); +        scope.$flush();          expect(scope.count).toEqual(0);          select.val('1'); @@ -924,7 +934,7 @@ describe("widget", 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.$eval(); +        scope.$flush();          expect(select.val()).toEqual('0');          select.val('1'); @@ -937,7 +947,7 @@ describe("widget", function(){          scope.values = [{name:'A'}, {name:'B'}];          scope.selected = scope.values[0];          select.val('0'); -        scope.$eval(); +        scope.$flush();          select.val('');          browserTrigger(select, 'change'); @@ -951,19 +961,19 @@ describe("widget", function(){          scope.values = [{name:'A'}, {name:'B'}];          scope.selected = []; -        scope.$eval(); +        scope.$flush();          expect(select.find('option').length).toEqual(2);          expect(jqLite(select.find('option')[0]).attr('selected')).toEqual(false);          expect(jqLite(select.find('option')[1]).attr('selected')).toEqual(false);          scope.selected.push(scope.values[1]); -        scope.$eval(); +        scope.$flush();          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.$eval(); +        scope.$flush();          expect(select.find('option').length).toEqual(2);          expect(select.find('option')[0].selected).toEqual(true);          expect(select.find('option')[1].selected).toEqual(true); @@ -974,7 +984,7 @@ describe("widget", function(){          scope.values = [{name:'A'}, {name:'B'}];          scope.selected = []; -        scope.$eval(); +        scope.$flush();          select.find('option')[0].selected = true;          browserTrigger(select, 'change'); @@ -991,24 +1001,30 @@ describe("widget", function(){        var scope = compile('<ul><li ng:repeat="item in items" ng:init="suffix = \';\'" ng:bind="item + suffix"></li></ul>');        Array.prototype.extraProperty = "should be ignored"; +      // INIT        scope.items = ['misko', 'shyam']; -      scope.$eval(); +      scope.$flush(); +      expect(element.find('li').length).toEqual(2);        expect(element.text()).toEqual('misko;shyam;');        delete Array.prototype.extraProperty; +      // GROW        scope.items = ['adam', 'kai', 'brad']; -      scope.$eval(); +      scope.$flush(); +      expect(element.find('li').length).toEqual(3);        expect(element.text()).toEqual('adam;kai;brad;'); +      // SHRINK        scope.items = ['brad']; -      scope.$eval(); +      scope.$flush(); +      expect(element.find('li').length).toEqual(1);        expect(element.text()).toEqual('brad;');      });      it('should ng:repeat over object', function(){        var scope = compile('<ul><li ng:repeat="(key, value) in items" ng:bind="key + \':\' + value + \';\' "></li></ul>'); -      scope.$set('items', {misko:'swe', shyam:'set'}); -      scope.$eval(); +      scope.items = {misko:'swe', shyam:'set'}; +      scope.$flush();        expect(element.text()).toEqual('misko:swe;shyam:set;');      }); @@ -1020,28 +1036,23 @@ describe("widget", function(){        var scope = compile('<ul><li ng:repeat="(key, value) in items" ng:bind="key + \':\' + value + \';\' "></li></ul>');        scope.items = new Class();        scope.items.name = 'value'; -      scope.$eval(); +      scope.$flush();        expect(element.text()).toEqual('name:value;');      });      it('should error on wrong parsing of ng:repeat', function(){ -      var scope = compile('<ul><li ng:repeat="i dont parse"></li></ul>'); - -      expect(scope.$service('$log').error.logs.shift()[0]). -        toEqualError("Expected ng:repeat in form of '_item_ in _collection_' but got 'i dont parse'."); - -      expect(scope.$element.attr('ng-exception')). -        toMatch(/Expected ng:repeat in form of '_item_ in _collection_' but got 'i dont parse'/); -      expect(scope.$element).toHaveClass('ng-exception'); +      expect(function(){ +        compile('<ul><li ng:repeat="i dont parse"></li></ul>'); +      }).toThrow("Expected ng:repeat in form of '_item_ in _collection_' but got 'i dont parse'."); -      dealoc(scope); +      $logMock.error.logs.shift();      });      it('should expose iterator offset as $index when iterating over arrays', function() {        var scope = compile('<ul><li ng:repeat="item in items" ' +                                    'ng:bind="item + $index + \'|\'"></li></ul>');        scope.items = ['misko', 'shyam', 'frodo']; -      scope.$eval(); +      scope.$flush();        expect(element.text()).toEqual('misko0|shyam1|frodo2|');      }); @@ -1049,7 +1060,7 @@ describe("widget", function(){        var scope = compile('<ul><li ng:repeat="(key, val) in items" ' +                                    'ng:bind="key + \':\' + val + $index + \'|\'"></li></ul>');        scope.items = {'misko':'m', 'shyam':'s', 'frodo':'f'}; -      scope.$eval(); +      scope.$flush();        expect(element.text()).toEqual('misko:m0|shyam:s1|frodo:f2|');      }); @@ -1057,16 +1068,16 @@ describe("widget", function(){        var scope = compile('<ul><li ng:repeat="item in items" ' +                                    'ng:bind="item + \':\' + $position + \'|\'"></li></ul>');        scope.items = ['misko', 'shyam', 'doug']; -      scope.$eval(); +      scope.$flush();        expect(element.text()).toEqual('misko:first|shyam:middle|doug:last|');        scope.items.push('frodo'); -      scope.$eval(); +      scope.$flush();        expect(element.text()).toEqual('misko:first|shyam:middle|doug:middle|frodo:last|');        scope.items.pop();        scope.items.pop(); -      scope.$eval(); +      scope.$flush();        expect(element.text()).toEqual('misko:first|shyam:last|');      }); @@ -1074,12 +1085,12 @@ describe("widget", function(){        var scope = compile('<ul><li ng:repeat="(key, val) in items" ' +                                    'ng:bind="key + \':\' + val + \':\' + $position + \'|\'"></li></ul>');        scope.items = {'misko':'m', 'shyam':'s', 'doug':'d', 'frodo':'f'}; -      scope.$eval(); +      scope.$flush();        expect(element.text()).toEqual('misko:m:first|shyam:s:middle|doug:d:middle|frodo:f:last|');        delete scope.items.doug;        delete scope.items.frodo; -      scope.$eval(); +      scope.$flush();        expect(element.text()).toEqual('misko:m:first|shyam:s:last|');      });    }); @@ -1089,8 +1100,8 @@ describe("widget", function(){      it('should prevent compilation of the owning element and its children', function(){        var scope = compile('<div ng:non-bindable><span ng:bind="name"></span></div>'); -      scope.$set('name', 'misko'); -      scope.$eval(); +      scope.name =  'misko'; +      scope.$digest();        expect(element.text()).toEqual('');      });    }); @@ -1113,7 +1124,7 @@ describe("widget", function(){      it('should do nothing when no routes are defined', function() {        $location.updateHash('/unknown'); -      rootScope.$eval(); +      rootScope.$digest();        expect(rootScope.$element.text()).toEqual('');      }); @@ -1126,13 +1137,15 @@ describe("widget", function(){        $location.updateHash('/foo');        $browser.xhr.expectGET('myUrl1').respond('<div>{{1+3}}</div>'); -      rootScope.$eval(); +      rootScope.$digest(); +      rootScope.$flush();        $browser.xhr.flush();        expect(rootScope.$element.text()).toEqual('4');        $location.updateHash('/bar');        $browser.xhr.expectGET('myUrl2').respond('angular is da best'); -      rootScope.$eval(); +      rootScope.$digest(); +      rootScope.$flush();        $browser.xhr.flush();        expect(rootScope.$element.text()).toEqual('angular is da best');      }); @@ -1142,12 +1155,14 @@ describe("widget", function(){        $location.updateHash('/foo');        $browser.xhr.expectGET('myUrl1').respond('<div>{{1+3}}</div>'); -      rootScope.$eval(); +      rootScope.$digest(); +      rootScope.$flush();        $browser.xhr.flush();        expect(rootScope.$element.text()).toEqual('4');        $location.updateHash('/unknown'); -      rootScope.$eval(); +      rootScope.$digest(); +      rootScope.$flush();        expect(rootScope.$element.text()).toEqual('');      }); @@ -1157,16 +1172,20 @@ describe("widget", function(){        $location.updateHash('/foo');        $browser.xhr.expectGET('myUrl1').respond('<div>{{parentVar}}</div>'); -      rootScope.$eval(); +      rootScope.$digest(); +      rootScope.$flush();        $browser.xhr.flush();        expect(rootScope.$element.text()).toEqual('parent');        rootScope.parentVar = 'new parent'; -      rootScope.$eval(); +      rootScope.$digest(); +      rootScope.$flush();        expect(rootScope.$element.text()).toEqual('new parent');      });      it('should be possible to nest ng:view in ng:include', function() { +      dealoc(rootScope); // we are about to override it. +        var myApp = angular.scope();        var $browser = myApp.$service('$browser');        $browser.xhr.expectGET('includePartial.html').respond('view: <ng:view></ng:view>'); @@ -1175,13 +1194,14 @@ describe("widget", function(){        var $route = myApp.$service('$route');        $route.when('/foo', {controller: angular.noop, template: 'viewPartial.html'}); -      dealoc(rootScope); // we are about to override it.        rootScope = angular.compile(            '<div>' +              'include: <ng:include src="\'includePartial.html\'">' +            '</ng:include></div>')(myApp); +      rootScope.$apply();        $browser.xhr.expectGET('viewPartial.html').respond('content'); +      rootScope.$flush();        $browser.xhr.flush();        expect(rootScope.$element.text()).toEqual('include: view: content'); @@ -1211,21 +1231,21 @@ describe("widget", function(){            respond('<div ng:init="log.push(\'init\')">' +                      '<div ng:controller="ChildCtrl"></div>' +                    '</div>'); -      rootScope.$eval(); +      rootScope.$apply();        $browser.xhr.flush(); -      expect(rootScope.log).toEqual(['parent', 'init', 'child']); +      expect(rootScope.log).toEqual(['parent', 'child', 'init']);        $location.updateHash(''); -      rootScope.$eval(); -      expect(rootScope.log).toEqual(['parent', 'init', 'child']); +      rootScope.$apply(); +      expect(rootScope.log).toEqual(['parent', 'child', 'init']);        rootScope.log = [];        $location.updateHash('/foo'); -      rootScope.$eval(); +      rootScope.$apply();        $browser.defer.flush(); -      expect(rootScope.log).toEqual(['parent', 'init', 'child']); +      expect(rootScope.log).toEqual(['parent', 'child', 'init']);      });    });  });  | 
