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']); }); }); }); |
