JavaScript newValue always equals to oldValue in AngularJS property watching in unit test

I have an controller which is simply watching a 'name' property and prints its new and old values on any change.

function Ctrl($scope) {
    $scope.$watch('name', function(newValue, oldValue) {
        console.log('newValue: ' + newValue + ', oldValue: '+ oldValue);
        if (newValue !== oldValue) {
            //...
        }
    }
});

Then I want to unit test it with Jasmine:

var rootScope, scope, ctrl;
beforeEach(inject(function ($rootScope, $controller) {
    rootScope = $rootScope;
    scope = $rootScope.$new();
    ctrl = $controller('Ctrl', { $scope: scope });
}));

it('should have different old and new values if I set a new name', function() {
    rootScope.name = 'some new name';
    rootScope.$apply();

    //expect the behaviors happen for newValue !== oldValue
});

Then I expected the console to log a message which is indicating newValue not equals oldValue, however I always get newValue === oldValue. Why the old value is lost?

Answer:1

I think , this is the behavior. When we 1st time invoke controller, the old value equals to new one and therefore nothing happens. Generally in this case we can write :

if(oldValue === newValue){return;}

We also can write $watch like:

$scope.$watch('name', function () {
    // ....
  });

and it will be invoked only if name is changed:

Demo 1 Plunker

I'm not Unitest Guru, anyways try this flow:

Controller

angular.module('plunker').controller('MyCtrl', function($scope) {

 $scope.watchFunctionCounter= 0;

  $scope.$watch(function () {
    return $scope.name;
},
function (newValue, oldValue) {
    console.log('newValue: ' + newValue + ', oldValue: '+ oldValue);
        if (newValue !== oldValue) {
            $scope.watchFunctionCounter++;
        }
}, true);
});

Unitest

describe('Directive: maybeLink', function() {
 var scope, ctrl;

  beforeEach(function() {
    module('plunker');

    inject(function($rootScope, $controller) {
      scope = $rootScope.$new();
      ctrl = $controller('MyCtrl', {$scope: scope});
    });
  });

  afterEach(function() {
        controller = null;
    });

        it('should have different old and new values if I set a new name', function() {
           scope.name = 'some new name';
           scope.$digest();

          expect(scope.watchFunctionCounter).toBe(0); 
         // on this strage the name is undefined, therefore we stay out of "if" statemant

           scope.name = 'diff name';
           scope.$digest();

          expect(scope.watchFunctionCounter).toBe(1);
     });
});

Demo 2 Plunker

Answer:2

I am trying to replace all occurences of 'S' (capital S) with '.sss' : For example the following line doesn't even contain a capital S in it and it still replaces a lot : "MM/dd/yyyy EEEE hh:mm aa"....

I am trying to replace all occurences of 'S' (capital S) with '.sss' : For example the following line doesn't even contain a capital S in it and it still replaces a lot : "MM/dd/yyyy EEEE hh:mm aa"....

I am pushing HTML Code including <script> in a div, I am able to push inside the div successfully using innerHTML but script is not executing. Code: $.ajax({ data: '', dataType: 'html'...

I am pushing HTML Code including <script> in a div, I am able to push inside the div successfully using innerHTML but script is not executing. Code: $.ajax({ data: '', dataType: 'html'...

  1. delete script after execution
  2. script execution timed out after 30000ms
  3. remove script after execution
  4. exit shell script after execution
  5. pause powershell script after execution
  6. exit bash script after execution
  7. javascript remove script after execution
  8. powershell delete script after execution

Lets say I have some constructors: function Foo() { } function FooObject() { return {} } function FooArray() { return [] } function FooFunction() { return function () {} } function FooString() { ...

Lets say I have some constructors: function Foo() { } function FooObject() { return {} } function FooArray() { return [] } function FooFunction() { return function () {} } function FooString() { ...

  1. canvas
  2. canada
  3. cancelled
  4. canceled vs cancelled
  5. canada vaccines
  6. canada goose
  7. cane corso
  8. canes
  9. canadian prime minister
  10. cancun flights
  11. canker sore
  12. candy
  13. cancer
  14. cancun
  15. canon
  16. canvas prints
  17. cancer sign
  18. candace owens
  19. canada news
  20. candytopia

I have two states in my current apps, which is login and register. If I just open my website towards localhost:8001, it is automatically redirect to /login because I've set $urlRouterProvider....

I have two states in my current apps, which is login and register. If I just open my website towards localhost:8001, it is automatically redirect to /login because I've set $urlRouterProvider....

  1. angularjs route reload
  2. angularjs router reload page
  3. angularjs routing reload page
  4. angularjs reload routing
  5. angularjs ui-router reload current state
  6. angularjs ui router reload
  7. angularjs ui router reload parent state
  8. angularjs ui router reload page
  9. angularjs ui router reload state
  10. angularjs router force reload
  11. angularjs ui router reload controller
  12. angularjs ui-router force reload