TDD – Correct test attached to $ SCOPE

According to angular.js source:

$q promises are recognized by the templating engine in angular, which means that in templates you can treat promises attached to a scope as if they were the resulting values.

So, I have a controller that gets the list of categories from the backend,

function myController($scope, $categoryService) {
...
$scope.categoriesList = categoryService.search().then(function(response) {< br /> return response;
}
...
}

I have a choice in my template:

“Work” in the browser (select display fill List)

But how do you test it?

I have the following specifications:

it('populates the categoriesList from the categoryService ', inject(function(categoryService, $q, $controller, $rootScope) {
var $scope = $rootScope.$new();
var catList = [{id:1, name:" Animal"},{id:2, name:"Vegetable"}];
var deferred = $ q.defer()
spyOn(categoryService,'search').andReturn(deferred.promise);

$controller(myController, {'$scope': $scope});< br /> expect(categoryService.search).toHaveBeenCalled(); // PASSES

deferred.resolve(catList);
$scope.$digest();

expect($scope.categoriesList).toEqual(catList); // FAILS, returns the promise instead
}));

If I rewrite my initializer like this< /p>

...then(function(response) {
$scope.categoriesList = response;
}

My test will Passed, but then I did not assign the scope to the scope, nor did the template engine resolve the promise to me. In my opinion, the first implementation is the intent of the framework, but it is not testable. The second implementation is testable , But not the expected way to append data to the scope.

when you say

$scope.categoriesList = categoryService.search().then(function(response) {
return response;
}

$scope.categoriesList is not assigned a response; instead, it is assigned a new promise, which will resolve to the response (as shown in the test). Since the initial promise has resolved the response, you may only have:

< p>

$scope.categoriesList = categoryService.search()

The document means that you can add $scope.c ategoriesList is assigned to such a promise, and the view treats the expression categoryList as the value it resolves (response in this case) – it doesn’t actually accept the value and assign it to the scope.

[Update]

If you are testing the controller, not the category service itself, I will keep the promise in full – it may look like this:

it ('populates the categoriesList from the categoryService', inject(function(categoryService, $controller, $rootScope) {
var $scope = $rootScope.$new();
var catList = [{id: 1, name:"Animal"},{id:2, name:"Vegetable"}];
spyOn(categoryService,'search').andReturn(catList);

$controller (myController, {'$scope': $scope});
expect(categoryService.search).toHaveBeenCalled();

$scope.$digest();
< br /> expect($scope.categoriesList).toEqual(catList);
}));

According to angular.js source:

$q promises are recognized by the templating engine in angular, which means that in templates you can treat promises attached to a scope as if they were the resulting values.

p>

So, I have a controller that gets the list of categories from the backend,

function myCon troller($scope, $categoryService) {
...
$scope.categoriesList = categoryService.search().then(function(response) {
return response;
}
...
}

I have a choice in my template:

“work” in the browser (select to display the filled list)

but you How to test it?

I have the following specifications:

it('populates the categoriesList from the categoryService', inject(function(categoryService, $q, $controller, $ rootScope) {
var $scope = $rootScope.$new();
var catList = [{id:1, name:"Animal"},{id:2, name:"Vegetable"} ];
var deferred = $q.defer()
spyOn(categoryService,'search').andReturn(deferred.promise);

$controller(myController, {' $scope': $scope});
expect(categoryService.search).toHaveBeenCalled(); // PASSES

deferred.resolve(catList);
$scope.$ digest();

expect($scope.categoriesList).toEqual(catList); // FAILS, returns the promise instead
}));

If I I rewrote my initializer like this

...then(function(response) {
$scope.categoriesList = response;
}< /pre>

My test will pass, but then I did not assign the scope to the scope, and the template engine did not resolve the promise to me. In my opinion, the first implementation is the intent of the framework, but it is not Tested. The second implementation is testable, but it is not the intended method of appending data to the scope.

When you say

$scope.categoriesList = categoryService.search().then(function(r esponse) {
return response;
}

$scope.categoriesList is not assigned a response; instead, it is assigned a new promise, which will resolve to a response (as in the test Show). Since the initial promise has resolved the response, you may only have:

$scope.categoriesList = categoryService.search()

The meaning of the document Yes, you can assign $scope.categoriesList to such a promise, and the view will treat the expression categoryList as the value it resolves (response in this case)-it doesn't actually accept the value and assign it to Scope.

[Update]

If you are testing the controller, rather than the category service itself, I will keep the promise in full – it might look like this:

it('populates the categoriesList from the categoryService', inject(function(categoryService, $controller, $rootScope) {
var $scope = $rootScope.$new();
var catList = [{id:1, name:"Animal"},{id:2, name:"Vegetable"}];
spyOn(categoryService,'search').andReturn(catList);

$controller(myController, {'$scope': $scope});
expect(categoryService.search).toHaveBeenCalled();

$scope.$digest ();

expect($scope.categoriesList).toEqual(catList);
}));

Leave a Comment

Your email address will not be published.