I have written a NodeJs client that generates API requests for various combinations and stores the responses in an array. By looping a Jasmine script I am trying to assert them. However my tests run before it initialize the API responses array. I have tried two approaches and no luck so far.
Approach 1:
var answersReq = require('../requests/answers_request');
var data = answersReq.answers(function(results) {
return results;
})
describe("Answer API test", function() {
function runTest(context) {
describe("test array suite", function() {
it("test array", function(done) {
expect(context).not.toBeNull();
done();
});
});
}
for (i = 0; i <= data.length; i++) {
runTest(data[i]);
}
});
Approach 2:
var answersReq = require('../requests/answers_request');
var data;
describe("Answer API test", function() {
beforeAll(function(done) {
data = answersReq.answers(function(results) {
data = results;
done();
})
});
function runTest(context) {
describe("test array suite", function() {
it("test array", function(done) {
expect(context).not.toBeNull();
done();
});
});
}
for (i = 0; i <= data.length; i++) {
runTest(data[i]);
}
});
works for me, double check what's in data
/*** CODE ***/
var data = [1,1,1,1,1]
describe("Answer API test", function() {
function runTest(context) {
describe("test array suite", function() {
it("test array", function(done) {
expect(context).not.toBeNull();
done();
});
});
}
for (i = 0; i <= data.length; i++) {
runTest(data[i]);
}
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.4.1/jasmine.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.4.1/jasmine.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.4.1/jasmine-html.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.4.1/boot.min.js"></script>
Related
I have 20 data packet in the client and I am pushing one by one to the server via Ajax post. Each call take approximately one minute to yield the response. Is there any way to make few of these requests run parallel.
I have used Jquery promise. However, still the request waiting for the prior one to get completed.
var dataPackets=[{"Data1"},{"Data2"},{"Data3"},{"Data4"},{"Data5"},
{"Data6"},{"Data7"},{"Data8"},{"Data9"},{"Data10"},
{"Data11"},{"Data12"},{"Data13"},{"Data14"},{"Data15"},{"Data16"},
{"Data17"},{"Data18"},{"Data19"},{"Data20"}];
$(dataPackets).each(function(indx, request) {
var req = JSON.stringify(request);
setTimeout({
$.Ajax({
url: "sample/sampleaction",
data: req,
success: function(data) {
UpdateSuccessResponse(data);
}
});
}, 500);
});
The when...done construct in jQuery runs ops in parallel..
$.when(request1(), request2(), request3(),...)
.done(function(data1, data2, data3) {});
Here's an example:
http://flummox-engineering.blogspot.com/2015/12/making-your-jquery-ajax-calls-parallel.html
$.when.apply($, functionArray) allows you to place an array of functions that can be run in parallel. This function array can be dynamically created. In fact, I'm doing this to export a web page to PDF based on items checked in a radio button list.
Here I create an empty array, var functionArray = []; then based on selected items I push a function on to the array f = createPDF(checkedItems[i].value)
$(document).ready(function () {
});
function sleep(milliseconds) {
var start = new Date().getTime();
for (var i = 0; i < 1e7; i++) {
if ((new Date().getTime() - start) > milliseconds){
break;
}
}
}
function exportPDFCollection() {
var f = null;
var x = 0;
var checkedItems = $("input:checked");
var count = checkedItems.length;
var reportList = $(checkedItems).map(
function () {
return $(this).next("label").text();
})
.get().join(",");
var functionArray = [];
var pdf = null;
for (var i = 0; i < count; i++) {
f = createPDF(checkedItems[i].value)
.done(function () {
pdf = checkedItems[x++].value;
alert('PDF => ' + pdf + ' created.');
})
.fail(function (jqxhr, errorText, errorThrown) {
alert('ajax call failed');
});
functionArray.push(f);
}
$.when.apply($, functionArray)
.done(function () {
$.get("http://yourserver/ExportPage.aspx",{reports: reportList})
.done(function () {
alert('PDF merge complete.');
})
.fail(function (jqxhr, errorText, errorThrown) {
alert('PDF merge failed. Please try again.');
});
return true;
});
}
function createPDF(webPage) {
return $.get(webPage);
}
I've spent a lot of time trying to figure out how to go inside anonymous functions in jasmine.
Sample of method:
numerateColumns: function (rows) {
rows.each(function () {
var $row = $(this);
$row.children().each(function (index) {
var $cell = $(this);
$cell.addClass('column-' + (index + 1));
});
});
}
Try to test with:
it("[TEST] Should call each method.", function () {
// setup
var rows = {
each: function () {
return {
children: function () {
return {
replaceWith: function () {
return null;
}
};
}
};
}
};
spyOn(rows, 'each').and.callThrough();
// method under test
module.numerateColumns(rows);
// expectations
expect(rows.each).toHaveBeenCalled();
});
But coverage test shows me that code of method is read only in first line (rows.each).
How to force it to read all the code inside (function() {}) ?
Why you want to test jQuery? It works perfectly, if not - some tests probably it will catch before new version publication.
function numerateColumns($rows) {
$rows.each(function() {
var $row = $(this);
$row.children().each(function(index) {
var $cell = $(this);
$cell.addClass('column-' + (index + 1));
});
});
}
describe('Iterate over columns`', function() {
var mockRows
beforeEach(function() {
mockRows = $('<div><div></div></div>')
})
it("calls .each() on passed jQuery collection", function() {
spyOn($, 'each').and.callThrough();
expect($.each).not.toHaveBeenCalled();
numerateColumns(mockRows);
expect($.each).toHaveBeenCalled();
});
it("adds CSS class to each child", function() {
var column = $(mockRows[0]).find('div');
expect(column.hasClass('column-1')).toBeFalsy()
numerateColumns(mockRows);
expect(column.hasClass('column-1')).toBeTruthy()
});
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="//safjanowski.github.io/jasmine-jsfiddle-pack/pack/jasmine.css" rel="stylesheet" />
<script src="//safjanowski.github.io/jasmine-jsfiddle-pack/pack/jasmine-2.0.3-concated.js"></script>
What you can test - it is extracted business logic that is independent to jQuery itself.
I am new in Casperjs and I would like do dinamic testing depending on external data sources. But, I am experiencing some problems with the loops.
This is my code:
var url = ['http://google.com/','http://www.as.com'];
casper.test.begin('PruebaLoop', function (test) {
casper.start('about:blank',function() {
});
casper.then(function() {
casper.viewport(1024, 768);
//casper.echo(casper.getTitle());
});
console.log('url.length: ' + url.length)
for (i = 0; i < url.length; i++) {
casper.thenOpen(url[i], function() { // open that link
console.log('i: '+i);
});
casper.wait(5000, function() {
this.echo("I've waited for a 5 seconds.");
});
casper.then(function() {
casper.capture('url'+i+'.png');
});
}
casper.run(function() {
casper.echo('Test completado');
casper.test.done();
});
});
From debugging, I always get 2 as the result. I don't know why. Could you please offer me some help?
Thanks a lot!
my solution is:
var urls = ['http://www.elpais.es','http://www.as.com'];
casper.test.begin('PruebaLoop', function (test) {
casper.start('auto:blank',function() {
console.log("-----------------------------------");
console.log("estoy en start ");
});
casper.then(function() {
casper.viewport(1024, 768);
console.log("estoy en wiewport");
console.log("urls.length = " + urls.length);
console.log("-----------------------------------");
});
for(i = 0; i < urls.length; i++) {
(function(index) {
var url = urls[index]
casper.thenOpen(url, function() {
console.log('index tiene el valor: '+ index);
console.log('i tiene el valor: '+ i);
});
casper.then(function() {
this.wait(5000);
console.log("estoy en wait: "+ index);
});
casper.then(function() {
this.wait(5000);
casper.capture("pagina"+index+".png");
console.log("estoy en capture: " + index);
console.log("-----------------------------------");
});
})(i);
}
casper.run(function() {
casper.echo('Test completado');
casper.test.done();
});
});
it works.
As I want to implement a chat in AngularJS, I want to use the promise/deferred principle. My ChatService looks like the following:
factory('ChatService', ['$q', '$resource', function($q, $resource) {
var Service = {};
var connected = false;
var connection;
var chatResource = $resource('/guitars/chat/:action', {action: '#action'}, {
requestChatroomId: {
params: {
action: 'requestChatroomId'
},
method: 'GET'
},
sendMessage: {
params: {
action: 'sendMessage'
},
method: 'POST'
}
});
Service.connect = function(cb) {
var deferred = $q.defer();
chatResource.requestChatroomId(function(data) {
connection = new WebSocket('ws://127.0.0.1:8888/realtime/' + data.chatroomId);
connection.onerror = function (error) {
deferred.reject('Error: ' + error);
};
connection.onmessage = function (e) {
cb.call(this, e.data);
deferred.notify(e.data);
};
connected = true;
});
return deferred.promise;
};
Service.sendMessage = function(msg) {
if(!connected) {
return;
}
chatResource.sendMessage({message: msg});
}
return Service;
}])
My controller using the ChatService is:
app.controller('ChatCtrl', ['$scope', 'ChatService', function($scope, ChatService) {
$scope.chat = {};
$scope.chat.conversation = [];
var $messages = ChatService.connect(function(message) {
$scope.$apply(function() {
// #1 THIS FIRES EVERY TIME
$scope.chat.conversation.push(message);
});
});
$messages.then(function(message) {
console.log('Finishes - should never occur!')
}, function(error) {
console.log('An error occurred!')
}, function(message) {
// #2 THIS FIRES ONLY IF THERE IS AN INTERACTION WITH THE ANGULAR MODEL
console.log(message);
});
$scope.sendMessage = function(event) {
ChatService.sendMessage($scope.chat.message);
$scope.chat.message = '';
};
}]);
If something is pushed from the server, callback #1 is called, but callback #2 wont be called until there is some interaction with the angular-model, i.e. start writing something in the input-Box. What is the reason for that behaviour?
Okay the reason was, that AngularJS was not aware of a change. So I injected the $rootScope to my ChatService:
factory('ChatService', ['$q', '$resource', '$rootScope', function($q, $resource, $rootScope) {
and in connection.onmessage I called $apply() on $rootScope:
connection.onmessage = function (e) {
deferred.notify(e.data);
$rootScope.$apply();
};
I want to test the "addGroup" function using Jasmine. I get the following error:
Error: Expected spy modifyMyHtml to have been called.at null.
I don't know what is the best way to test the addGroup function. Please HELP.....
var myRecord = {
addGroup: function(groupNumber) {
$.when(myRecord.getHtml())
.done(function(returnedHtml){
myRecord.modifyMyHtml(returnedHtml);
});
},
getHtml: function() {
return $.ajax({url: "myHtmlFile.html", dataType: "html" });
},
// adds options and events to my returned HTML
modifyMyHtml: function(returnedHtml) {
$('#outerDiv').html(returnedHtml);
var myOptions = myRecord.getOptions();
$('#optionsField').append(myOptions);
myRecord.bindEventsToDiv();
},
}
====JASMINE TEST
describe("Configure Record page", function() {
var fixture;
jasmine.getFixtures().fixturesPath = "/test/" ;
jasmine.getFixtures().load("myHtmlFile.html");
fixture = $("#jasmine-fixtures").html();
describe("addGroup", function(){
beforeEach(function() {
var groupNumber = 0;
spyOn(myRecord, "getHtml").andCallFake(function(){
return $.Deferred().promise();
});
spyOn(myRecord, "modifyMyHtml");
myRecord.addGroup(groupNumber);
});
it("Should call getHtml", function() {
expect(myRecord.getHtml).toHaveBeenCalled();
});
it("Should call modifyMyHtml", function() {
expect(myRecord.modifyMyHtml).toHaveBeenCalled(); ==>FAILS
});
});
});
You have to resolve the promise before you return em in your andCallFake.
spyOn(myRecord, "getHtml").andCallFake(function(){
return $.Deferred().resolve ().promise();
});
Btw. you should not test that the function on the object you wanna test are called, but that the html in the DOM are set with the right html
it("Should call modifyMyHtml", function() {
spyOn(myRecord, "getHtml").andCallFake(function(){
return $.Deferred().resolveWith(null, 'returnedHtml').promise();
});
expect($('#outerDiv').html).toEqual('returnedHtml')
});