0

Trying to understand how do jasmine tests work. I've got a module and a controller:

var app = angular.module('planApp', []);

app.controller('PlanCtrl', function($scope, plansStorage){
var plans = $scope.plans = plansStorage.get();

$scope.formHidden = true;

$scope.togglePlanForm = function() {
    this.formHidden = !this.formHidden;
};

$scope.newPlan = {title: '', description: ''}   ;

$scope.$watch('plans', function() {
    plansStorage.put(plans);
}, true);

$scope.addPlan = function() {
    var newPlan = {
        title: $scope.newPlan.title.trim(),
        description: $scope.newPlan.description
    };

    if (!newPlan.title.length || !newPlan.description.length) {
        return;
    }

    plans.push({
        title: newPlan.title,
        description: newPlan.description
    });

    $scope.newPlan = {title: '', description: ''};
    $scope.formHidden = true;

};

});

plansStorage.get() is a method of a service that gets a json string from localstorage and returns an object.

When I run this test:

var storedPlans = [
  {
    title: 'Good plan',
    description: 'Do something right'
  },
  {
    title: 'Bad plan',
    description: 'Do something wrong'
  }
];

describe('plan controller', function () {
  var ctrl,
  scope,
  service;


  beforeEach(angular.mock.module('planApp'));
  beforeEach(angular.mock.inject(function($rootScope, $controller, plansStorage) {

    scope = $rootScope.$new();
    service = plansStorage;

    spyOn(plansStorage, 'get').andReturn(storedPlans);


    ctrl = $controller('PlanCtrl', {
      $scope: scope,
      plansStorage: service
    });

    spyOn(scope, 'addPlan')

  }));

  it('should get 2 stored plans', function(){
    expect(scope.plans).toBeUndefined;
    expect(service.get).toHaveBeenCalled();
    expect(scope.plans).toEqual([
  {
    title: 'Good plan',
    description: 'Do something right'
  },
  {
    title: 'Bad plan',
    description: 'Do something wrong'
  }
    ]);
  });

  it('should add a plan', function() {
    scope.newPlan = {title: 'new', description: 'plan'};
    expect(scope.newPlan).toEqual({title: 'new', description: 'plan'});
    scope.addPlan();

    expect(scope.addPlan).toHaveBeenCalled();

    expect(scope.plans.length).toEqual(3);
  });

});

first test passes ok, but second one fails. The length of the scope.plans expected to be 3, but it is 2. scope.plans didn't change after scope.addPlan() call.

If I understand that right, the $scope inside addPlan method is not the same as scope that I trying to test in second test.

The question is why? And how do I test the addPlan method?

1 Answer 1

1

the solution is just to add andCallThrough() method after spy:

spyOn(scope, 'addPlan').andCallThrough()
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.