Here is my code:
function sendRequestData(url, urlParameters) {
$.ajax({
url : url,
method : 'POST',
headers : {
'Accept' : 'application/json'
},
contentType : 'application/json',
data : JSON.stringify(urlParameters),
dataType : "json",
success : function(data) {
successCallBack(data)
},
error : function(data, status, errorThrown) {
failCallBack(data, status, errorThrown)
}
});
I want to mock and test this ajax call. Is there anyway I can do that?
If your test are hard to test, this means you are doing something wrong.
In your specific case, you need follow Dependency Inversion principle (think Dependency Injection) and inject your requirements into your function. Basically, you need to pass in all the dependencies including $, successCallback and failCallback. This would let you mock your ajax calls with Jasmine's spyOn() method and then check for correct function calls.
function sendRequestData(url, urlParameters, $, successCallBack, failCallBack) {
$.ajax({
url : url,
method : 'POST',
headers : {
'Accept' : 'application/json'
},
contentType : 'application/json',
data : JSON.stringify(urlParameters),
dataType : "json",
success : function(data) {
successCallBack(data)
},
error : function(data, status, errorThrown) {
failCallBack(data, status, errorThrown)
}
});
}
Your tests might look like this. I have not checked it, but you get an idea of what I mean.
describe("sendRequestData() does correct ajax calls", function() {
var $ok, $error, successCallback, failCallback = null;
beforeEach(function() {
// You can create a spy object using this syntax
$ok = jasmine.createSpyObj('$', ['ajax']);
// Or define it yourself like so
$ok = {
ajax: function(value) {
successCallback();
}
};
$error = {
ajax: function(value) {
failCallback();
}
};
spyOn($, 'ajax');
spyOn(successCallback);
spyOn(failCallback);
});
it("calls successCallback on success", function() {
sendRequestData('url', {}, $ok, successCallback, failCallback);
expect($.ajax).toHaveBeenCalled();
expect(successCallback).toHaveBeenCalled();
expect(failCallbackCallback).not.toHaveBeenCalled();
});
it("calls failCallback on failure", function() {
sendRequestData('url', {}, $error, successCallback, failCallback);
expect($.ajax).toHaveBeenCalled();
expect(successCallback).not.toHaveBeenCalled();
expect(failCallbackCallback).toHaveBeenCalled();
});
});
Or simply use jasmine-ajax plugin to mock your ajax calls.
If you are doing this on legacy code and cannot change the JS code maybe you can try as below
JS file
$.ajax({
async : true,
type : "POST",
data : requestPayload,
url : APIURL,
contentType: "application/json",
success : function (response) {
/* -- some code here --*/
},
error : function (errorResponse) {
/* -- some code here --*/
}
});
SPEC file
it("check api call", function () {
var testResponse = {
'status' : 'ok',
'errorCode' : '',
'message' : 'this is a mock response'
};
/*...*/
spyOn($, 'ajax').and.callFake(function(e) {
return e.success(testResponse);
// for failure case
//return e.error({
// 'status' : 'not_ok',
// 'errorCode' : 'Unauthorized'
//});
});
form.submit();
});
You can also call the e.success and
return $.Deferred().resolve(testData).promise(); from what I have understood in other examples.
Mocking jQuery ajax calls with Jasmine
spyOn($, 'ajax').and.callFake(function (e) {
e.success(testData)
return $.Deferred().resolve(testData).promise();
});
Related
I have this function in my UsersController. I created this JSON response by using the _serialize key:
public function test() {
$arrEmail = $this->User->find('first');
$this->set('foo', $arrEmail);
$this->set('_serialize', array('foo') );
}
Now in the client side, in my phonegap application, I am trying to access this data. So I put the following:
<script>
$( document ).ready(function() {
alert(1);
$.ajax({
url : "http://localhost/database/users/" + 'test.json',
async : false,
cache : false,
crossDomain: true,
dataType : 'json',
type : 'post',
success : function(result) {
alert('success');
alert(JSON.stringify(result));
},
error : function(xhr, status, err) {
//con failed
alert(err+' '+xhr+' '+status);
}
});
});
</script>
The alert gives me the following .
Now I need to access to the username and the other attributes. I tried result.attributename but i always get undefined as a response.
EDIT:
`result.foo.User.id` solved the issue.
I am now trying to build a dnn module using ajax calls. But there is a jquery error stating
SyntaxError: Unexpected token <
I have tried to work around with ajax "url: " and tried to create a new ascx at the root folder but still showing error 404.
My ajax call is as below
$.ajax({
url: "NewsManagement.ascx/Add",
contentType: "application/json; charset=utf-8",
dataType: "json",
method: "POST",
beforeSend: function () {
},
cache: false,
data: {
title : $('#txt_Title').val(),
news_content : $('#txt_Content').val(),
image : $('#file_Image').val(),
chapter_id : $('#sel_Chapter').val(),
is_draft : $('#chk_Draft').val(),
posted_date : $('#dp_PostDate').val(),
created_by : "",
lastupdate_by : ""
},
success: function (data) {
console.log(data);
if (data == "success") {
console.log(data);
}
else {
initMdlError("SERVER : " + data);
}
},
error: function (data, textStatus, error) {
// ERROR IS BEING CALLED FROM HERE
console.log("JQUERY JAVASCRIPT : " + error);
initMdlError(error);
},
complete: function () {
console.log('complete');
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Is there any way to solve the issues?
The problem you're running into is that DNN isn't handling the requested URL properly that you are calling. If you want to call a service URL in DNN you're going to want to setup routes to handle the calls.
namespace Christoc.Com.Modules.SlidePresentation.services
{
public class SlidePresentationRouteMapper : IServiceRouteMapper
{
public void RegisterRoutes(IMapRoute mapRouteManager)
{
mapRouteManager.MapRoute("SlidePresentation", "{controller}.ashx/{action}",
new[] {"Christoc.Com.Modules.SlidePresentation.services"});
}
}
}
In the Controller you can define the methods available
[DnnAuthorize(AllowAnonymous = true)]
public ActionResult ListOfSlides()
{
try
{
var slides = Slide.GetSlides(ActiveModule.TabID, ActiveModule.ModuleID);
return Json(slides, JsonRequestBehavior.AllowGet);
}
catch (Exception exc)
{
DnnLog.Error(exc);
return Json(null, JsonRequestBehavior.AllowGet);
}
}
https://slidepresentation.codeplex.com/SourceControl/latest#DesktopModules/SlidePresentation/services/SlidePresentationController.cs
sample Javascript
//get slides on initialization
this.init = function(element) {
//var data = {}; //removed because we don't need this
//data.moduleId = moduleId; //removed because we don't need this when calling setModuleHeaders
//data.tabId = tabId; //removed because we don't need this
//serviceFramework.getAntiForgeryProperty(); //removed because we don't need this
$.ajax({
type: "POST",
cache: false,
url: baseServicePath + 'ListOfSlides',
//data: data,
//dataType:"json",
beforeSend: serviceFramework.setModuleHeaders
}).done(function(data) {
viewModel.slides = ko.utils.arrayMap(data, function(s) {
return new slide(s);
});
ko.applyBindings(viewModel);
$(element).jmpress();
}).fail(function () {
Console.Log('Sorry failed to load Slides');
});
};
Here's an example module that does this
https://slidepresentation.codeplex.com/
And a user group video I did years ago on this module.
https://www.youtube.com/watch?v=hBqn5TsLUxA
For a functionality that I need, I found a really nice AJAX example. Basically it calls the Yahoo API. But I'm working with Angular.JS. So I have no clue how to convert that. Any help?
That's the AJAX function (details see this posting and this JsFiddle):
$.ajax({
type: 'GET',
dataType: 'jsonp',
jsonp: 'callback',
jsonpCallback: 'YAHOO.Finance.SymbolSuggest.ssCallback',
data:{
query: request.term
},
url: 'http://autoc.finance.yahoo.com/autoc',
success: function (data) {
alert("yes");
},
error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.status);
alert(thrownError);
}
});
So what I'm looking for, is how to convert the code above into somewhat like this. The sample should just print the return value. See this JsFiddle. Especially, I have not idea what to do with the jsonpCallback parameter. That's what I could not find in any other example.
<div ng-app='MyModule' ng-controller='DefaultCtrl'>
{{ test() }}
</div>
JavaScript
function DefaultCtrl($scope, myService) {
$scope.test = myService.test;
}
angular.module('MyModule', [])
.factory('myService', function () {
return {
test: function () {
$http.get("?????")
.success(function(data, status, headers, config) {
return data;
})
.error(function(data, status, headers, config) {
return "there was an error";
})
}
}
});
The intermediate solution - after all your help - looks like this. Thanks. I had to install a Chrome extension which allows cross-domain calls as long as you use the updated JsFiddle. I changed the way I'm passing the parameters to the http-get call and I also included the $q (promise) handling. The result contains a valid list from Yahoo YQL API. Just need to handle that array then.
function DefaultCtrl($log, $scope, $http, myService) {
var promise = myService.getSuggestions('yahoo');
promise.then(
function(payload) {
$scope.test = payload;
$log.info('received data', payload);
},
function(errorPayload) {
$log.error('failure loading suggestions', errorPayload);
});
}
angular.module('MyModule', [])
.factory('myService', function ($http, $log, $q) {
return {
getSuggestions: function (symbol) {
var deferred = $q.defer();
$http.get('http://d.yimg.com/autoc.finance.yahoo.com/autoc', {
cache: true,
params: {
query: symbol,
callback: 'YAHOO.Finance.SymbolSuggest.ssCallback'
}
})
.success(function(data) {
deferred.resolve(data);
})
.error(function(msg, code) {
deferred.reject(msg);
$log.error(msg, code);
});
return deferred.promise;
}
}
});
just have a look at the docs
https://docs.angularjs.org/api/ng/service/$http
$http.get('http://autoc.finance.yahoo.com/autoc',
{dataType: 'jsonp',
jsonp: 'callback',
jsonpCallback: 'YAHOO.Finance.SymbolSuggest.ssCallback'}).success(function(data){ alert("yes"); });
Use Ajax call and you have to use promise
And use only test not {{test()}}
Because in your controller when you call your factory ajax function then in controller you get undefined response.
So use promise.
Service:
var demoService = angular.module('demoService', [])
.service('myService',['$http', function($http) {
this.getdata = function(entity){
var promise = $http({
method : 'GET',
url : 'services/entity/add',
data : entity,
dataType: 'jsonp',
jsonp: 'callback',
jsonpCallback: 'YAHOO.Finance.SymbolSuggest.ssCallback',
headers : {
'Content-Type' : 'application/json'
},
cache : false
}).then(function (response) {
return response;
});
return promise;
};
}]);
Controller :
var demoService = angular.module('demoService', [])
.controller('myctr',['$scope','myService',function($scope,myService){
myService.getdata().then(function(response){
//Success
},function(response){
//Error
});
}]);
now you can see your json in controller success
I'm trying to call Javascript function inside controller action method, Is there any right way to call setTimeout() to be invoked on certain condition inside controller action method ?
window.setTimeout(function() {
alert("test");
$.ajax({
type: "POST",
url: "'.$this->createUrl("/operator/createViopNode/").'",
data: {
id: '.$bc_id.',
callid:"'.$num.'",
taskid:'.$this->taskid.'
},
success: function(msg){
var ifrm = document.getElementById("frame");
ifrm = (ifrm.contentWindow) ? ifrm.contentWindow : (ifrm.contentDocument.document) ? ifrm.contentDocument.document : ifrm.contentDocument;
ifrm.document.open();
ifrm.document.write(msg);
ifrm.document.close();
},
error: function (jqXHR, textStatus, errorThrown){
alert("" + textStatus + ", " + errorThrown);
}
});
}, parseInt('.$tps_call.'));
I need to write above js function inside controller action method, how to write this ?
Index.csHtml
function abc()
{
alert("called")
}
now Ajax Call function
function ExecuteAjax(URL,Data,Success)
{
try {
$.ajax({
type: "post",
url: URL,
data: Data,
contentType: "json",
success: function (data) { if (typeof Success == "function") { Success(data); } }
})
} catch (e) {
alert(e.message)
}
}
Call ajax like this
ExecuteAjax("/Home/FillColorDropDown", "", function (data) {
eval(data.script);
});
return from controller
if(demo=="true")//put condition here whatever you want
{
string strscript="abc();";
}
protected JObject jobj = new JObject();
jobj.Add("Script", strscript);
return Json(jobj);
Execute js function when controller return success
You should register your javascript function like this:
function actionTest(){
$cs = Yii::app()->clientScript;
$cs->registerScript('my_script', 'alert("Hi there!");', CClientScript::POS_READY);
$this->render('any_view');
}
source
I am trying to get data from ajax call by cross domain.
Here is code
function GetMaxWULen() {
var x;
$.ajax({
url : url,
method : 'POST',
jsonp : "callback",
async : false,
data : {
Function : "GetMaxWULen",
Authorization : Base64.encode(login + ":" + token),
WuType : $("#ddlWUType").val()
},
dataType : 'jsonp',
crossDomain : true,
error : function(request, status, error) {
alert('nie udało sie');
alert(error);
}
}).done(function(result) {
console.log('done result');
x = result;
console.log(x);
});
console.log('function end');
console.log(x);}
At the end of the function, x variable is undefined but in done event value is correct.
Could anyone can help me or tell what is wrong in this code?
This happens because your AJAX request is done asynchronously. It means the rest of your code won't wait your response be ready to continue.
If you need to use the data returned from AJAX outside your function, you might want to create a parameter to serve as a callback when the response is ready. For example:
function yourFunction(callback) {
$.ajax({
/* your options here */
}).done(function(result) {
/* do something with the result here */
callback(result); // invokes the callback function passed as parameter
});
}
And then call it:
yourFunction(function(result) {
console.log('Result: ', result);
});
Fiddle: http://jsfiddle.net/9duek/
try
$.ajax({
url : url,
method : 'POST',
jsonp : "callback",
async : false,
data : {
Function : "GetMaxWULen",
Authorization : Base64.encode(login + ":" + token),
WuType : $("#ddlWUType").val()
},
dataType : 'jsonp',
crossDomain : true,
error : function(request, status, error) {
alert('nie udało sie');
alert(error);
}
}).success(function(result) {
var datareturned = result.d;
console.log('done' + datareturned);
x = datareturned;
console.log(x);
});