Mockjax twice in same test file? - javascript

Using Qunit and MockJax, I seek to have two tests, simplified here for ease of understanding. One of the following two tests fails, presumably because the two tests run in parallel and thus they do not each get their own detour of $.ajax(). (The only difference is the responseText in each.) Any ideas on a good way to tweak it so that both the following tests pass?
function testAjax() {
return $.ajax({
type: 'POST',
dataType: 'json',
url: '/fakeservice/1',
data: {'a':'b'}
});
}
asyncTest("testAjax 1", function () {
$.mockjax({
url: '/fakeservice/1',
type: 'POST',
dataType: 'json',
responseText: { 'name1': 'foo' }
});
testAjax().then(
function (response) {
deepEqual(response.name1, 'foo', "no name1");
start();
},
function (error) {
ok(false, "got AJAX error");
start();
}
);
});
asyncTest("testAjax 2", function () {
$.mockjax({
url: '/fakeservice/1',
type: 'POST',
dataType: 'json',
responseText: { 'name1': 'bar' }
});
testAjax().then(
function (response) {
deepEqual(response.name1, "bar", "no name1");
start();
},
function (error) {
ok(false, "got AJAX error");
start();
}
);
});

You must call $.mockjaxClear() at the end of each test (e.g. in the teardown() method of your module). This destroys the mock and prepares the environment for the next test.
function testAjax() {
return $.ajax({
type: 'POST',
dataType: 'json',
url: '/fakeservice/1',
data: {'a':'b'}
});
}
module("AJAX tests", {
teardown: function() {
$.mockjaxClear();
}
});
asyncTest("testAjax 1", function () {
$.mockjax({
url: '/fakeservice/1',
type: 'POST',
dataType: 'json',
responseText: { 'name1': 'foo' }
});
testAjax().then(
function (response) {
deepEqual(response.name1, 'foo', "no name1");
start();
},
function (error) {
ok(false, "got AJAX error");
start();
}
);
});
asyncTest("testAjax 2", function () {
$.mockjax({
url: '/fakeservice/1',
type: 'POST',
dataType: 'json',
responseText: { 'name1': 'bar' }
});
testAjax().then(
function (response) {
deepEqual(response.name1, "bar", "no name1");
start();
},
function (error) {
ok(false, "got AJAX error");
start();
}
);
});
See your adapted example on jsFiddle.

Related

How to avoid repeating the same $.ajax() call

I have two $.ajax() calls in my javascript code.
$.ajax({
url: 'http://localhost/webmap201/php/load_data.php',
data: {
tbl: 'district'
},
type: 'POST',
success: function(response) {
console.log(JSON.parse(response));
json_district = JSON.parse(response);
district = L.geoJSON(json_district, {
onEachFeature: return_district,
});
ctl_layers.addOverlay(district, "district", "Overlays");
ar_district_object_names.sort();
$("#text_district_find_project").autocomplete({
source: ar_district_object_names,
});
},
error: function(xhr, status, error) {
alert("Error: " + error);
}
}
);
$.ajax({
url: 'http://localhost/webmap201/php/load_data.php',
data: {
tbl: 'province'
},
type: 'POST',
success: function(response) {
console.log(JSON.parse(response));
json_province = JSON.parse(response);
province = L.geoJSON(json_province, {
onEachFeature: return_province,
});
ctl_layers.addOverlay(province, "province", "Overlays");
ar_province_object_names.sort();
$("#text_province_find_project").autocomplete({
source: ar_province_object_names,
});
},
error: function(xhr, status, error) {
alert("Error: " + error);
}
}
);
changes on both ajax are as below:
tbl: 'district' -> tbl: 'province'
json_district -> json_province
return_district -> return_province
(district, "district", "Overlays") -> (province, "province", "Overlays")
ar_district_object_names -> ar_province_object_names
$("#text_district_find_project") -> $("#text_province_find_project")
Is there a way I can call this $.ajax() inside a function with one parameter and call the function afterwards. As an example:
function lyr(shpName){
$.ajax({
url: 'http://localhost/webmap201/php/load_data.php',
data: {
tbl: `${shpName}`
},
type: 'POST',
success: function(response) {
console.log(JSON.parse(response));
json_shpName = JSON.parse(response);
shpName = L.geoJSON(json_shpName, {
onEachFeature: return_shpName,
});
ctl_layers.addOverlay(shpName, `${shpName}`, "Overlays");
ar_shpName_object_names.sort();
$("#text_shpName_find_project").autocomplete({
source: ar_shpName_object_names,
});
},
error: function(xhr, status, error) {
alert("Error: " + error);
}
}
);
}
lyr (district);
Can I use template strings? Can I use that a function inside a function. Any help would be highly appriceated.
Create a function for ajax call.
For eg.:-
function serviceajaxjson(_successfun, _failurefun, _url, _data, _async, _global) {
if (_successfun == null) _successfun = ajax_return_successfun;
if (_failurefun == null) _failurefun = ajax_return_failurefun;
if (_global != false) { _global = true; }
if (_async != false) { _async = true; }
$.ajax({
type: "POST",
url: _url,
data: _data,
global: _global,
contentType: "application/json; charset=utf-8",
dataType: "json",
cache: false,
async: _async,
success: _successfun,
error: ajax_return_error,
failure: _failurefun
});
}
function ajax_return_successfun(response) {
console.info("success for " + response.d);
}
function ajax_return_failurefun(response) {
console.error("failuer occoured for " + response);
}
function ajax_return_error(response) {
console.warn("error occoured for " + response);
}
// // // call the above function
function myResponseFn(response){
if(response.data){
// // your code...
}
}
var data = "{'tbl': 'district'}";
serviceajaxjson(myResponseFn,myResponseFn,"http://localhost/webmap201/php/load_data.php",data);
If you're using latest version of popular browser (IE's dead, use Edge instead), then the simplest answer is yes. You might need some tweaking on the parameters and its use, but it should work

ReferenceError: response is not defined on autocomplete jquery ajax call in singleton design pattern

I am trying to implement jQuery autocomplete in my solution but I got an error ReferenceError: response is not defined
Here is my code
(function ($) {
$.SupportArticleObj = function (p) {
var SupportArticle = {
config: {
isPostBack: false,
async: false,
cache: false,
type: 'POST',
contentType: "application/json; charset=utf-8",
data: { data: '' },
dataType: 'json',
baseURL: "Modules/SupportArticle/Services/SupportArticleWebService.asmx/",
url: "",
method: "",
ajaxCallMode: 0,
PortalID: PortalID,
UserModuleID: UserModuleID,
SecureToken: SecureToken,
UserName: UserName
},
init: function () {
$("#searchSupport").autocomplete({
source: function (request, response) {
searchTerm = request.term;
SupportArticle.getSearchData(searchTerm);
}
});
},
getSearchData: function (searchTearm) {
SupportArticle.config.method = "SearchSupportArticle";
SupportArticle.config.url = SupportArticle.config.baseURL + SupportArticle.config.method;
SupportArticle.config.data = JSON2.stringify({
searchTerm: searchTerm,
portalID: SupportArticle.config.PortalID,
userModuleID: SupportArticle.config.UserModuleID,
userName: SupportArticle.config.UserName,
secureToken: SupportArticle.config.SecureToken
});
SupportArticle.ajaxCall(SupportArticle.config);
},
ajaxSuccess: function (data) {
response(data);
},
ajaxFailure: function () {
jAlert('Somethings went wrong', 'Support Article');
},
ajaxCall: function (config) {
$.ajax({
type: SupportArticle.config.type,
contentType: SupportArticle.config.contentType,
cache: SupportArticle.config.cache,
url: SupportArticle.config.url,
data: SupportArticle.config.data,
dataType: SupportArticle.config.dataType,
success: SupportArticle.ajaxSuccess,
error: SupportArticle.ajaxFailure,
async: SupportArticle.config.async
});
}
};
SupportArticle.init();
};
$.fn.callSupportArticle = function (p) {
$.SupportArticleObj(p);
};
})(jQuery);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.js"></script>
What I am trying to do here is, I am calling a webservice which will search the records on database and return as a list and I want to bind that list on textbox as a autocomplete. But the problem is while running the solution in browser I got an error ReferenceError: response is not defined.
I was trying http://www.c-sharpcorner.com/UploadFile/da55bf/Asp-Net-autocomplete-textbox-using-jquery-json-and-ajax/ as reference.
How can I solve the issue of ReferenceError: response is not defined
Write your script like below:
AutoDemoDataBase: function () {
$("#lytA_ctl29_txtSearchName").autocomplete({
source: function (request, response) {
var param = JSON.stringify({
userModuleID: UserModuleID,
portalID: autoComplete.config.portalId,
prefix: $("#lytA_ctl29_txtSearchName").val(),
userName: autoComplete.config.UserName,
secureToken: SageFrameSecureToken
});
$.ajax({
type: autoComplete.config.type,
contentType: autoComplete.config.contentType,
cache: autoComplete.config.cache,
url: autoComplete.config.baseURL + "GetNames",
data: param,
dataType: autoComplete.config.dataType,
async: autoComplete.config.async,
success: function (data) {
response($.map(data.d, function (item) {
return {
value: item.Name
}
}))
},
error: function (response) {
jAlert(response.responseText);
},
failure: function (response) {
jAlert(response.responseText);
}
});
},
select: function (e, i) {
$("#hfId").val(i.item.val);
$('#test').text(i.item.val);
},
minLength: 1
});
}
Your ajax success function is out of response scope.

jQuery Ajax get value via function?

I have created a save(id) function that will submit ajax post request. When calling a save(id). How to get value/data from save(id) before going to next step. How to solve this?
For example:
function save(id) {
$.ajax({
type: "POST",
url: "/post/",
dataType: "json",
contentType: 'application/json',
data: JSON.stringify({
id: id,
}),
success: function (data) {
return data;
},
error: function (error) {
return data;
}
});
}
Usage:
$('.btn-create').click(function () {
var id = 123;
data = saveArea(id); //get data from ajax request or error data?
if (data) {
window.location = "/post/" + data.something
}
}
You have two options, either run the AJAX call synchronously (not recommended). Or asynchronously using callbacks
Synchronous
As #Drew_Kennedy mentions, this will freeze the page until it's finished, degrading the user experience.
function save(id) {
return $.ajax({
type: "POST",
url: "/post/",
dataType: "json",
contentType: 'application/json',
async: false,
data: JSON.stringify({
id: id,
})
}).responseText;
}
$('.btn-create').click(function () {
var id = 123;
// now this will work
data = save(id);
if (data) {
window.location = "/post/" + data.something
}
}
Asynchronous (recommended)
This will run in the background, and allow for normal user interaction on the page.
function save(id, cb, err) {
$.ajax({
type: "POST",
url: "/post/",
dataType: "json",
contentType: 'application/json',
data: JSON.stringify({
id: id,
}),
success: function (data) {
cb(data);
},
error: err // you can do the same for success/cb: "success: cb"
});
}
$('.btn-create').click(function () {
var id = 123;
save(id,
// what to do on success
function(data) {
// data is available here in the callback
if (data) {
window.location = "/post/" + data.something
}
},
// what to do on failure
function(data) {
alert(data);
}
});
}
Just make things a bit simpler.
For starters just add window.location = "/post/" + data.something to the success callback.
Like this:
function save(id) {
return $.ajax({
type: "POST",
url: "/post/",
dataType: "json",
contentType: 'application/json',
data: JSON.stringify({
id: id,
}),
success:function(data){
window.location = "/post/" + data.something
}
}).responseText;
}
Or by adding all your Ajax code within the click event.
$('.btn-create').click(function () {
var id = "123";
$.ajax({
type: "POST",
url: "/post/",
dataType: "json",
contentType: 'application/json',
data: JSON.stringify({
id: id,
}),
success: function (data) {
window.location = "/post/" + data.something
},
error: function (error) {
console.log(error)
}
});
}

using $.when to execute first ajax then execute the next in $.when().done

I know this has been asked multiple times but I'm having a problem executing $.ajax by order using $.when.
In the sample code below, I want to run the first ajax inside $.when() then the second $.ajax inside .done().
var api = {
getFoo: function(callback) {
$.when(this.getBar()).done(function() {
chrome.storage.local.get(['bar'], function(data) {
// omitted some code here for brevity
$.ajax({
type: 'GET',
url: /api/foo/,
dataType: 'json'
}).done(function(result) {
console.log('success', 'went here!');
}).fail(function(request) {
console.log('failed', 'went here!');
});
});
});
},
getBar: function() {
chrome.storage.local.get(['data1'], function(data) {
if(typeof data['data1'] !== 'undefined') {
// omitted some code here for brevity
$.ajax({
type: 'POST',
url: /api/bar/,
data: data['data1'],
dataType: 'json'
}).done(function(result) {
console.log('success', 'went here!');
}).fail(function(xhr, status, error) {
console.log('failed', 'went here!');
});
}
});
}
}
When I ran the code, the second $.ajax execute immediately without waiting for the first $.ajax to finish. Please, could anyone redirect me to the right way?
We need to return a promise for async actions
try this:
getFoo: function(callback) {
this.getBar().then(function(){
chrome.storage.local.get(['bar'], function(data) {
// omitted some code here for brevity
$.ajax({
type: 'GET',
url: /api/foo/,
dataType: 'json'
}).done(function(result) {
console.log('success', 'went here!');
}).fail(function(request) {
console.log('failed', 'went here!');
});
});
});
},
getBar: function() {
var deferred = $q.defer();
chrome.storage.local.get(['data1'], function(data) {
if(typeof data['data1'] !== 'undefined') {
// omitted some code here for brevity
$.ajax({
type: 'POST',
url: /api/bar/,
data: data['data1'],
dataType: 'json'
}).done(function(result) {
deferred.resolve(result);
}).fail(function(xhr, status, error) {
deferred.reject(error);
});
}
});
return deferred.promise;
}
There is a good example at jQuery - when() page. Here is a short example:
var api = {
flag: $.Deferred(),
getFoo: function(callback) {
$.when(this.flag).done(function() {
console.log('getFoo');
});
},
getBar: function() {
console.log('getBar');
this.flag.resolve();
}
}

AJAX method Jquery can't return data

I can't return the value of an ajax request in Jquery. Here's my code:
function ajaxUniversal(datos, url) {
$.ajax({
url: url,
data: {
valores: datos
},
type: "POST",
dataType: "html",
success: function (data) {
console.log("Datos recibidos: "+data)
return data; //This does not returns the data
},
error: function (errorThrown) {
return false;
}
});
}
And if I add the return statement to the final:
function ajaxUniversal(datos, url) {
$.ajax({
url: url,
data: {
valores: datos
},
type: "POST",
dataType: "html",
success: function (data) {
console.log("Datos recibidos: "+data)
return data;
},
error: function (errorThrown) {
return false;
}
});
return data;//This is the statement but not works
}
And I get this error:
Uncaught ReferenceError: data is not defined
How can I return the data? Thank you. And sorry for my bad english but I speak spanish.
Ajax calls are asynchronous so you can not return value immediately from them. Instead they return a promise to return a value so what you can do is:
function ajaxUniversal(datos, url, callback) {
return $.ajax({
url: url,
data: {
valores: datos
},
type: "POST",
dataType: "html"
});
}
And call it like this:
ajaxUniversal( datos, url, callback ).then( function(data){
//manipulate data here
});
Ajax calls are asynchronous, therefore you cannot return data with them. If you want to use that data, you need to use a callback function instead.
function ajaxUniversal(datos, url, callback) {
$.ajax({
url: url,
data: {
valores: datos
},
type: "POST",
dataType: "html",
success: function (data) {
console.log("Datos recibidos: "+data)
callback(data);
},
error: function (errorThrown) {
callback(errorThrown);
}
});
}
Elsewhere...
ajaxUniversal(someData, someUrl, function(data){
// Do work with data here
console.log(data);
});
As the others have said, this is failing due to the request being asynchronous. You could either fix your code as they suggest, by handling it asynchronously, OR you can set your request to be synchronous using async: false.
function ajaxUniversal(datos, url) {
var data;
$.ajax({
url: url,
async: false, // <---- this will cause the function to wait for a response
data: {
valores: datos
},
type: "POST",
dataType: "html",
success: function (data) {
console.log("Datos recibidos: "+data)
data = data;
}
});
return data;
}
You can't return the item cause it no longer exists. try to define it first, like this:
function ajaxUniversal(datos, url) {
var returlVal;
$.ajax({
url: url,
async: false,
data: {valores: datos},
type: "POST",
dataType: "html",
success: function (data) {
console.log("Datos recibidos: "+data)
returlVal = data;
},
error: function (errorThrown) {
returlVal = false;
}
});
return returlVal;
}

Categories