diff options
| author | Misko Hevery | 2011-08-10 13:15:43 -0700 | 
|---|---|---|
| committer | Misko Hevery | 2011-08-12 15:47:47 -0700 | 
| commit | 42062dab34192d2cb9ed66a720c0f791408c61c0 (patch) | |
| tree | ca85b56f12dd0138dbe3d7f1346c4125d64e09a5 | |
| parent | 1c9fc1e1dec67c8c05f02da1e0853439238c4d8e (diff) | |
| download | angular.js-42062dab34192d2cb9ed66a720c0f791408c61c0.tar.bz2 | |
refactor(scope): remove $flush/$observe ng:eval/ng:eval-order
35 files changed, 265 insertions, 987 deletions
| diff --git a/CHANGELOG.md b/CHANGELOG.md index 65ca238c..d2c3704e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,9 @@  - $route.onChange() callback (http://docs.angularjs.org/#!angular.service.$route)    no longer has this bound.  - Removed undocumented $config in root scope. (You should have not been depending on this.) +- removed $flush()/$observe on scope +- removed ng:eval/ng:eval-order since it is incompatible with $digest phase +- ng:init and ng:controllers are now called in the order of declaration in HTML @@ -27,7 +27,6 @@ ANGULAR = [    'src/service/log.js',    'src/service/resource.js',    'src/service/route.js', -  'src/service/updateView.js',    'src/service/window.js',    'src/service/xhr.bulk.js',    'src/service/xhr.cache.js', diff --git a/docs/src/templates/docs.js b/docs/src/templates/docs.js index de6130dc..b31a748d 100644 --- a/docs/src/templates/docs.js +++ b/docs/src/templates/docs.js @@ -27,7 +27,7 @@ function DocsController($location, $browser, $window, $cookies) {        var i = self.pages.length;        while (i--) {          if (self.pages[i].id == self.partialId) { -          self.partialTitle = self.pages[i].name +          self.partialTitle = self.pages[i].name;            break;          }        } @@ -36,7 +36,7 @@ function DocsController($location, $browser, $window, $cookies) {          delete self.partialId;        }      } -  })(); +  });    this.getUrl = function(page){      return '#!/' + page.section + '/' + page.id; diff --git a/jsTestDriver-coverage.conf b/jsTestDriver-coverage.conf index 8399a9f6..de7f8536 100644 --- a/jsTestDriver-coverage.conf +++ b/jsTestDriver-coverage.conf @@ -30,7 +30,6 @@ load:    - src/service/log.js    - src/service/resource.js    - src/service/route.js -  - src/service/updateView.js    - src/service/window.js    - src/service/xhr.bulk.js    - src/service/xhr.cache.js diff --git a/jsTestDriver-jquery.conf b/jsTestDriver-jquery.conf index a31d5b72..7cadc3aa 100644 --- a/jsTestDriver-jquery.conf +++ b/jsTestDriver-jquery.conf @@ -30,7 +30,6 @@ load:    - src/service/log.js    - src/service/resource.js    - src/service/route.js -  - src/service/updateView.js    - src/service/window.js    - src/service/xhr.bulk.js    - src/service/xhr.cache.js diff --git a/jsTestDriver.conf b/jsTestDriver.conf index ba893777..57ddae32 100644 --- a/jsTestDriver.conf +++ b/jsTestDriver.conf @@ -30,7 +30,6 @@ load:    - src/service/log.js    - src/service/resource.js    - src/service/route.js -  - src/service/updateView.js    - src/service/window.js    - src/service/xhr.bulk.js    - src/service/xhr.cache.js diff --git a/src/Angular.js b/src/Angular.js index d698aa11..1b887779 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -77,10 +77,6 @@ var _undefined        = undefined,      NG_EXCEPTION      = 'ng-exception',      NG_VALIDATION_ERROR = 'ng-validation-error',      NOOP              = 'noop', -    PRIORITY_FIRST    = -99999, -    PRIORITY_WATCH    = -1000, -    PRIORITY_LAST     =  99999, -    PRIORITY          = {'FIRST': PRIORITY_FIRST, 'LAST': PRIORITY_LAST, 'WATCH':PRIORITY_WATCH},      Error             = window.Error,      /** holds major version number for IE or NaN for real browsers */      msie              = parseInt((/msie (\d+)/.exec(lowercase(navigator.userAgent)) || [])[1], 10), diff --git a/src/Compiler.js b/src/Compiler.js index 8512f0c3..98e9630c 100644 --- a/src/Compiler.js +++ b/src/Compiler.js @@ -6,44 +6,26 @@   * bind to a new instance of elements. It also provides a list   * of child paths which contain child templates   */ -function Template(priority) { +function Template() {    this.paths = [];    this.children = []; -  this.inits = []; -  this.priority = priority; +  this.linkFns = [];    this.newScope = false;  }  Template.prototype = { -  attach: function(element, scope) { -    var inits = {}; -    this.collectInits(element, inits, scope); -    forEachSorted(inits, function(queue){ -      forEach(queue, function(fn) {fn();}); -    }); -  }, - -  collectInits: function(element, inits, scope) { -    var queue = inits[this.priority], childScope = scope; -    if (!queue) { -      inits[this.priority] = queue = []; -    } +  link: function(element, scope) { +    var childScope = scope;      if (this.newScope) {        childScope = isFunction(this.newScope) ? scope.$new(this.newScope(scope)) : scope.$new();        element.data($$scope, childScope);      } -    // TODO(misko): refactor this!!! -    // Why are inits even here? -    forEach(this.inits, function(fn) { -      queue.push(function() { -        childScope.$eval(function(){ -          try { -            return childScope.$service.invoke(childScope, fn, [element]); -          } catch (e) { -            childScope.$service('$exceptionHandler')(e); -          } -        }); -      }); +    forEach(this.linkFns, function(fn) { +      try { +        childScope.$service.invoke(childScope, fn, [element]); +      } catch (e) { +        childScope.$service('$exceptionHandler')(e); +      }      });      var i,          childNodes = element[0].childNodes, @@ -51,16 +33,16 @@ Template.prototype = {          paths = this.paths,          length = paths.length;      for (i = 0; i < length; i++) { -      children[i].collectInits(jqLite(childNodes[paths[i]]), inits, childScope); +      children[i].link(jqLite(childNodes[paths[i]]), childScope);      }    }, -  addInit:function(linkingFn) { +  addLinkFn:function(linkingFn) {      if (linkingFn) {        if (!linkingFn.$inject)          linkingFn.$inject = []; -      this.inits.push(linkingFn); +      this.linkFns.push(linkingFn);      }    }, @@ -73,7 +55,7 @@ Template.prototype = {    },    empty: function() { -    return this.inits.length === 0 && this.paths.length === 0; +    return this.linkFns.length === 0 && this.paths.length === 0;    }  }; @@ -211,7 +193,7 @@ Compiler.prototype = {          }        }      } -    template = this.templatize(templateElement, index, 0) || new Template(); +    template = this.templatize(templateElement, index) || new Template();      return function(scope, cloneConnectFn){        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart        // and sometimes changes the structure of the DOM. @@ -222,69 +204,12 @@ Compiler.prototype = {        element.data($$scope, scope);        scope.$element = element;        (cloneConnectFn||noop)(element, scope); -      template.attach(element, scope); +      template.link(element, scope);        return scope;      };    }, - -  /** -   * @workInProgress -   * @ngdoc directive -   * @name angular.directive.ng:eval-order -   * @deprecated -   * -   * @description -   * Normally the view is updated from top to bottom. This usually is -   * not a problem, but under some circumstances the values for data -   * is not available until after the full view is computed. If such -   * values are needed before they are computed the order of -   * evaluation can be changed using ng:eval-order -   * -   * @element ANY -   * @param {integer|string=} [priority=0] priority integer, or FIRST, LAST constant -   * -   * @example -   * try changing the invoice and see that the Total will lag in evaluation -   * @example -     <doc:example> -       <doc:source> -        <div>TOTAL: without ng:eval-order {{ total | currency }}</div> -        <div ng:eval-order='LAST'>TOTAL: with ng:eval-order {{ total | currency }}</div> -        <table ng:init="items=[{qty:1, cost:9.99, desc:'gadget'}];total=0;"> -          <tr> -            <td>QTY</td> -            <td>Description</td> -            <td>Cost</td> -            <td>Total</td> -            <td></td> -          </tr> -          <tr ng:repeat="item in items"> -            <td><input name="item.qty"/></td> -            <td><input name="item.desc"/></td> -            <td><input name="item.cost"/></td> -            <td>{{item.qty * item.cost | currency}}</td> -            <td><a href="" ng:click="items.$remove(item)">X</a></td> -          </tr> -          <tr> -            <td colspan="3"><a href="" ng:click="items.$add()">add</a></td> -            <td>{{ total = items.$sum('qty*cost') | currency }}</td> -          </tr> -        </table> -       </doc:source> -       <doc:scenario> -         it('should check ng:format', function(){ -           expect(using('.doc-example-live div:first').binding("total")).toBe('$0.00'); -           expect(using('.doc-example-live div:last').binding("total")).toBe('$9.99'); -           input('item.qty').enter('2'); -           expect(using('.doc-example-live div:first').binding("total")).toBe('$9.99'); -           expect(using('.doc-example-live div:last').binding("total")).toBe('$19.98'); -         }); -       </doc:scenario> -     </doc:example> -   */ - -  templatize: function(element, elementIndex, priority){ +  templatize: function(element, elementIndex){      var self = this,          widget,          fn, @@ -300,17 +225,8 @@ Compiler.prototype = {            directives: function(value){ if(isDefined(value)) directives = value; return directives;},            scope: function(value){ if(isDefined(value)) template.newScope = template.newScope || value; return template.newScope;}          }; -    try { -      priority = element.attr('ng:eval-order') || priority || 0; -    } catch (e) { -      // for some reason IE throws error under some weird circumstances. so just assume nothing -      priority = priority || 0; -    }      element.addClass(elementNamespace); -    if (isString(priority)) { -      priority = PRIORITY[uppercase(priority)] || parseInt(priority, 10); -    } -    template = new Template(priority); +    template = new Template();      eachAttribute(element, function(value, name){        if (!widget) {          if (widget = self.widgets('@' + name)) { @@ -330,7 +246,7 @@ Compiler.prototype = {        descend = false;        directives = false;        var parent = element.parent(); -      template.addInit(widget.call(selfApi, element)); +      template.addLinkFn(widget.call(selfApi, element));        if (parent && parent[0]) {          element = jqLite(parent[0].childNodes[elementIndex]);        } @@ -361,14 +277,14 @@ Compiler.prototype = {          fn = directiveFns[name];          if (fn) {            element.addClass('ng-directive'); -          template.addInit((directiveFns[name]).call(selfApi, value, element)); +          template.addLinkFn((directiveFns[name]).call(selfApi, value, element));          }        });      }      // Process non text child nodes      if (descend) {        eachNode(element, function(child, i){ -        template.addChild(i, self.templatize(child, i, priority)); +        template.addChild(i, self.templatize(child, i));        });      }      return template.empty() ? null : template; diff --git a/src/Scope.js b/src/Scope.js index 370c4bec..bd402744 100644 --- a/src/Scope.js +++ b/src/Scope.js @@ -93,7 +93,7 @@ function createScope(providers, instanceCache) {   */  function Scope() {    this.$id = nextUid(); -  this.$$phase = this.$parent = this.$$watchers = this.$$observers = +  this.$$phase = this.$parent = this.$$watchers =      this.$$nextSibling = this.$$childHead = this.$$childTail = null;    this['this'] = this.$root =  this;  } @@ -145,7 +145,7 @@ Scope.prototype = {     * @description     * Creates a new child {@link angular.scope scope}. The new scope can optionally behave as a     * controller. The parent scope will propagate the {@link angular.scope.$digest $digest()} and -   * {@link angular.scope.$flush $flush()} events. The scope can be removed from the scope +   * {@link angular.scope.$digest $digest()} events. The scope can be removed from the scope     * hierarchy using {@link angular.scope.$destroy $destroy()}.     *     * {@link angular.scope.$destroy $destroy()} must be called on a scope when it is desired for @@ -168,7 +168,7 @@ Scope.prototype = {      child['this'] = child;      child.$parent = this;      child.$id = nextUid(); -    child.$$phase = child.$$watchers = child.$$observers = +    child.$$phase = child.$$watchers =        child.$$nextSibling = child.$$childHead = child.$$childTail = null;      if (this.$$childHead) {        this.$$childTail.$$nextSibling = child; @@ -207,76 +207,15 @@ Scope.prototype = {     *   {@link angular.copy} function is used. It also means that watching complex options will     *   have adverse memory and performance implications.     * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This -   *   is achieving my rerunning the watchers until no changes are detected. The rerun iteration +   *   is achieved by rerunning the watchers until no changes are detected. The rerun iteration     *   limit is 100 to prevent infinity loop deadlock.     * -   * # When to use `$watch`? -   * -   * The `$watch` should be used from within controllers to listen on properties *immediately* after -   * a stimulus is applied to the system (see {@link angular.scope.$apply $apply()}). This is in -   * contrast to {@link angular.scope.$observe $observe()} which is used from within the directives -   * and which gets applied at some later point in time. In addition -   * {@link angular.scope.$observe $observe()} must not modify the model.     *     * If you want to be notified whenever {@link angular.scope.$digest $digest} is called,     * you can register an `watchExpression` function with no `listener`. (Since `watchExpression`,     * can execute multiple times per {@link angular.scope.$digest $digest} cycle when a change is     * detected, be prepared for multiple calls to your listener.)     * -   * # `$watch` vs `$observe` -   * -   * <table class="table"> -   *   <tr> -   *     <th></td> -   *     <th>{@link angular.scope.$watch $watch()}</th> -   *     <th>{@link angular.scope.$observe $observe()}</th> -   *   </tr> -   *   <tr><th colspan="3" class="section">When to use it?</th></tr> -   *   <tr> -   *     <th>Purpose</th> -   *     <td>Application behavior (including further model mutation) in response to a model -   *         mutation.</td> -   *     <td>Update the DOM in response to a model mutation.</td> -   *   </tr> -   *   <tr> -   *     <th>Used from</th> -   *     <td>{@link angular.directive.ng:controller controller}</td> -   *     <td>{@link angular.directive directives}</td> -   *   </tr> -   *   <tr><th colspan="3" class="section">What fires listeners?</th></tr> -   *   <tr> -   *     <th>Directly</th> -   *     <td>{@link angular.scope.$digest $digest()}</td> -   *     <td>{@link angular.scope.$flush $flush()}</td> -   *   </tr> -   *   <tr> -   *     <th>Indirectly via {@link angular.scope.$apply $apply()}</th> -   *     <td>{@link angular.scope.$apply $apply} calls -   *         {@link angular.scope.$digest $digest()} after apply argument executes.</td> -   *     <td>{@link angular.scope.$apply $apply} schedules -   *         {@link angular.scope.$flush $flush()} at some future time via -   *         {@link angular.service.$updateView $updateView}</td> -   *   </tr> -   *   <tr><th colspan="3" class="section">API contract</th></tr> -   *   <tr> -   *     <th>Model mutation</th> -   *     <td>allowed: detecting mutations requires one or mare calls to `watchExpression' per -   *         {@link angular.scope.$digest $digest()} cycle</td> -   *     <td>not allowed: called once per {@link angular.scope.$flush $flush()} must be -   *         {@link http://en.wikipedia.org/wiki/Idempotence idempotent} -   *         (function without side-effects which can be called multiple times.)</td> -   *   </tr> -   *   <tr> -   *     <th>Initial Value</th> -   *     <td>uses the current value of `watchExpression` as the initial value. Does not fire on -   *         initial call to {@link angular.scope.$digest $digest()}, unless `watchExpression` has -   *         changed form the initial value.</td> -   *     <td>fires on first run of {@link angular.scope.$flush $flush()} regardless of value of -   *         `observeExpression`</td> -   *   </tr> -   * </table> -   * -   *     *     * # Example       <pre> @@ -311,8 +250,6 @@ Scope.prototype = {     *    - `string`: Evaluated as {@link guide/dev_guide.expressions expression}     *    - `function(scope, newValue, oldValue)`: called with current `scope` an previous and     *       current values as parameters. -   * @returns {function()} a function which will call the `listener` with apprariate arguments. -   *    Useful for forcing initialization of listener.     */    $watch: function(watchExp, listener) {      var scope = this; @@ -326,15 +263,9 @@ Scope.prototype = {      // the while loop reads in reverse order.      array.unshift({        fn: listenFn, -      last: copy(get(scope)), +      last: Number.NaN, // NaN !== NaN. We used this to force $watch to fire on first run.        get: get      }); -    // we only return the initialization function for $watch (not for $observe), since creating -    // function cost time and memory, and $observe functions do not need it. -    return function() { -      var value = get(scope); -      listenFn(scope, value, value); -    };    },    /** @@ -369,15 +300,15 @@ Scope.prototype = {         scope.counter = 0;         expect(scope.counter).toEqual(0); -       scope.$flush('name', function(scope, newValue, oldValue) { counter = counter + 1; }); +       scope.$digest('name', function(scope, newValue, oldValue) { counter = counter + 1; });         expect(scope.counter).toEqual(0); -       scope.$flush(); +       scope.$digest();         // no variable change         expect(scope.counter).toEqual(0);         scope.name = 'adam'; -       scope.$flush(); +       scope.$digest();         expect(scope.counter).toEqual(1);       </pre>     * @@ -432,222 +363,14 @@ Scope.prototype = {    /**     * @workInProgress     * @ngdoc function -   * @name angular.scope.$observe -   * @function -   * -   * @description -   * Registers a `listener` callback to be executed during the {@link angular.scope.$flush $flush()} -   * phase when the `observeExpression` changes.. -   * -   * - The `observeExpression` is called on every call to {@link angular.scope.$flush $flush()} and -   *   should return the value which will be observed. -   * - The `listener` is called only when the value from the current `observeExpression` and the -   *   previous call to `observeExpression' are not equal. The inequality is determined according to -   *   {@link angular.equals} function. To save the value of the object for later comparison -   *   {@link angular.copy} function is used. It also means that watching complex options will -   *   have adverse memory and performance implications. -   * -   * # When to use `$observe`? -   * -   * {@link angular.scope.$observe $observe()} is used from within directives and gets applied at -   * some later point in time. Addition {@link angular.scope.$observe $observe()} must not -   * modify the model. This is in contrast to {@link angular.scope.$watch $watch()} which should be -   * used from within controllers to trigger a callback *immediately* after a stimulus is applied -   * to the system (see {@link angular.scope.$apply $apply()}). -   * -   * If you want to be notified whenever {@link angular.scope.$flush $flush} is called, -   * you can register an `observeExpression` function with no `listener`. -   * -   * -   * # `$watch` vs `$observe` -   * -   * <table class="table"> -   *   <tr> -   *     <th></td> -   *     <th>{@link angular.scope.$watch $watch()}</th> -   *     <th>{@link angular.scope.$observe $observe()}</th> -   *   </tr> -   *   <tr><th colspan="3" class="section">When to use it?</th></tr> -   *   <tr> -   *     <th>Purpose</th> -   *     <td>Application behavior (including further model mutation) in response to a model -   *         mutation.</td> -   *     <td>Update the DOM in response to a model mutation.</td> -   *   </tr> -   *   <tr> -   *     <th>Used from</th> -   *     <td>{@link angular.directive.ng:controller controller}</td> -   *     <td>{@link angular.directive directives}</td> -   *   </tr> -   *   <tr><th colspan="3" class="section">What fires listeners?</th></tr> -   *   <tr> -   *     <th>Directly</th> -   *     <td>{@link angular.scope.$digest $digest()}</td> -   *     <td>{@link angular.scope.$flush $flush()}</td> -   *   </tr> -   *   <tr> -   *     <th>Indirectly via {@link angular.scope.$apply $apply()}</th> -   *     <td>{@link angular.scope.$apply $apply} calls -   *         {@link angular.scope.$digest $digest()} after apply argument executes.</td> -   *     <td>{@link angular.scope.$apply $apply} schedules -   *         {@link angular.scope.$flush $flush()} at some future time via -   *         {@link angular.service.$updateView $updateView}</td> -   *   </tr> -   *   <tr><th colspan="3" class="section">API contract</th></tr> -   *   <tr> -   *     <th>Model mutation</th> -   *     <td>allowed: detecting mutations requires one or mare calls to `watchExpression' per -   *         {@link angular.scope.$digest $digest()} cycle</td> -   *     <td>not allowed: called once per {@link angular.scope.$flush $flush()} must be -   *         {@link http://en.wikipedia.org/wiki/Idempotence idempotent} -   *         (function without side-effects which can be called multiple times.)</td> -   *   </tr> -   *   <tr> -   *     <th>Initial Value</th> -   *     <td>uses the current value of `watchExpression` as the initial value. Does not fire on -   *         initial call to {@link angular.scope.$digest $digest()}, unless `watchExpression` has -   *         changed form the initial value.</td> -   *     <td>fires on first run of {@link angular.scope.$flush $flush()} regardless of value of -   *         `observeExpression`</td> -   *   </tr> -   * </table> -   * -   * # Example -     <pre> -       var scope = angular.scope(); -       scope.name = 'misko'; -       scope.counter = 0; - -       expect(scope.counter).toEqual(0); -       scope.$flush('name', function(scope, newValue, oldValue) { counter = counter + 1; }); -       expect(scope.counter).toEqual(0); - -       scope.$flush(); -       // no variable change -       expect(scope.counter).toEqual(0); - -       scope.name = 'adam'; -       scope.$flush(); -       expect(scope.counter).toEqual(1); -     </pre> -   * -   * @param {(function()|string)} observeExpression Expression that is evaluated on each -   *    {@link angular.scope.$flush $flush} cycle. A change in the return value triggers a -   *    call to the `listener`. -   * -   *    - `string`: Evaluated as {@link guide/dev_guide.expressions expression} -   *    - `function(scope)`: called with current `scope` as a parameter. -   * @param {(function()|string)=} listener Callback called whenever the return value of -   *   the `observeExpression` changes. -   * -   *    - `string`: Evaluated as {@link guide/dev_guide.expressions expression} -   *    - `function(scope, newValue, oldValue)`: called with current `scope` an previous and -   *       current values as parameters. -   */ -  $observe: function(watchExp, listener) { -    var array = this.$$observers; - -    if (!array) { -      array = this.$$observers = []; -    } -    // we use unshift since we use a while loop in $flush for speed. -    // the while loop reads in reverse order. -    array.unshift({ -      fn: compileToFn(listener || noop, 'listener'), -      last: NaN, -      get:  compileToFn(watchExp, 'watch') -    }); -  }, - -  /** -   * @workInProgress -   * @ngdoc function -   * @name angular.scope.$flush -   * @function -   * -   * @description -   * Process all of the {@link angular.scope.$observe observers} of the current scope -   * and its children. -   * -   * Usually you don't call `$flush()` directly in -   * {@link angular.directive.ng:controller controllers} or in {@link angular.directive directives}. -   * Instead a call to {@link angular.scope.$apply $apply()} (typically from within a -   * {@link angular.directive directive}) will scheduled a call to `$flush()` (with the -   * help of the {@link angular.service.$updateView $updateView} service). -   * -   * If you want to be notified whenever `$flush()` is called, -   * you can register a `observeExpression` function  with {@link angular.scope.$observe $observe()} -   * with no `listener`. -   * -   * You may have a need to call `$flush()` from within unit-tests, to simulate the scope -   * life-cycle. -   * -   * # Example -     <pre> -       var scope = angular.scope(); -       scope.name = 'misko'; -       scope.counter = 0; - -       expect(scope.counter).toEqual(0); -       scope.$flush('name', function(scope, newValue, oldValue) { counter = counter + 1; }); -       expect(scope.counter).toEqual(0); - -       scope.$flush(); -       // no variable change -       expect(scope.counter).toEqual(0); - -       scope.name = 'adam'; -       scope.$flush(); -       expect(scope.counter).toEqual(1); -     </pre> -   * -   */ -  $flush: function() { -    var observers = this.$$observers, -        child, -        length, -        observer, value, last; - -    if (this.$$phase) { -      throw Error(this.$$phase + ' already in progress'); -    } -    this.$$phase = '$flush'; -    if (observers) { -      // process our watches -      length = observers.length; -      while (length--) { -        try { -          observer = observers[length]; -          // Most common watches are on primitives, in which case we can short -          // circuit it with === operator, only when === fails do we use .equals -          if ((value = observer.get(this)) !== (last = observer.last) && !equals(value, last)) { -            observer.fn(this, observer.last = copy(value), last); -          } -        } catch (e){ -          this.$service('$exceptionHandler')(e); -        } -      } -    } -    // observers can create new children -    child = this.$$childHead; -    while(child) { -      child.$flush(); -      child = child.$$nextSibling; -    } -    this.$$phase = null; -  }, - -  /** -   * @workInProgress -   * @ngdoc function     * @name angular.scope.$destroy     * @function     *     * @description     * Remove the current scope (and all of its children) from the parent scope. Removal implies -   * that calls to {@link angular.scope.$digest $digest()} and -   * {@link angular.scope.$flush $flush()} will no longer propagate to the current scope and its -   * children. Removal also implies that the current scope is eligible for garbage collection. +   * that calls to {@link angular.scope.$digest $digest()} will no longer propagate to the current +   * scope and its children. Removal also implies that the current scope is eligible for garbage +   * collection.     *     * The `$destroy()` is usually used by directives such as     * {@link angular.widget.@ng:repeat ng:repeat} for managing the unrolling of the loop. @@ -726,9 +449,7 @@ Scope.prototype = {     * (For example from browser DOM events, setTimeout, XHR or third party libraries).     * Because we are calling into the angular framework we need to perform proper scope life-cycle     * of {@link angular.service.$exceptionHandler exception handling}, -   * {@link angular.scope.$digest executing watches} and scheduling -   * {@link angular.service.$updateView updating of the view} which in turn -   * {@link angular.scope.$digest executes observers} to update the DOM. +   * {@link angular.scope.$digest executing watches}.     *     * ## Life cycle     * @@ -740,7 +461,6 @@ Scope.prototype = {            $exceptionHandler(e);          } finally {            $root.$digest(); -          $updateView();          }        }     * @@ -753,12 +473,6 @@ Scope.prototype = {     *    {@link angular.service.$exceptionHandler $exceptionHandler} service.     * 3. The {@link angular.scope.$watch watch} listeners are fired immediately after the expression     *    was executed using the {@link angular.scope.$digest $digest()} method. -   * 4. A DOM update is scheduled using the {@link angular.service.$updateView $updateView} service. -   *    The `$updateView` may merge multiple update requests into a single update, if the requests -   *    are issued in close time proximity. -   * 6. The {@link angular.service.$updateView $updateView} service then fires DOM -   *    {@link angular.scope.$observe observers} using the {@link angular.scope.$flush $flush()} -   *    method.     *     *     * @param {(string|function())=} exp An angular expression to be executed. @@ -775,7 +489,6 @@ Scope.prototype = {        this.$service('$exceptionHandler')(e);      } finally {        this.$root.$digest(); -      this.$service('$updateView')();      }    }  }; diff --git a/src/angular-bootstrap.js b/src/angular-bootstrap.js index 9c95a158..7495b6ad 100644 --- a/src/angular-bootstrap.js +++ b/src/angular-bootstrap.js @@ -114,7 +114,6 @@               'service/log.js',               'service/resource.js',               'service/route.js', -             'service/updateView.js',               'service/window.js',               'service/xhr.bulk.js',               'service/xhr.cache.js', diff --git a/src/directives.js b/src/directives.js index 4712f250..dd292de8 100644 --- a/src/directives.js +++ b/src/directives.js @@ -28,9 +28,6 @@   * * {@link angular.directive.ng:click ng:click} - Executes custom behavior when element is clicked.   * * {@link angular.directive.ng:controller ng:controller} - Creates a scope object linked to the   * DOM element and assigns behavior to the scope. - * * {@link angular.directive.ng:eval ng:eval} - Executes a binding but blocks output. - * * {@link angular.directive.ng:eval-order ng:eval-order} - Change evaluation order when updating - * the view.   * * {@link angular.directive.ng:hide ng:hide} - Conditionally hides a portion of HTML.   * * {@link angular.directive.ng:href ng:href} - Places an href in the angular namespace.   * * {@link angular.directive.ng:init} - Initialization tasks run before a template is executed. @@ -177,54 +174,6 @@ angularDirective("ng:controller", function(expression){  /**   * @workInProgress - * @deprecated - * @ngdoc directive - * @name angular.directive.ng:eval - * - * @description - * The `ng:eval` allows you to execute a binding which has side effects - * without displaying the result to the user. - * - * @element ANY - * @param {expression} expression {@link guide/dev_guide.expressions Expression} to eval. - * - * @example - * Notice that `{{` `obj.multiplied = obj.a * obj.b` `}}` has a side effect of assigning - * a value to `obj.multiplied` and displaying the result to the user. Sometimes, - * however, it is desirable to execute a side effect without showing the value to - * the user. In such a case `ng:eval` allows you to execute code without updating - * the display. -   <doc:example> -     <doc:source> -       <input name="obj.a" value="6" > -         * <input name="obj.b" value="2"> -         = {{obj.multiplied = obj.a * obj.b}} <br> -       <span ng:eval="obj.divide = obj.a / obj.b"></span> -       <span ng:eval="obj.updateCount = 1 + (obj.updateCount||0)"> -       </span> -       <tt>obj.divide = {{obj.divide}}</tt><br> -       <tt>obj.updateCount = {{obj.updateCount}}</tt> -     </doc:source> -     <doc:scenario> -       it('should check eval', function(){ -         expect(binding('obj.divide')).toBe('3'); -         expect(binding('obj.updateCount')).toBe('1'); -         input('obj.a').enter('12'); -         expect(binding('obj.divide')).toBe('6'); -         expect(binding('obj.updateCount')).toBe('2'); -       }); -     </doc:scenario> -   </doc:example> - */ -// TODO(misko): remove me -angularDirective("ng:eval", function(expression){ -  return function(element){ -    this.$observe(expression); -  }; -}); - -/** - * @workInProgress   * @ngdoc directive   * @name angular.directive.ng:bind   * @@ -258,7 +207,7 @@ angularDirective("ng:bind", function(expression, element){    element.addClass('ng-binding');    return function(element) {      var lastValue = noop, lastError = noop; -    this.$observe(function(scope) { +    this.$watch(function(scope) {        // TODO(misko): remove error handling https://github.com/angular/angular.js/issues/347        var error, value, html, isHtml, isDomElement,            hadOwnElement = scope.hasOwnProperty('$element'), @@ -398,7 +347,7 @@ angularDirective("ng:bind-template", function(expression, element){    var templateFn = compileBindTemplate(expression);    return function(element) {      var lastValue; -    this.$observe(function(scope) { +    this.$watch(function(scope) {        var value = templateFn(scope, element, true);        if (value != lastValue) {          element.text(value); @@ -472,7 +421,7 @@ var REMOVE_ATTRIBUTES = {  angularDirective("ng:bind-attr", function(expression){    return function(element){      var lastValue = {}; -    this.$observe(function(scope){ +    this.$watch(function(scope){        var values = scope.$eval(expression);        for(var key in values) {          var value = compileBindTemplate(values[key])(scope, element), @@ -594,7 +543,7 @@ function ngClass(selector) {    return function(expression, element) {      var existing = element[0].className + ' ';      return function(element) { -      this.$observe(function(scope) { +      this.$watch(function(scope) {          if (selector(scope.$index)) {            var value = scope.$eval(expression);            if (isArray(value)) value = value.join(' '); @@ -756,7 +705,7 @@ angularDirective("ng:class-even", ngClass(function(i){return i % 2 === 1;}));   */  angularDirective("ng:show", function(expression, element){    return function(element){ -    this.$observe(expression, function(scope, value){ +    this.$watch(expression, function(scope, value){        toBoolean(value) ? element.show() : element.hide();      });    }; @@ -797,7 +746,7 @@ angularDirective("ng:show", function(expression, element){   */  angularDirective("ng:hide", function(expression, element){    return function(element){ -    this.$observe(expression, function(scope, value){ +    this.$watch(expression, function(scope, value){        toBoolean(value) ? element.hide() : element.show();      });    }; @@ -839,7 +788,7 @@ angularDirective("ng:hide", function(expression, element){  angularDirective("ng:style", function(expression, element){    return function(element){      var resetStyle = getStyle(element); -    this.$observe(function(scope){ +    this.$watch(function(scope){        var style = scope.$eval(expression) || {}, key, mergedStyle = {};        for(key in style) {          if (resetStyle[key] === undefined) resetStyle[key] = ''; diff --git a/src/filters.js b/src/filters.js index 52aafcf3..e423f590 100644 --- a/src/filters.js +++ b/src/filters.js @@ -435,18 +435,11 @@ angularFilter.date = function(date, format) {   * @example:     <doc:example>       <doc:source> -       <input type="text" name="objTxt" value="{a:1, b:[]}" -              ng:eval="obj = $eval(objTxt)"/> -       <pre>{{ obj | json }}</pre> +       <pre>{{ {'name':'value'} | json }}</pre>       </doc:source>       <doc:scenario>         it('should jsonify filtered objects', function() { -         expect(binding('obj | json')).toBe('{\n  "a":1,\n  "b":[]}'); -       }); - -       it('should update', function() { -         input('objTxt').enter('[1, 2, 3]'); -         expect(binding('obj | json')).toBe('[1,2,3]'); +         expect(binding('| json')).toBe('{\n  "name":"value"}');         });       </doc:scenario>     </doc:example> diff --git a/src/service/cookies.js b/src/service/cookies.js index 74e63679..220a6ed5 100644 --- a/src/service/cookies.js +++ b/src/service/cookies.js @@ -37,7 +37,7 @@ angularServiceInject('$cookies', function($browser) {    //at the end of each eval, push cookies    //TODO: this should happen before the "delayed" watches fire, because if some cookies are not    //      strings or browser refuses to store some cookies, we update the model in the push fn. -  this.$observe(push); +  this.$watch(push);    return cookies; diff --git a/src/service/defer.js b/src/service/defer.js index 0a69912c..1ea4bf0c 100644 --- a/src/service/defer.js +++ b/src/service/defer.js @@ -5,8 +5,6 @@   * @ngdoc service   * @name angular.service.$defer   * @requires $browser - * @requires $exceptionHandler - * @requires $updateView   *   * @description   * Delegates to {@link angular.service.$browser $browser.defer}, but wraps the `fn` function @@ -25,4 +23,4 @@ angularServiceInject('$defer', function($browser) {        scope.$apply(fn);      }, delay);    }; -}, ['$browser', '$exceptionHandler', '$updateView']); +}, ['$browser']); diff --git a/src/service/location.js b/src/service/location.js index 23531140..6e646b8b 100644 --- a/src/service/location.js +++ b/src/service/location.js @@ -91,7 +91,7 @@ angularServiceInject("$location", function($browser) {     * @description     * Updates the location object.     * Does not immediately update the browser -   * Browser is updated at the end of $flush() +   * Browser is updated at the end of $digest()     *     * Does not immediately update the browser. Instead the browser is updated at the end of $eval()     * cycle. diff --git a/src/service/route.js b/src/service/route.js index e1d0e7be..9b4db0dd 100644 --- a/src/service/route.js +++ b/src/service/route.js @@ -62,7 +62,7 @@        </doc:scenario>      </doc:example>   */ -angularServiceInject('$route', function($location, $updateView) { +angularServiceInject('$route', function($location) {    var routes = {},        onChange = [],        matcher = switchRouteMatcher, @@ -267,7 +267,7 @@ angularServiceInject('$route', function($location, $updateView) {    } -  this.$watch(function(){return dirty + $location.hash;}, updateRoute)(); +  this.$watch(function(){return dirty + $location.hash;}, updateRoute);    return $route; -}, ['$location', '$updateView']); +}, ['$location']); diff --git a/src/service/updateView.js b/src/service/updateView.js deleted file mode 100644 index b51e719b..00000000 --- a/src/service/updateView.js +++ /dev/null @@ -1,61 +0,0 @@ -'use strict'; - -/** - * @workInProgress - * @ngdoc service - * @name angular.service.$updateView - * @requires $browser - * - * @description - * Calling `$updateView` enqueues the eventual update of the view. (Update the DOM to reflect the - * model). The update is eventual, since there are often multiple updates to the model which may - * be deferred. The default update delayed is 25 ms. This means that the view lags the model by - * that time. (25ms is small enough that it is perceived as instantaneous by the user). The delay - * can be adjusted by setting the delay property of the service. - * - * <pre>angular.service('$updateView').delay = 10</pre> - * - * The delay is there so that multiple updates to the model which occur sufficiently close - * together can be merged into a single update. - * - * You don't usually call '$updateView' directly since angular does it for you in most cases, - * but there are some cases when you need to call it. - * - *  - `$updateView()` called automatically by angular: - *    - Your Application Controllers: Your controller code is called by angular and hence - *      angular is aware that you may have changed the model. - *    - Your Services: Your service is usually called by your controller code, hence same rules - *      apply. - *  - May need to call `$updateView()` manually: - *    - Widgets / Directives: If you listen to any DOM events or events on any third party - *      libraries, then angular is not aware that you may have changed state state of the - *      model, and hence you need to call '$updateView()' manually. - *    - 'setTimeout'/'XHR':  If you call 'setTimeout' (instead of {@link angular.service.$defer}) - *      or 'XHR' (instead of {@link angular.service.$xhr}) then you may be changing the model - *      without angular knowledge and you may need to call '$updateView()' directly. - * - * Note: if you wish to update the view immediately (without delay), you can do so by calling - * {@link angular.scope.$apply} at any time from your code: - * <pre>scope.$apply()</pre> - * - * In unit-test mode the update is instantaneous and synchronous to simplify writing tests. - * - */ - -function serviceUpdateViewFactory($browser){ -  var rootScope = this; -  var scheduled; -  function update(){ -    scheduled = false; -    rootScope.$flush(); -  } -  return $browser.isMock ? update : function(){ -    if (!scheduled) { -      scheduled = true; -      $browser.defer(update, serviceUpdateViewFactory.delay); -    } -  }; -} -serviceUpdateViewFactory.delay = 25; - -angularServiceInject('$updateView', serviceUpdateViewFactory, ['$browser']); diff --git a/src/service/xhr.bulk.js b/src/service/xhr.bulk.js index 816336f8..15bf0c83 100644 --- a/src/service/xhr.bulk.js +++ b/src/service/xhr.bulk.js @@ -82,6 +82,6 @@ angularServiceInject('$xhr.bulk', function($xhr, $error, $log){        }      });    }; -  this.$observe(bulkXHR.flush); +  this.$watch(bulkXHR.flush);    return bulkXHR;  }, ['$xhr', '$xhr.error', '$log']); diff --git a/src/service/xhr.js b/src/service/xhr.js index 224bc57a..bf882684 100644 --- a/src/service/xhr.js +++ b/src/service/xhr.js @@ -10,8 +10,6 @@   *                    in your tests   * @requires $xhr.error $xhr delegates all non `2xx` response code to this service.   * @requires $log $xhr delegates all exceptions to `$log.error()`. - * @requires $updateView After a server response the view needs to be updated for data-binding to - *           take effect.   *   * @description   * Generates an XHR request. The $xhr service delegates all requests to @@ -173,8 +171,8 @@       </doc:scenario>     </doc:example>   */ -angularServiceInject('$xhr', function($browser, $error, $log, $updateView){ - +angularServiceInject('$xhr', function($browser, $error, $log){ +  var rootScope = this;    var xhrHeaderDefaults = {      common: {        "Accept": "application/json, text/plain, */*", @@ -206,19 +204,19 @@ angularServiceInject('$xhr', function($browser, $error, $log, $updateView){              response = fromJson(response, true);            }          } -        if (200 <= code && code < 300) { -          success(code, response); -        } else if (isFunction(error)) { -          error(code, response); -        } else { -          $error( -            {method: method, url: url, data: post, success: success}, -            {status: code, body: response}); -        } +        rootScope.$apply(function(){ +          if (200 <= code && code < 300) { +              success(code, response); +          } else if (isFunction(error)) { +            error(code, response); +          } else { +            $error( +              {method: method, url: url, data: post, success: success}, +              {status: code, body: response}); +          } +        });        } catch (e) {          $log.error(e); -      } finally { -        $updateView();        }      }, extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},                xhrHeaderDefaults.common, @@ -228,4 +226,4 @@ angularServiceInject('$xhr', function($browser, $error, $log, $updateView){    xhr.defaults = {headers: xhrHeaderDefaults};    return xhr; -}, ['$browser', '$xhr.error', '$log', '$updateView']); +}, ['$browser', '$xhr.error', '$log']); diff --git a/src/validators.js b/src/validators.js index 6b54f67a..0a69a002 100644 --- a/src/validators.js +++ b/src/validators.js @@ -469,7 +469,6 @@ extend(angularValidator, {            $invalidWidgets.markValid(element);          }          element.data($$validate)(); -        scope.$service('$updateView')();        });      } else if (inputState.inFlight) {        // request in flight, mark widget invalid, but don't show it to user diff --git a/src/widgets.js b/src/widgets.js index 438fccb3..3d034fc5 100644 --- a/src/widgets.js +++ b/src/widgets.js @@ -548,7 +548,7 @@ function inputWidget(events, modelAccessor, viewAccessor, initFn, textBox) {          if (!equals(lastValue, value)) {            view.set(lastValue = value);          } -      })(); +      });      }    });  } @@ -773,7 +773,7 @@ angularWidget('select', function(element){        }      }); -    scope.$observe(function(scope) { +    scope.$watch(function(scope) {        var optionGroups = {'':[]}, // Temporary location for the option groups before we render them            optionGroupNames = [''],            optionGroupName, @@ -996,15 +996,15 @@ angularWidget('ng:include', function(element){            oldScope;        function incrementChange(){ changeCounter++;} -      this.$observe(srcExp, incrementChange); -      this.$observe(function(scope){ +      this.$watch(srcExp, incrementChange); +      this.$watch(function(scope){          var newScope = scope.$eval(scopeExp);          if (newScope !== oldScope) {            oldScope = newScope;            incrementChange();          }        }); -      this.$observe(function(){return changeCounter;}, function(scope) { +      this.$watch(function(){return changeCounter;}, function(scope) {          var src = scope.$eval(srcExp),              useScope = scope.$eval(scopeExp); @@ -1124,9 +1124,9 @@ angularWidget('ng:switch', function (element) {          childScope = scope.$new();          childScope.$eval(changeExpr);        } -    })(); +    }); -    this.$observe(function(){return changeCounter;}, function() { +    this.$watch(function(){return changeCounter;}, function() {        element.html('');        if (selectedTemplate) {          selectedTemplate(childScope, function(caseElement) { @@ -1251,7 +1251,7 @@ angularWidget('@ng:repeat', function(expression, element){      var childScopes = [];      var childElements = [iterStartElement];      var parentScope = this; -    this.$observe(function(scope){ +    this.$watch(function(scope){        var index = 0,            childCount = childScopes.length,            collection = scope.$eval(rhs), @@ -1285,11 +1285,11 @@ angularWidget('@ng:repeat', function(expression, element){              linker(childScope, function(clone){                clone.attr('ng:repeat-index', index);                fragment.appendChild(clone[0]); -              // TODO(misko): Temporary hack - maybe think about it - removed after we add fragment after $flush() -              // This causes double $flush for children +              // TODO(misko): Temporary hack - maybe think about it - removed after we add fragment after $digest() +              // This causes double $digest for children                // The first flush will couse a lot of DOM access (initial)                // Second flush shuld be noop since nothing has change hence no DOM access. -              childScope.$flush(); +              childScope.$digest();                childElements[index + 1] = clone;              });            } @@ -1300,7 +1300,7 @@ angularWidget('@ng:repeat', function(expression, element){        //attach new nodes buffered in doc fragment        if (addFragmentTo) {          // TODO(misko): For performance reasons, we should do the addition after all other widgets -        // have run. For this should happend after $flush() is done! +        // have run. For this should happend after $digest() is done!          addFragmentTo.after(jqLite(fragment));        } @@ -1429,7 +1429,7 @@ angularWidget('ng:view', function(element) {        })(); //initialize the state forcefully, it's possible that we missed the initial              //$route#onChange already -      this.$observe(function(){return changeCounter;}, function() { +      this.$watch(function(){return changeCounter;}, function() {          var template = $route.current && $route.current.template;          if (template) {            //xhr's callback must be async, see commit history for more info diff --git a/test/AngularSpec.js b/test/AngularSpec.js index abb34f3e..cbafa54c 100644 --- a/test/AngularSpec.js +++ b/test/AngularSpec.js @@ -551,7 +551,7 @@ describe('angular', function(){      it('should link to existing node and create scope', function(){        template = angular.element('<div>{{greeting = "hello world"}}</div>');        scope = angular.compile(template)(); -      scope.$flush(); +      scope.$digest();        expect(template.text()).toEqual('hello world');        expect(scope.greeting).toEqual('hello world');      }); @@ -560,7 +560,7 @@ describe('angular', function(){        scope = angular.scope();        template = angular.element('<div>{{greeting = "hello world"}}</div>');        angular.compile(template)(scope); -      scope.$flush(); +      scope.$digest();        expect(template.text()).toEqual('hello world');        expect(scope).toEqual(scope);      }); @@ -575,7 +575,7 @@ describe('angular', function(){        templateFn(scope, function(clone){          templateClone = clone;        }); -      scope.$flush(); +      scope.$digest();        expect(template.text()).toEqual('');        expect(scope.$element.text()).toEqual('hello world'); @@ -586,7 +586,7 @@ describe('angular', function(){      it('should link to cloned node and create scope', function(){        scope = angular.scope();        template = jqLite('<div>{{greeting = "hello world"}}</div>'); -      angular.compile(template)(scope, noop).$flush(); +      angular.compile(template)(scope, noop).$digest();        expect(template.text()).toEqual('');        expect(scope.$element.text()).toEqual('hello world');        expect(scope.greeting).toEqual('hello world'); diff --git a/test/BinderSpec.js b/test/BinderSpec.js index a84fe68a..ecfe0682 100644 --- a/test/BinderSpec.js +++ b/test/BinderSpec.js @@ -54,8 +54,8 @@ describe('Binder', function(){    });    it('BindUpdate', function(){ -    var scope = this.compile('<div ng:eval="a=123"/>'); -    scope.$flush(); +    var scope = this.compile('<div ng:init="a=123"/>'); +    scope.$digest();      assertEquals(123, scope.a);    }); @@ -284,6 +284,7 @@ describe('Binder', function(){      assertEquals(['ErrorMsg1'], errorLogs.shift());      scope.error['throw'] = function(){throw "MyError";}; +    errorLogs.length = 0;      scope.$apply();      span = childNode(doc, 0);      assertTrue(span.hasClass('ng-exception')); @@ -309,8 +310,9 @@ describe('Binder', function(){          'throw': function(){throw new Error("ErrorMsg" + (++count));}      };      scope.$apply(); -    expect(errorLogs.length).toMatch(1); +    expect(errorLogs.length).not.toEqual(0);      expect(errorLogs.shift()).toMatch(/ErrorMsg1/); +    errorLogs.length = 0;      scope.error['throw'] =  function(){ return 'X';};      scope.$apply(); diff --git a/test/CompilerSpec.js b/test/CompilerSpec.js index 90afbaff..8f86e99a 100644 --- a/test/CompilerSpec.js +++ b/test/CompilerSpec.js @@ -15,7 +15,7 @@ describe('compiler', function(){        observe: function(expression, element){          return function() { -          this.$observe(expression, function(scope, val){ +          this.$watch(expression, function(scope, val){              if (val)                log += ":" + val;            }); @@ -76,13 +76,13 @@ describe('compiler', function(){    it('should observe scope', function(){      scope = compile('<span observe="name">');      expect(log).toEqual(""); -    scope.$flush(); +    scope.$digest();      scope.name = 'misko'; -    scope.$flush(); -    scope.$flush(); +    scope.$digest(); +    scope.$digest();      scope.name = 'adam'; -    scope.$flush(); -    scope.$flush(); +    scope.$digest(); +    scope.$digest();      expect(log).toEqual(":misko:adam");    }); @@ -100,18 +100,21 @@ describe('compiler', function(){        element.removeAttr("duplicate");        var linker = this.compile(element);        return function(marker) { -        this.$observe(function() { +        this.$watch('value', function() {            var scope = linker(angular.scope(), noop);            marker.after(scope.$element);          });        };      };      scope = compile('before<span duplicate="expr">x</span>after'); -    scope.$flush(); +    scope.value = 1; +    scope.$digest();      expect(sortedHtml(scope.$element)).toEqual('<div>before<#comment></#comment><span>x</span>after</div>'); -    scope.$flush(); +    scope.value = 2; +    scope.$digest();      expect(sortedHtml(scope.$element)).toEqual('<div>before<#comment></#comment><span>x</span><span>x</span>after</div>'); -    scope.$flush(); +    scope.value = 3; +    scope.$digest();      expect(sortedHtml(scope.$element)).toEqual('<div>before<#comment></#comment><span>x</span><span>x</span><span>x</span>after</div>');    }); diff --git a/test/ScenarioSpec.js b/test/ScenarioSpec.js index ce8b0dec..e91e0b98 100644 --- a/test/ScenarioSpec.js +++ b/test/ScenarioSpec.js @@ -15,20 +15,20 @@ describe("ScenarioSpec: Compilation", function(){      it("should compile dom node and return scope", function(){        var node = jqLite('<div ng:init="a=1">{{b=a+1}}</div>')[0];        scope = angular.compile(node)(); -      scope.$flush(); +      scope.$digest();        expect(scope.a).toEqual(1);        expect(scope.b).toEqual(2);      });      it("should compile jQuery node and return scope", function(){        scope = compile(jqLite('<div>{{a=123}}</div>'))(); -      scope.$flush(); +      scope.$digest();        expect(jqLite(scope.$element).text()).toEqual('123');      });      it("should compile text node and return scope", function(){        scope = angular.compile('<div>{{a=123}}</div>')(); -      scope.$flush(); +      scope.$digest();        expect(jqLite(scope.$element).text()).toEqual('123');      });    }); diff --git a/test/ScopeSpec.js b/test/ScopeSpec.js index 6105df21..5a14abd6 100644 --- a/test/ScopeSpec.js +++ b/test/ScopeSpec.js @@ -5,9 +5,6 @@ describe('Scope', function(){    beforeEach(function(){      root = createScope(angular.service, { -      $updateView: function(){ -        root.$flush(); -      },        '$exceptionHandler': $exceptionHandlerMockFactory()      });      mockHandler = root.$service('$exceptionHandler'); @@ -108,6 +105,9 @@ describe('Scope', function(){      it('should watch and fire on simple property change', function(){        var spy = jasmine.createSpy();        root.$watch('name', spy); +      root.$digest(); +      spy.reset(); +        expect(spy).not.wasCalled();        root.$digest();        expect(spy).not.wasCalled(); @@ -120,6 +120,9 @@ describe('Scope', function(){      it('should watch and fire on expression change', function(){        var spy = jasmine.createSpy();        root.$watch('name.first', spy); +      root.$digest(); +      spy.reset(); +        root.name = {};        expect(spy).not.wasCalled();        root.$digest(); @@ -170,6 +173,8 @@ describe('Scope', function(){        root.$watch('c', function(self, v){self.d = v; log+='c'; });        root.$watch('b', function(self, v){self.c = v; log+='b'; });        root.$watch('a', function(self, v){self.b = v; log+='a'; }); +      root.$digest(); +      log = '';        root.a = 1;        expect(root.$digest()).toEqual(3);        expect(root.b).toEqual(1); @@ -204,22 +209,13 @@ describe('Scope', function(){        root.a = 1;        root.$watch('a', function(){ log += 'a'; });        root.$watch('b', function(){ log += 'b'; }); -      expect(log).toEqual(''); +      root.$digest(); +      log = '';        expect(root.$digest()).toEqual(0);        expect(log).toEqual('');      }); -    it('should return the listener to force a initial watch', function(){ -      var log = ''; -      root.a = 1; -      root.$watch('a', function(scope, o1, o2){ log += scope.a + ':' + (o1 == o2 == 1) ; })(); -      expect(log).toEqual('1:true'); -      expect(root.$digest()).toEqual(0); -      expect(log).toEqual('1:true'); -    }); - -      it('should watch objects', function(){        var log = '';        root.a = []; @@ -227,7 +223,7 @@ describe('Scope', function(){        root.$watch('a', function(){ log +='.';});        root.$watch('b', function(){ log +='!';});        root.$digest(); -      expect(log).toEqual(''); +      log = '';        root.a.push({});        root.b.name = ''; @@ -243,9 +239,6 @@ describe('Scope', function(){          expect(function(){            root.$digest();          }).toThrow('$digest already in progress'); -        expect(function(){ -          root.$flush(); -        }).toThrow('$digest already in progress');          callCount++;        });        root.name = 'a'; @@ -255,138 +248,6 @@ describe('Scope', function(){    }); -  describe('$observe/$flush', function(){ -    it('should register simple property observer and fire on change', function(){ -      var spy = jasmine.createSpy(); -      root.$observe('name', spy); -      expect(spy).not.wasCalled(); -      root.$flush(); -      expect(spy).wasCalled(); -      expect(spy.mostRecentCall.args[0]).toEqual(root); -      expect(spy.mostRecentCall.args[1]).toEqual(undefined); -      expect(spy.mostRecentCall.args[2].toString()).toEqual(NaN.toString()); -      root.name = 'misko'; -      root.$flush(); -      expect(spy).wasCalledWith(root, 'misko', undefined); -    }); - - -    it('should register expression observers and fire them on change', function(){ -      var spy = jasmine.createSpy(); -      root.$observe('name.first', spy); -      root.name = {}; -      expect(spy).not.wasCalled(); -      root.$flush(); -      expect(spy).wasCalled(); -      root.name.first = 'misko'; -      root.$flush(); -      expect(spy).wasCalled(); -    }); - - -    it('should delegate exceptions', function(){ -      root.$observe('a', function(){throw new Error('abc');}); -      root.a = 1; -      root.$flush(); -      expect(mockHandler.errors[0].message).toEqual('abc'); -      $logMock.error.logs.shift(); -    }); - - -    it('should fire observers in order of addition', function(){ -      // this is not an external guarantee, just our own sanity -      var log = ''; -      root.$observe('a', function(){ log += 'a'; }); -      root.$observe('b', function(){ log += 'b'; }); -      root.$observe('c', function(){ log += 'c'; }); -      root.a = root.b = root.c = 1; -      root.$flush(); -      expect(log).toEqual('abc'); -    }); - - -    it('should delegate $flush to children in addition order', function(){ -      // this is not an external guarantee, just our own sanity -      var log = ''; -      var childA = root.$new(); -      var childB = root.$new(); -      var childC = root.$new(); -      childA.$observe('a', function(){ log += 'a'; }); -      childB.$observe('b', function(){ log += 'b'; }); -      childC.$observe('c', function(){ log += 'c'; }); -      childA.a = childB.b = childC.c = 1; -      root.$flush(); -      expect(log).toEqual('abc'); -    }); - - -    it('should fire observers once at beggining and on change', function(){ -      var log = ''; -      root.$observe('c', function(self, v){self.d = v; log += 'c';}); -      root.$observe('b', function(self, v){self.c = v; log += 'b';}); -      root.$observe('a', function(self, v){self.b = v; log += 'a';}); -      root.a = 1; -      root.$flush(); -      expect(root.b).toEqual(1); -      expect(log).toEqual('cba'); -      root.$flush(); -      expect(root.c).toEqual(1); -      expect(log).toEqual('cbab'); -      root.$flush(); -      expect(root.d).toEqual(1); -      expect(log).toEqual('cbabc'); -    }); - - -    it('should fire on initial observe', function(){ -      var log = ''; -      root.a = 1; -      root.$observe('a', function(){ log += 'a'; }); -      root.$observe('b', function(){ log += 'b'; }); -      expect(log).toEqual(''); -      root.$flush(); -      expect(log).toEqual('ab'); -    }); - - -    it('should observe objects', function(){ -      var log = ''; -      root.a = []; -      root.b = {}; -      root.$observe('a', function(){ log +='.';}); -      root.$observe('a', function(){ log +='!';}); -      root.$flush(); -      expect(log).toEqual('.!'); - -      root.$flush(); -      expect(log).toEqual('.!'); - -      root.a.push({}); -      root.b.name = ''; - -      root.$digest(); -      expect(log).toEqual('.!'); -    }); - - -    it('should prevent recursion', function(){ -      var callCount = 0; -      root.$observe('name', function(){ -        expect(function(){ -          root.$digest(); -        }).toThrow('$flush already in progress'); -        expect(function(){ -          root.$flush(); -        }).toThrow('$flush already in progress'); -        callCount++; -      }); -      root.name = 'a'; -      root.$flush(); -      expect(callCount).toEqual(1); -    }); -  }); - -    describe('$destroy', function(){      var first, middle, last, log; @@ -401,6 +262,7 @@ describe('Scope', function(){        middle.$watch(function(){ log += '2';});        last.$watch(function(){ log += '3';}); +      root.$digest();        log = '';      }); @@ -450,9 +312,8 @@ describe('Scope', function(){        var log = '';        var child = root.$new();        root.$watch('a', function(scope, a){ log += '1'; }); -      root.$observe('a', function(scope, a){ log += '2'; });        child.$apply('$parent.a=0'); -      expect(log).toEqual('12'); +      expect(log).toEqual('1');      }); @@ -460,25 +321,24 @@ describe('Scope', function(){        var log = '';        var child = root.$new();        root.$watch('a', function(scope, a){ log += '1'; }); -      root.$observe('a', function(scope, a){ log += '2'; });        root.a = 0;        child.$apply(function(){ throw new Error('MyError'); }); -      expect(log).toEqual('12'); +      expect(log).toEqual('1');        expect(mockHandler.errors[0].message).toEqual('MyError');        $logMock.error.logs.shift();      });      describe('exceptions', function(){ -      var $exceptionHandler, $updateView, log; +      var $exceptionHandler, log;        beforeEach(function(){          log = '';          $exceptionHandler = jasmine.createSpy('$exceptionHandler'); -        $updateView = jasmine.createSpy('$updateView');          root.$service = function(name) { -          return {$updateView:$updateView, $exceptionHandler:$exceptionHandler}[name]; +          return {$exceptionHandler:$exceptionHandler}[name];          };          root.$watch(function(){ log += '$digest;'; }); +        root.$digest();          log = '';        }); @@ -490,7 +350,6 @@ describe('Scope', function(){          })).toEqual('abc');          expect(log).toEqual('$digest;');          expect($exceptionHandler).not.wasCalled(); -        expect($updateView).wasCalled();        }); @@ -499,7 +358,6 @@ describe('Scope', function(){          root.$apply(function(){ throw error; });          expect(log).toEqual('$digest;');          expect($exceptionHandler).wasCalledWith(error); -        expect($updateView).wasCalled();        });      });    }); diff --git a/test/directivesSpec.js b/test/directivesSpec.js index a05861ae..1a02e318 100644 --- a/test/directivesSpec.js +++ b/test/directivesSpec.js @@ -20,20 +20,12 @@ describe("directive", function(){      expect(scope.a).toEqual(123);    }); -  it("should ng:eval", function() { -    var scope = compile('<div ng:init="a=0" ng:eval="a = a + 1"></div>'); -    scope.$flush(); -    expect(scope.a).toEqual(1); -    scope.$flush(); -    expect(scope.a).toEqual(2); -  }); -    describe('ng:bind', function(){      it('should set text', function() {        var scope = compile('<div ng:bind="a"></div>');        expect(element.text()).toEqual('');        scope.a = 'misko'; -      scope.$flush(); +      scope.$digest();        expect(element.hasClass('ng-binding')).toEqual(true);        expect(element.text()).toEqual('misko');      }); @@ -41,24 +33,24 @@ describe("directive", function(){      it('should set text to blank if undefined', function() {        var scope = compile('<div ng:bind="a"></div>');        scope.a = 'misko'; -      scope.$flush(); +      scope.$digest();        expect(element.text()).toEqual('misko');        scope.a = undefined; -      scope.$flush(); +      scope.$digest();        expect(element.text()).toEqual('');      });      it('should set html', function() {        var scope = compile('<div ng:bind="html|html"></div>');        scope.html = '<div unknown>hello</div>'; -      scope.$flush(); +      scope.$digest();        expect(lowercase(element.html())).toEqual('<div>hello</div>');      });      it('should set unsafe html', function() {        var scope = compile('<div ng:bind="html|html:\'unsafe\'"></div>');        scope.html = '<div onclick="">hello</div>'; -      scope.$flush(); +      scope.$digest();        expect(lowercase(element.html())).toEqual('<div onclick="">hello</div>');      }); @@ -67,7 +59,7 @@ describe("directive", function(){          return jqLite('<a>hello</a>');        };        var scope = compile('<div ng:bind="0|myElement"></div>'); -      scope.$flush(); +      scope.$digest();        expect(lowercase(element.html())).toEqual('<a>hello</a>');      }); @@ -77,14 +69,14 @@ describe("directive", function(){          return 'HELLO';        };        var scope = compile('<div>before<div ng:bind="0|myFilter"></div>after</div>'); -      scope.$flush(); +      scope.$digest();        expect(sortedHtml(scope.$element)).toEqual('<div>before<div class="filter" ng:bind="0|myFilter">HELLO</div>after</div>');      });      it('should suppress rendering of falsy values', function(){        var scope = compile('<div>{{ null }}{{ undefined }}{{ "" }}-{{ 0 }}{{ false }}</div>'); -      scope.$flush(); +      scope.$digest();        expect(scope.$element.text()).toEqual('-0false');      }); @@ -94,19 +86,19 @@ describe("directive", function(){      it('should ng:bind-template', function() {        var scope = compile('<div ng:bind-template="Hello {{name}}!"></div>');        scope.name = 'Misko'; -      scope.$flush(); +      scope.$digest();        expect(element.hasClass('ng-binding')).toEqual(true);        expect(element.text()).toEqual('Hello Misko!');      });      it('should have $element set to current bind element', function(){ -      var innerText = 'blank'; +      var innerText;        angularFilter.myFilter = function(text){ -        innerText = this.$element.text(); +        innerText = innerText || this.$element.text();          return text;        };        var scope = compile('<div>before<span ng:bind-template="{{\'HELLO\'|myFilter}}">INNER</span>after</div>'); -      scope.$flush(); +      scope.$digest();        expect(scope.$element.text()).toEqual("beforeHELLOafter");        expect(innerText).toEqual('INNER');      }); @@ -116,14 +108,14 @@ describe("directive", function(){    describe('ng:bind-attr', function(){      it('should bind attributes', function(){        var scope = compile('<div ng:bind-attr="{src:\'http://localhost/mysrc\', alt:\'myalt\'}"/>'); -      scope.$flush(); +      scope.$digest();        expect(element.attr('src')).toEqual('http://localhost/mysrc');        expect(element.attr('alt')).toEqual('myalt');      });      it('should not pretty print JSON in attributes', function(){        var scope = compile('<img alt="{{ {a:1} }}"/>'); -      scope.$flush(); +      scope.$digest();        expect(element.attr('alt')).toEqual('{"a":1}');      });    }); @@ -138,7 +130,7 @@ describe("directive", function(){      scope.disabled = true;      scope.readonly = true;      scope.checked = true; -    scope.$flush(); +    scope.$digest();      expect(input.disabled).toEqual(true);      expect(input.readOnly).toEqual(true); @@ -148,7 +140,7 @@ describe("directive", function(){    describe('ng:click', function(){      it('should get called on a click', function(){        var scope = compile('<div ng:click="clicked = true"></div>'); -      scope.$flush(); +      scope.$digest();        expect(scope.clicked).toBeFalsy();        browserTrigger(element, 'click'); @@ -157,7 +149,7 @@ describe("directive", function(){      it('should stop event propagation', function() {        var scope = compile('<div ng:click="outer = true"><div ng:click="inner = true"></div></div>'); -      scope.$flush(); +      scope.$digest();        expect(scope.outer).not.toBeDefined();        expect(scope.inner).not.toBeDefined(); @@ -175,7 +167,7 @@ describe("directive", function(){        var scope = compile('<form action="" ng:submit="submitted = true">' +                              '<input type="submit"/>' +                            '</form>'); -      scope.$flush(); +      scope.$digest();        expect(scope.submitted).not.toBeDefined();        browserTrigger(element.children()[0]); @@ -187,18 +179,18 @@ describe("directive", function(){      it('should add new and remove old classes dynamically', function() {        var scope = compile('<div class="existing" ng:class="dynClass"></div>');        scope.dynClass = 'A'; -      scope.$flush(); +      scope.$digest();        expect(element.hasClass('existing')).toBe(true);        expect(element.hasClass('A')).toBe(true);        scope.dynClass = 'B'; -      scope.$flush(); +      scope.$digest();        expect(element.hasClass('existing')).toBe(true);        expect(element.hasClass('A')).toBe(false);        expect(element.hasClass('B')).toBe(true);        delete scope.dynClass; -      scope.$flush(); +      scope.$digest();        expect(element.hasClass('existing')).toBe(true);        expect(element.hasClass('A')).toBe(false);        expect(element.hasClass('B')).toBe(false); @@ -206,7 +198,7 @@ describe("directive", function(){      it('should support adding multiple classes', function(){        var scope = compile('<div class="existing" ng:class="[\'A\', \'B\']"></div>'); -      scope.$flush(); +      scope.$digest();        expect(element.hasClass('existing')).toBeTruthy();        expect(element.hasClass('A')).toBeTruthy();        expect(element.hasClass('B')).toBeTruthy(); @@ -216,7 +208,7 @@ describe("directive", function(){    it('should ng:class odd/even', function(){      var scope = compile('<ul><li ng:repeat="i in [0,1]" class="existing" ng:class-odd="\'odd\'" ng:class-even="\'even\'"></li><ul>'); -    scope.$flush(); +    scope.$digest();      var e1 = jqLite(element[0].childNodes[1]);      var e2 = jqLite(element[0].childNodes[2]);      expect(e1.hasClass('existing')).toBeTruthy(); @@ -228,32 +220,32 @@ describe("directive", function(){    describe('ng:style', function(){      it('should set', function(){        var scope = compile('<div ng:style="{height: \'40px\'}"></div>'); -      scope.$flush(); +      scope.$digest();        expect(element.css('height')).toEqual('40px');      });      it('should silently ignore undefined style', function() {        var scope = compile('<div ng:style="myStyle"></div>'); -      scope.$flush(); +      scope.$digest();        expect(element.hasClass('ng-exception')).toBeFalsy();      });      it('should preserve and remove previous style', function(){        var scope = compile('<div style="height: 10px;" ng:style="myStyle"></div>'); -      scope.$flush(); +      scope.$digest();        expect(getStyle(element)).toEqual({height: '10px'});        scope.myStyle = {height: '20px', width: '10px'}; -      scope.$flush(); +      scope.$digest();        expect(getStyle(element)).toEqual({height: '20px', width: '10px'});        scope.myStyle = {}; -      scope.$flush(); +      scope.$digest();        expect(getStyle(element)).toEqual({height: '10px'});      });    });    it('should silently ignore undefined ng:style', function() {      var scope = compile('<div ng:style="myStyle"></div>'); -    scope.$flush(); +    scope.$digest();      expect(element.hasClass('ng-exception')).toBeFalsy();    }); @@ -263,10 +255,10 @@ describe("directive", function(){        var element = jqLite('<div ng:show="exp"></div>'),            scope = compile(element); -      scope.$flush(); +      scope.$digest();        expect(isCssVisible(element)).toEqual(false);        scope.exp = true; -      scope.$flush(); +      scope.$digest();        expect(isCssVisible(element)).toEqual(true);      }); @@ -277,7 +269,7 @@ describe("directive", function(){        expect(isCssVisible(element)).toBe(false);        scope.exp = true; -      scope.$flush(); +      scope.$digest();        expect(isCssVisible(element)).toBe(true);      });    }); @@ -289,7 +281,7 @@ describe("directive", function(){        expect(isCssVisible(element)).toBe(true);        scope.exp = true; -      scope.$flush(); +      scope.$digest();        expect(isCssVisible(element)).toBe(false);      });    }); @@ -339,25 +331,10 @@ describe("directive", function(){        expect(scope.greeter.greeting).toEqual('hello');        expect(scope.childGreeter.greeting).toEqual('hey');        expect(scope.childGreeter.$parent.greeting).toEqual('hello'); -      scope.$flush(); +      scope.$digest();        expect(scope.$element.text()).toEqual('hey dude!');      });    }); -  //TODO(misko): this needs to be deleted when ng:eval-order is gone -  it('should eval things according to ng:eval-order', function(){ -    var scope = compile( -          '<div ng:init="log=\'\'">' + -            '{{log = log + \'e\'}}' + -            '<span ng:eval-order="first" ng:eval="log = log + \'a\'">' + -              '{{log = log + \'b\'}}' + -              '<span src="{{log = log + \'c\'}}"></span>' + -              '<span bind-template="{{log = log + \'d\'}}"></span>' + -            '</span>' + -          '</div>'); -    scope.$flush(); -    expect(scope.log).toEqual('abcde'); -  }); -  }); diff --git a/test/markupSpec.js b/test/markupSpec.js index ab8b4c74..36861e17 100644 --- a/test/markupSpec.js +++ b/test/markupSpec.js @@ -21,16 +21,16 @@ describe("markups", function(){      compile('<div>hello {{name}}!</div>');      expect(sortedHtml(element)).toEqual('<div>hello <span ng:bind="name"></span>!</div>');      scope.name = 'Misko'; -    scope.$flush(); +    scope.$digest();      expect(sortedHtml(element)).toEqual('<div>hello <span ng:bind="name">Misko</span>!</div>');    });    it('should translate {{}} in terminal nodes', function(){      compile('<select name="x"><option value="">Greet {{name}}!</option></select>'); -    scope.$flush(); +    scope.$digest();      expect(sortedHtml(element).replace(' selected="true"', '')).toEqual('<select name="x"><option ng:bind-template="Greet {{name}}!">Greet !</option></select>');      scope.name = 'Misko'; -    scope.$flush(); +    scope.$digest();      expect(sortedHtml(element).replace(' selected="true"', '')).toEqual('<select name="x"><option ng:bind-template="Greet {{name}}!">Greet Misko!</option></select>');    }); @@ -38,7 +38,7 @@ describe("markups", function(){      compile('<div src="http://server/{{path}}.png"/>');      expect(element.attr('ng:bind-attr')).toEqual('{"src":"http://server/{{path}}.png"}');      scope.path = 'a/b'; -    scope.$flush(); +    scope.$digest();      expect(element.attr('src')).toEqual("http://server/a/b.png");    }); @@ -95,57 +95,57 @@ describe("markups", function(){    it('should bind disabled', function() {      compile('<button ng:disabled="{{isDisabled}}">Button</button>');      scope.isDisabled = false; -    scope.$flush(); +    scope.$digest();      expect(element.attr('disabled')).toBeFalsy();      scope.isDisabled = true; -    scope.$flush(); +    scope.$digest();      expect(element.attr('disabled')).toBeTruthy();    });    it('should bind checked', function() {      compile('<input type="checkbox" ng:checked="{{isChecked}}" />');      scope.isChecked = false; -    scope.$flush(); +    scope.$digest();      expect(element.attr('checked')).toBeFalsy();      scope.isChecked=true; -    scope.$flush(); +    scope.$digest();      expect(element.attr('checked')).toBeTruthy();    });    it('should bind selected', function() {      compile('<select><option value=""></option><option ng:selected="{{isSelected}}">Greetings!</option></select>');      scope.isSelected=false; -    scope.$flush(); +    scope.$digest();      expect(element.children()[1].selected).toBeFalsy();      scope.isSelected=true; -    scope.$flush(); +    scope.$digest();      expect(element.children()[1].selected).toBeTruthy();    });    it('should bind readonly', function() {      compile('<input type="text" ng:readonly="{{isReadonly}}" />');      scope.isReadonly=false; -    scope.$flush(); +    scope.$digest();      expect(element.attr('readOnly')).toBeFalsy();      scope.isReadonly=true; -    scope.$flush(); +    scope.$digest();      expect(element.attr('readOnly')).toBeTruthy();    });    it('should bind multiple', function() {      compile('<select ng:multiple="{{isMultiple}}"></select>');      scope.isMultiple=false; -    scope.$flush(); +    scope.$digest();      expect(element.attr('multiple')).toBeFalsy();      scope.isMultiple='multiple'; -    scope.$flush(); +    scope.$digest();      expect(element.attr('multiple')).toBeTruthy();    });    it('should bind src', function() {      compile('<div ng:src="{{url}}" />');      scope.url = 'http://localhost/'; -    scope.$flush(); +    scope.$digest();      expect(element.attr('src')).toEqual('http://localhost/');    }); diff --git a/test/service/cookieStoreSpec.js b/test/service/cookieStoreSpec.js index 75be924c..fa4f3ceb 100644 --- a/test/service/cookieStoreSpec.js +++ b/test/service/cookieStoreSpec.js @@ -16,7 +16,7 @@ describe('$cookieStore', function() {    it('should serialize objects to json', function() {      $cookieStore.put('objectCookie', {id: 123, name: 'blah'}); -    scope.$flush(); +    scope.$digest();      expect($browser.cookies()).toEqual({'objectCookie': '{"id":123,"name":"blah"}'});    }); @@ -30,12 +30,12 @@ describe('$cookieStore', function() {    it('should delete objects from the store when remove is called', function() {      $cookieStore.put('gonner', { "I'll":"Be Back"}); -    scope.$flush(); //force eval in test +    scope.$digest(); //force eval in test      $browser.poll();      expect($browser.cookies()).toEqual({'gonner': '{"I\'ll":"Be Back"}'});      $cookieStore.remove('gonner'); -    scope.$flush(); +    scope.$digest();      expect($browser.cookies()).toEqual({});    });  }); diff --git a/test/service/cookiesSpec.js b/test/service/cookiesSpec.js index cc667b56..782cee72 100644 --- a/test/service/cookiesSpec.js +++ b/test/service/cookiesSpec.js @@ -38,13 +38,13 @@ describe('$cookies', function() {    it('should create or update a cookie when a value is assigned to a property', function() {      scope.$cookies.oatmealCookie = 'nom nom'; -    scope.$flush(); +    scope.$digest();      expect($browser.cookies()).        toEqual({'preexisting': 'oldCookie', 'oatmealCookie':'nom nom'});      scope.$cookies.oatmealCookie = 'gone'; -    scope.$flush(); +    scope.$digest();      expect($browser.cookies()).        toEqual({'preexisting': 'oldCookie', 'oatmealCookie': 'gone'}); @@ -56,7 +56,7 @@ describe('$cookies', function() {      scope.$cookies.nullVal = null;      scope.$cookies.undefVal = undefined;      scope.$cookies.preexisting = function(){}; -    scope.$flush(); +    scope.$digest();      expect($browser.cookies()).toEqual({'preexisting': 'oldCookie'});      expect(scope.$cookies).toEqual({'preexisting': 'oldCookie'});    }); @@ -64,13 +64,13 @@ describe('$cookies', function() {    it('should remove a cookie when a $cookies property is deleted', function() {      scope.$cookies.oatmealCookie = 'nom nom'; -    scope.$flush(); +    scope.$digest();      $browser.poll();      expect($browser.cookies()).        toEqual({'preexisting': 'oldCookie', 'oatmealCookie':'nom nom'});      delete scope.$cookies.oatmealCookie; -    scope.$flush(); +    scope.$digest();      expect($browser.cookies()).toEqual({'preexisting': 'oldCookie'});    }); @@ -85,16 +85,16 @@ describe('$cookies', function() {      //drop if no previous value      scope.$cookies.longCookie = longVal; -    scope.$flush(); +    scope.$digest();      expect(scope.$cookies).toEqual({'preexisting': 'oldCookie'});      //reset if previous value existed      scope.$cookies.longCookie = 'shortVal'; -    scope.$flush(); +    scope.$digest();      expect(scope.$cookies).toEqual({'preexisting': 'oldCookie', 'longCookie': 'shortVal'});      scope.$cookies.longCookie = longVal; -    scope.$flush(); +    scope.$digest();      expect(scope.$cookies).toEqual({'preexisting': 'oldCookie', 'longCookie': 'shortVal'});    });  }); diff --git a/test/service/locationSpec.js b/test/service/locationSpec.js index 73e5e43e..5839b0b6 100644 --- a/test/service/locationSpec.js +++ b/test/service/locationSpec.js @@ -108,7 +108,9 @@ describe('$location', function() {      var log = '';      scope.$watch('$location.hash', function(scope){        log += scope.$location.hashPath + ';'; -    })(); +    }); +    expect(log).toEqual(''); +    scope.$digest();      expect(log).toEqual(';');      log = ''; diff --git a/test/service/routeSpec.js b/test/service/routeSpec.js index 6c6c0868..bfe201d1 100644 --- a/test/service/routeSpec.js +++ b/test/service/routeSpec.js @@ -71,7 +71,7 @@ describe('$route', function() {      $route.when('/foo', {template: 'foo.html'});      $route.onChange(onChangeSpy); -    expect($route.current).toBeNull(); +    expect($route.current).toBeUndefined();      expect(onChangeSpy).not.toHaveBeenCalled();      $location.updateHash('/foo'); @@ -94,7 +94,7 @@ describe('$route', function() {      $route.when('/foo', {template: 'foo.html'});      $route.otherwise({template: '404.html', controller: NotFoundCtrl});      $route.onChange(onChangeSpy); -    expect($route.current).toBeNull(); +    expect($route.current).toBeUndefined();      expect(onChangeSpy).not.toHaveBeenCalled();      $location.updateHash('/unknownRoute'); @@ -164,7 +164,7 @@ describe('$route', function() {        $route.when('/baz', {redirectTo: '/bar'});        $route.otherwise({template: '404.html'});        $route.onChange(onChangeSpy); -      expect($route.current).toBeNull(); +      expect($route.current).toBeUndefined();        expect(onChangeSpy).not.toHaveBeenCalled();        scope.$digest(); //triggers initial route change - match the redirect route diff --git a/test/service/updateViewSpec.js b/test/service/updateViewSpec.js deleted file mode 100644 index d8932d29..00000000 --- a/test/service/updateViewSpec.js +++ /dev/null @@ -1,63 +0,0 @@ -'use strict'; - -describe('$updateView', function() { -  var scope, browser, evalCount, $updateView; - -  beforeEach(function(){ -    browser = new MockBrowser(); -    // Pretend that you are real Browser so that we see the delays -    browser.isMock = false; -    browser.defer = jasmine.createSpy('defer'); - -    scope = angular.scope(null, {$browser:browser}); -    $updateView = scope.$service('$updateView'); -    scope.$observe(function(){ evalCount++; }); -    evalCount = 0; -  }); - - -  afterEach(function(){ -    dealoc(scope); -  }); - - -  it('should eval root scope after a delay', function(){ -    $updateView(); -    expect(evalCount).toEqual(0); -    expect(browser.defer).toHaveBeenCalled(); -    expect(browser.defer.mostRecentCall.args[1]).toEqual(25); -    browser.defer.mostRecentCall.args[0](); -    expect(evalCount).toEqual(1); -  }); - - -  it('should allow changing of delay time', function(){ -    var oldValue = angular.service('$updateView').delay; -    angular.service('$updateView').delay = 50; -    $updateView(); -    expect(evalCount).toEqual(0); -    expect(browser.defer).toHaveBeenCalled(); -    expect(browser.defer.mostRecentCall.args[1]).toEqual(50); -    angular.service('$updateView').delay = oldValue; -  }); - - -  it('should ignore multiple requests for update', function(){ -    $updateView(); -    $updateView(); -    expect(evalCount).toEqual(0); -    expect(browser.defer).toHaveBeenCalled(); -    expect(browser.defer.callCount).toEqual(1); -    browser.defer.mostRecentCall.args[0](); -    expect(evalCount).toEqual(1); -  }); - - -  it('should update immediatelly in test/mock mode', function(){ -    scope = angular.scope(); -    scope.$observe(function(){ evalCount++; }); -    expect(evalCount).toEqual(0); -    scope.$service('$updateView')(); -    expect(evalCount).toEqual(1); -  }); -}); diff --git a/test/service/xhr.cacheSpec.js b/test/service/xhr.cacheSpec.js index 7bf5d40b..c6b9cfec 100644 --- a/test/service/xhr.cacheSpec.js +++ b/test/service/xhr.cacheSpec.js @@ -126,7 +126,7 @@ describe('$xhr.cache', function() {    it('should call eval after callbacks for both cache hit and cache miss execute', function() { -    var flushSpy = this.spyOn(scope, '$flush').andCallThrough(); +    var flushSpy = this.spyOn(scope, '$digest').andCallThrough();      $browserXhr.expectGET('/url').respond('+');      cache('GET', '/url', null, callback); diff --git a/test/widgetsSpec.js b/test/widgetsSpec.js index 0ca42110..9e8492f1 100644 --- a/test/widgetsSpec.js +++ b/test/widgetsSpec.js @@ -368,7 +368,7 @@ describe("widget", function(){                  '</select>');          scope.a = 'foo';          scope.b = 'bar'; -        scope.$flush(); +        scope.$digest();          expect(scope.$element.text()).toBe('foobarC');        }); @@ -465,7 +465,7 @@ describe("widget", function(){        scope.childScope.name = 'misko';        scope.url = 'myUrl';        scope.$service('$xhr.cache').data.myUrl = {value:'{{name}}'}; -      scope.$flush(); +      scope.$digest();        expect(element.text()).toEqual('misko');        dealoc(scope);      }); @@ -477,12 +477,12 @@ describe("widget", function(){        scope.childScope.name = 'igor';        scope.url = 'myUrl';        scope.$service('$xhr.cache').data.myUrl = {value:'{{name}}'}; -      scope.$flush(); +      scope.$digest();        expect(element.text()).toEqual('igor');        scope.url = undefined; -      scope.$flush(); +      scope.$digest();        expect(element.text()).toEqual('');        dealoc(scope); @@ -492,15 +492,15 @@ describe("widget", function(){        var element = jqLite('<ng:include src="url" scope="this"></ng:include>');        var scope = angular.compile(element)();        scope.url = 'myUrl'; -      scope.$service('$xhr.cache').data.myUrl = {value:'{{c=c+1}}'}; -      scope.$flush(); +      scope.$service('$xhr.cache').data.myUrl = {value:'{{"abc"}}'}; +      scope.$digest();        // 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(); +      scope.$digest(); -      expect(element.text()).toEqual('1'); +      expect(element.text()).toEqual('abc');        dealoc(element);      }); @@ -512,7 +512,7 @@ describe("widget", function(){        scope.url = 'myUrl';        scope.$service('$xhr.cache').data.myUrl = {value:'my partial'}; -      scope.$flush(); +      scope.$digest();        expect(element.text()).toEqual('my partial');        expect(scope.loaded).toBe(true);        dealoc(element); @@ -526,11 +526,11 @@ describe("widget", function(){        scope.url = 'myUrl';        scope.$service('$xhr.cache').data.myUrl = {value:'my partial'}; -      scope.$flush(); +      scope.$digest();        expect(scope.$$childHead).toBeTruthy();        scope.url = null; -      scope.$flush(); +      scope.$digest();        expect(scope.$$childHead).toBeFalsy();        dealoc(element);      }); @@ -622,7 +622,7 @@ describe("widget", function(){        createSingleSelect();        scope.values = [{name:'A'}, {name:'B'}, {name:'C'}];        scope.selected = scope.values[0]; -      scope.$flush(); +      scope.$digest();        var options = select.find('option');        expect(options.length).toEqual(3);        expect(sortedHtml(options[0])).toEqual('<option value="0">A</option>'); @@ -637,7 +637,7 @@ describe("widget", function(){        });        scope.object = {'red':'FF0000', 'green':'00FF00', 'blue':'0000FF'};        scope.selected = scope.object.red; -      scope.$flush(); +      scope.$digest();        var options = select.find('option');        expect(options.length).toEqual(3);        expect(sortedHtml(options[0])).toEqual('<option value="blue">blue</option>'); @@ -646,7 +646,7 @@ describe("widget", function(){        expect(options[2].selected).toEqual(true);        scope.object.azur = '8888FF'; -      scope.$flush(); +      scope.$digest();        options = select.find('option');        expect(options[3].selected).toEqual(true);      }); @@ -654,18 +654,18 @@ describe("widget", function(){      it('should grow list', function(){        createSingleSelect();        scope.values = []; -      scope.$flush(); +      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.$flush(); +      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.$flush(); +      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>'); @@ -675,23 +675,23 @@ describe("widget", function(){        createSingleSelect();        scope.values = [{name:'A'}, {name:'B'}, {name:'C'}];        scope.selected = scope.values[0]; -      scope.$flush(); +      scope.$digest();        expect(select.find('option').length).toEqual(3);        scope.values.pop(); -      scope.$flush(); +      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.$flush(); +      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.$flush(); +      scope.$digest();        expect(select.find('option').length).toEqual(1); // we add back the special empty option      }); @@ -699,17 +699,17 @@ describe("widget", function(){        createSingleSelect();        scope.values = [{name:'A'}, {name:'B'}, {name:'C'}];        scope.selected = scope.values[0]; -      scope.$flush(); +      scope.$digest();        expect(select.find('option').length).toEqual(3);        scope.values = [{name:'1'}, {name:'2'}];        scope.selected = scope.values[0]; -      scope.$flush(); +      scope.$digest();        expect(select.find('option').length).toEqual(2);        scope.values = [{name:'A'}, {name:'B'}, {name:'C'}];        scope.selected = scope.values[0]; -      scope.$flush(); +      scope.$digest();        expect(select.find('option').length).toEqual(3);      }); @@ -717,11 +717,11 @@ describe("widget", function(){        createSingleSelect();        scope.values = [{name:'A'}, {name:'B'}, {name:'C'}];        scope.selected = scope.values[0]; -      scope.$flush(); +      scope.$digest();        scope.values = [{name:'B'}, {name:'C'}, {name:'D'}];        scope.selected = scope.values[0]; -      scope.$flush(); +      scope.$digest();        var options = select.find('option');        expect(options.length).toEqual(3);        expect(sortedHtml(options[0])).toEqual('<option value="0">B</option>'); @@ -732,19 +732,19 @@ describe("widget", function(){      it('should preserve existing options', function(){        createSingleSelect(true); -      scope.$flush(); +      scope.$digest();        expect(select.find('option').length).toEqual(1);        scope.values = [{name:'A'}];        scope.selected = scope.values[0]; -      scope.$flush(); +      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.$flush(); +      scope.$digest();        expect(select.find('option').length).toEqual(1);        expect(jqLite(select.find('option')[0]).text()).toEqual('blank');      }); @@ -754,11 +754,11 @@ describe("widget", function(){          createSingleSelect();          scope.values = [{name:'A'}, {name:'B'}];          scope.selected = scope.values[0]; -        scope.$flush(); +        scope.$digest();          expect(select.val()).toEqual('0');          scope.selected = scope.values[1]; -        scope.$flush(); +        scope.$digest();          expect(select.val()).toEqual('1');        }); @@ -773,7 +773,7 @@ describe("widget", function(){                          {name:'D', group:'first'},                          {name:'E', group:'second'}];          scope.selected = scope.values[3]; -        scope.$flush(); +        scope.$digest();          expect(select.val()).toEqual('3');          var first = jqLite(select.find('optgroup')[0]); @@ -791,7 +791,7 @@ describe("widget", function(){          expect(e.text()).toEqual('E');          scope.selected = scope.values[0]; -        scope.$flush(); +        scope.$digest();          expect(select.val()).toEqual('0');        }); @@ -799,11 +799,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.$flush(); +        scope.$digest();          expect(select.val()).toEqual('0');          scope.selected = scope.values[1].id; -        scope.$flush(); +        scope.$digest();          expect(select.val()).toEqual('1');        }); @@ -814,11 +814,11 @@ describe("widget", function(){          });          scope.object = {'red':'FF0000', 'green':'00FF00', 'blue':'0000FF'};          scope.selected = 'green'; -        scope.$flush(); +        scope.$digest();          expect(select.val()).toEqual('green');          scope.selected = 'blue'; -        scope.$flush(); +        scope.$digest();          expect(select.val()).toEqual('blue');        }); @@ -829,11 +829,11 @@ describe("widget", function(){          });          scope.object = {'red':'FF0000', 'green':'00FF00', 'blue':'0000FF'};          scope.selected = '00FF00'; -        scope.$flush(); +        scope.$digest();          expect(select.val()).toEqual('green');          scope.selected = '0000FF'; -        scope.$flush(); +        scope.$digest();          expect(select.val()).toEqual('blue');        }); @@ -841,13 +841,13 @@ describe("widget", function(){          createSingleSelect();          scope.values = [{name:'A'}];          scope.selected = null; -        scope.$flush(); +        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.$flush(); +        scope.$digest();          expect(select.val()).toEqual('0');          expect(select.find('option').length).toEqual(1);        }); @@ -856,13 +856,13 @@ describe("widget", function(){          createSingleSelect(true);          scope.values = [{name:'A'}];          scope.selected = null; -        scope.$flush(); +        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.$flush(); +        scope.$digest();          expect(select.val()).toEqual('0');          expect(select.find('option').length).toEqual(2);        }); @@ -871,13 +871,13 @@ describe("widget", function(){          createSingleSelect();          scope.values = [{name:'A'}];          scope.selected = {}; -        scope.$flush(); +        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.$flush(); +        scope.$digest();          expect(select.val()).toEqual('0');          expect(select.find('option').length).toEqual(1);        }); @@ -888,7 +888,7 @@ describe("widget", function(){          createSingleSelect();          scope.values = [{name:'A'}, {name:'B'}];          scope.selected = scope.values[0]; -        scope.$flush(); +        scope.$digest();          expect(select.val()).toEqual('0');          select.val('1'); @@ -905,7 +905,7 @@ describe("widget", function(){          scope.values = [{name:'A'}, {name:'B'}];          scope.selected = scope.values[0];          scope.count = 0; -        scope.$flush(); +        scope.$digest();          expect(scope.count).toEqual(0);          select.val('1'); @@ -922,7 +922,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.$flush(); +        scope.$digest();          expect(select.val()).toEqual('0');          select.val('1'); @@ -935,7 +935,7 @@ describe("widget", function(){          scope.values = [{name:'A'}, {name:'B'}];          scope.selected = scope.values[0];          select.val('0'); -        scope.$flush(); +        scope.$digest();          select.val('');          browserTrigger(select, 'change'); @@ -949,19 +949,19 @@ describe("widget", function(){          scope.values = [{name:'A'}, {name:'B'}];          scope.selected = []; -        scope.$flush(); +        scope.$digest();          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.$flush(); +        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.$flush(); +        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); @@ -972,7 +972,7 @@ describe("widget", function(){          scope.values = [{name:'A'}, {name:'B'}];          scope.selected = []; -        scope.$flush(); +        scope.$digest();          select.find('option')[0].selected = true;          browserTrigger(select, 'change'); @@ -991,20 +991,20 @@ describe("widget", function(){        Array.prototype.extraProperty = "should be ignored";        // INIT        scope.items = ['misko', 'shyam']; -      scope.$flush(); +      scope.$digest();        expect(element.find('li').length).toEqual(2);        expect(element.text()).toEqual('misko;shyam;');        delete Array.prototype.extraProperty;        // GROW        scope.items = ['adam', 'kai', 'brad']; -      scope.$flush(); +      scope.$digest();        expect(element.find('li').length).toEqual(3);        expect(element.text()).toEqual('adam;kai;brad;');        // SHRINK        scope.items = ['brad']; -      scope.$flush(); +      scope.$digest();        expect(element.find('li').length).toEqual(1);        expect(element.text()).toEqual('brad;');      }); @@ -1012,7 +1012,7 @@ describe("widget", function(){      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.items = {misko:'swe', shyam:'set'}; -      scope.$flush(); +      scope.$digest();        expect(element.text()).toEqual('misko:swe;shyam:set;');      }); @@ -1024,7 +1024,7 @@ 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.$flush(); +      scope.$digest();        expect(element.text()).toEqual('name:value;');      }); @@ -1040,7 +1040,7 @@ describe("widget", function(){        var scope = compile('<ul><li ng:repeat="item in items" ' +                                    'ng:bind="item + $index + \'|\'"></li></ul>');        scope.items = ['misko', 'shyam', 'frodo']; -      scope.$flush(); +      scope.$digest();        expect(element.text()).toEqual('misko0|shyam1|frodo2|');      }); @@ -1048,7 +1048,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.$flush(); +      scope.$digest();        expect(element.text()).toEqual('misko:m0|shyam:s1|frodo:f2|');      }); @@ -1056,16 +1056,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.$flush(); +      scope.$digest();        expect(element.text()).toEqual('misko:first|shyam:middle|doug:last|');        scope.items.push('frodo'); -      scope.$flush(); +      scope.$digest();        expect(element.text()).toEqual('misko:first|shyam:middle|doug:middle|frodo:last|');        scope.items.pop();        scope.items.pop(); -      scope.$flush(); +      scope.$digest();        expect(element.text()).toEqual('misko:first|shyam:last|');      }); @@ -1073,12 +1073,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.$flush(); +      scope.$digest();        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.$flush(); +      scope.$digest();        expect(element.text()).toEqual('misko:m:first|shyam:s:last|');      });    }); @@ -1126,14 +1126,14 @@ describe("widget", function(){        $location.updateHash('/foo');        $browser.xhr.expectGET('myUrl1').respond('<div>{{1+3}}</div>');        rootScope.$digest(); -      rootScope.$flush(); +      rootScope.$digest();        $browser.xhr.flush();        expect(rootScope.$element.text()).toEqual('4');        $location.updateHash('/bar');        $browser.xhr.expectGET('myUrl2').respond('angular is da best');        rootScope.$digest(); -      rootScope.$flush(); +      rootScope.$digest();        $browser.xhr.flush();        expect(rootScope.$element.text()).toEqual('angular is da best');      }); @@ -1144,13 +1144,13 @@ describe("widget", function(){        $location.updateHash('/foo');        $browser.xhr.expectGET('myUrl1').respond('<div>{{1+3}}</div>');        rootScope.$digest(); -      rootScope.$flush(); +      rootScope.$digest();        $browser.xhr.flush();        expect(rootScope.$element.text()).toEqual('4');        $location.updateHash('/unknown');        rootScope.$digest(); -      rootScope.$flush(); +      rootScope.$digest();        expect(rootScope.$element.text()).toEqual('');      }); @@ -1161,13 +1161,13 @@ describe("widget", function(){        $location.updateHash('/foo');        $browser.xhr.expectGET('myUrl1').respond('<div>{{parentVar}}</div>');        rootScope.$digest(); -      rootScope.$flush(); +      rootScope.$digest();        $browser.xhr.flush();        expect(rootScope.$element.text()).toEqual('parent');        rootScope.parentVar = 'new parent';        rootScope.$digest(); -      rootScope.$flush(); +      rootScope.$digest();        expect(rootScope.$element.text()).toEqual('new parent');      }); @@ -1189,7 +1189,7 @@ describe("widget", function(){        rootScope.$apply();        $browser.xhr.expectGET('viewPartial.html').respond('content'); -      rootScope.$flush(); +      rootScope.$digest();        $browser.xhr.flush();        expect(rootScope.$element.text()).toEqual('include: view: content'); @@ -1222,18 +1222,18 @@ describe("widget", function(){        rootScope.$apply();        $browser.xhr.flush(); -      expect(rootScope.log).toEqual(['parent', 'child', 'init']); +      expect(rootScope.log).toEqual(['parent', 'init', 'child']);        $location.updateHash('');        rootScope.$apply(); -      expect(rootScope.log).toEqual(['parent', 'child', 'init']); +      expect(rootScope.log).toEqual(['parent', 'init', 'child']);        rootScope.log = [];        $location.updateHash('/foo');        rootScope.$apply();        $browser.defer.flush(); -      expect(rootScope.log).toEqual(['parent', 'child', 'init']); +      expect(rootScope.log).toEqual(['parent', 'init', 'child']);      });    });  }); | 
