Unit Testing Angular Controller That Uses Kendo Grid / Datasource
My project is using AngularJS + Kendo-UI. I am trying to test one of my controllers that uses Kendo-UI grid:
angular.module('myApp')('DevicesCtrl', function ($scope) {
$scope.gridOptions = {
dataSource: {
transport: {
read: {
url: "/devices",
dataType: "json"
}
},
change: function(){
var view = this.view();
$scope.devices = [];
$.each(view, function(i, v) {
$scope.devices.push({id: v.id, description: v.name, status: v.status == 0 ? "failure" : "success"});
});
$scope.$apply();
}
},
columns: [
{
field: "name",
title: "Name",
width: 250,
template: function (item) {
var itemStatus = item.status == 0 ? 'failure' : 'success';
return '<div label size="small" operation="' + itemStatus + '" label="' + item.name + '"></div>';
}
},
{
field: "status",
title: "Status"
}
]
};
});
When I wrote my unit test, I expected a GET request to be called:
describe('deviceCtrl', function () {
var scope, deviceCtrl, httpBackend, timeout;
beforeEach(module("myApp"));
beforeEach(module('src/modules/devices/views/device.html'));
beforeEach(inject(function ($controller, $rootScope, $httpBackend, $timeout, $state) {
scope = $rootScope.$new();
httpBackend = $httpBackend;
timeout = $timeout;
httpBackend.expectGET('languages/en_US.json').respond({});
deviceCtrl = $controller("DeviceCtrl", {
$scope: scope
});
$state.go("devices");
timeout.flush()
}));
it('should load the switch list', function () {
httpBackend.expectGET("/devices").respond(
[{"id":"1","name":"name 1","status":"1"},
{"id":"2","name":"name 2","status":"2"}]
);
httpBackend.flush();
});
});
But expectations are never met, requests are not accepted. So my question is, is there a way to make a Kendo Grid / Datasource for this call so I can mock it?
I've seen several examples of how to do this using Mockjax ( http://www.telerik.com/forums/best-practice-mocking-with-datasource ), but I'd rather use angular libraries to accomplish that.
source to share
After a lot of research, I was able to find several ways to test controllers that use the Kendo datasource.
Kendo has its own way of making Ajax requests to fetch data and not using the normal Angular $ http to do it, so it's a bit tricky to test with Angular tools (angular-mocks). Go to options:
1 - Use the normal Angular way for Ajax calls.
Kendo allows us to change the way we get the data, so instead:
dataSource: new kendo.data.DataSource({
transport: {
read: {
url: "/devices,
dataType: "json"
}
},
change: function(){
var view = this.view();
$scope.devices = [];
$.each(view, function(i, v) {
$scope.devices.push({id: v.id, description: v.name, status: v.status == 0 ? "failure" : "success"});
});
$scope.$apply();
}
});
We would change to:
dataSource: new kendo.data.DataSource({
transport: {
read: function(options){
$http.get("/devices").then(function(response){
options.success(response.data);
$scope.devices = [];
response.data.forEach(function(v){
$scope.devices.push({id: v.id, description: v.name, status: v.status == 0 ? "failure" : "success"});
});
});
}
}
});
We can then use the regular $ httpBackend.expectGET (url) to mock the Ajax call. I personally like this approach because we have more control. Ps .: using the variable "parameters" inside the function, we have access to the Grid filter, sorting and paging.
2 - Refuse the Kendo Ajax call.
Thus, we hardly change anything in the controller, the only thing that needs to be changed is to create a new data source using the new kendo.data.DataSource ({}) file, and not just pass parameters. This is necessary because we are calling the read function inside the test case. I've tried different ways to mock this Ajax request, but the only thing I could do is use the Jasmine-Ajax tool . And in the test case, we would write something like:
var request = jasmine.Ajax.requests.mostRecent();
request.response(MockData);
I hope this can help other people.
source to share