I'm kind of new on Cypress intercept, but I am in need of capturing the response to a GET message, but wait for the message which has a response body with a specific value on its body.
For example, I may be receiving two responses to two GET requests, such as these two:
Event: request
cypress_runner.js:190995 Resource type: xhr
cypress_runner.js:190995 Method: GET
cypress_runner.js:190995 Url: https://127.0.0.1/api/users/61a68c4a1d2c5258baece19c?_=1638304841558
cypress_runner.js:190995 Matched `cy.intercept()`: {RouteMatcher: {…}, RouteHandler Type: 'Spy', RouteHandler: undefined, Request: {…}, Response: {…}, …}
cypress_runner.js:190995 Response status code: 200
cypress_runner.js:190995 Response headers: {date: 'Tue, 30 Nov 2021 20:40:43 GMT', Content-Encoding: 'gzip', server: 'nginx', Vary: 'Accept-Encoding', access-control-allow-methods: 'PUT, GET, POST, DELETE, OPTIONS, PATCH', …}
cypress_runner.js:190995 Response body: {"name": "Alice", "description": "Created by Cypress"}
Event: request
cypress_runner.js:190995 Resource type: xhr
cypress_runner.js:190995 Method: GET
cypress_runner.js:190995 Url: https://127.0.0.1/api/users/61a68c4a1d2c5258baece19c?_=1638304841558
cypress_runner.js:190995 Matched `cy.intercept()`: {RouteMatcher: {…}, RouteHandler Type: 'Spy', RouteHandler: undefined, Request: {…}, Response: {…}, …}
cypress_runner.js:190995 Response status code: 200
cypress_runner.js:190995 Response headers: {date: 'Tue, 30 Nov 2021 20:40:43 GMT', Content-Encoding: 'gzip', server: 'nginx', Vary: 'Accept-Encoding', access-control-allow-methods: 'PUT, GET, POST, DELETE, OPTIONS, PATCH', …}
cypress_runner.js:190995 Response body: {"name": "Bob", "description": "Created by Cypress"}
My intercept for now looks like this:
cy.intercept("GET", "/api/users/*").as("waitingForUpdateOnAlice")
cy.wait("#waitingForUpdateOnAlice")
But if the server returns the answer for Bob, then I don't have the chance of continue waiting.
Is there a way to handle this?
Mention: I do NOT have control or access to the trailing id on the url, so I do need to do this filtering only upon the response body.
First of all, declare a function to be used recursively:
function doIntercept(functionToWait){
cy.wait("#"+functionToWait).then((res)=>{
if(res.response.body.name === 'Bob') {
doIntercept("#"+functionToWait);
} else {
assert(res.response.body.name).to.be.eq('Alice');
}
})
}
then in your test section:
it("your test", ()=>{
cy.intercept("GET", "/api/users/*").as("waitingForUpdateOnAlice");
doIntercept("waitingForUpdateOnAlice");
})
You can alias an individual request. This should accomplish what you'd like.
cy.intercept("GET", "/api/users/*", (req) => {
if (req.body.name.equals('Alice')) {
req.alias = 'waitingForUpdateOnAlice'
}
});
cy.wait('#waitingForUpdateOnAlice');
You might need to play around with the exact form of that req.body.name conditional.
receive undefined value in hidden input
return Response::make($this->filepond->getServerIdFromPath($filePath), 200, [
'Content-Type' => 'text/plain',
]);
HTTP/1.0 200 OK
Cache-Control: no-cache, private
Content-Type: text/plain
Date: Mon, 25 May 2020 11:01:01 GMT
eyJpdiI6Ik1wWEY0UmNSNlRJR.....==
response generated correct but in filepond hidden receive undefined
<input type="hidden" name="filepond" value="undefined">
this is my server setting
FilePond.setOptions({
server: {
url: 'http://localhost/gadmin/public/filepond/api',
timeout: 7000,
process: {
url: '/process',
method: 'POST',
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
onload: (response) => response.key,
onerror: (response) => response.data,
ondata: (formData) => {
return formData;
}
},
}
});
The onload function is only needed if for example your server returns a JSON string and you need to select a certain property from it. In your situation the process end point returns a text/plain response with an id, this allows FilePond to automatically use the returned id as the file id. So that's why the onload function isn't needed.
See: https://pqina.nl/filepond/docs/patterns/api/server/#process
server returns unique location id 12345 in text/plain response
I have a machine on my local lan (machineA) that has two web servers. The first is the in-built one in XBMC (on port 8080) and displays our library. The second server is a CherryPy python script (port 8081) that I am using to trigger a file conversion on demand. The file conversion is triggered by a AJAX POST request from the page served from the XBMC server.
Goto http://machineA:8080 which displays library
Library is displayed
User clicks on 'convert' link which issues the following command -
jQuery Ajax Request
$.post('http://machineA:8081', {file_url: 'asfd'}, function(d){console.log(d)})
The browser issues a HTTP OPTIONS request with the following headers;
Request Header - OPTIONS
Host: machineA:8081
User-Agent: ... Firefox/4.01
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Origin: http://machineA:8080
Access-Control-Request-Method: POST
Access-Control-Request-Headers: x-requested-with
The server responds with the following;
Response Header - OPTIONS (STATUS = 200 OK)
Content-Length: 0
Access-Control-Allow-Headers: *
Access-Control-Max-Age: 1728000
Server: CherryPy/3.2.0
Date: Thu, 21 Apr 2011 22:40:29 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Content-Type: text/html;charset=ISO-8859-1
The conversation then stops. The browser, should in theory, issue a POST request as the server responded with the correct (?) CORS headers (Access-Control-Allow-Origin: *)
For troubleshooting, I have also issued the same $.post command from http://jquery.com. This is where I am stumped, from jquery.com, the post request works, a OPTIONS request is sent following by a POST. The headers from this transaction are below;
Request Header - OPTIONS
Host: machineA:8081
User-Agent: ... Firefox/4.01
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Origin: http://jquery.com
Access-Control-Request-Method: POST
Response Header - OPTIONS (STATUS = 200 OK)
Content-Length: 0
Access-Control-Allow-Headers: *
Access-Control-Max-Age: 1728000
Server: CherryPy/3.2.0
Date: Thu, 21 Apr 2011 22:37:59 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Content-Type: text/html;charset=ISO-8859-1
Request Header - POST
Host: machineA:8081
User-Agent: ... Firefox/4.01
Accept: */*
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://jquery.com/
Content-Length: 12
Origin: http://jquery.com
Pragma: no-cache
Cache-Control: no-cache
Response Header - POST (STATUS = 200 OK)
Content-Length: 32
Access-Control-Allow-Headers: *
Access-Control-Max-Age: 1728000
Server: CherryPy/3.2.0
Date: Thu, 21 Apr 2011 22:37:59 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Content-Type: application/json
I can't work out why the same request would work from one site, but not the other. I am hoping someone might be able to point out what I am missing. Thanks for your help!
I finally stumbled upon this link "A CORS POST request works from plain javascript, but why not with jQuery?" that notes that jQuery 1.5.1 adds the
Access-Control-Request-Headers: x-requested-with
header to all CORS requests. jQuery 1.5.2 does not do this. Also, according to the same question, setting a server response header of
Access-Control-Allow-Headers: *
does not allow the response to continue. You need to ensure the response header specifically includes the required headers. ie:
Access-Control-Allow-Headers: x-requested-with
REQUEST:
$.ajax({
url: "http://localhost:8079/students/add/",
type: "POST",
crossDomain: true,
data: JSON.stringify(somejson),
dataType: "json",
success: function (response) {
var resp = JSON.parse(response)
alert(resp.status);
},
error: function (xhr, status) {
alert("error");
}
});
RESPONSE:
response = HttpResponse(json.dumps('{"status" : "success"}'))
response.__setitem__("Content-type", "application/json")
response.__setitem__("Access-Control-Allow-Origin", "*")
return response
I solved my own problem when using google distance matrix API by setting my request header with Jquery ajax. take a look below.
var settings = {
'cache': false,
'dataType': "jsonp",
"async": true,
"crossDomain": true,
"url": "https://maps.googleapis.com/maps/api/distancematrix/json?units=metric&origins=place_id:"+me.originPlaceId+"&destinations=place_id:"+me.destinationPlaceId+"®ion=ng&units=metric&key=mykey",
"method": "GET",
"headers": {
"accept": "application/json",
"Access-Control-Allow-Origin":"*"
}
}
$.ajax(settings).done(function (response) {
console.log(response);
});
Note what i added at the settings
**
"headers": {
"accept": "application/json",
"Access-Control-Allow-Origin":"*"
}
**
I hope this helps.
Took me some time to find the solution.
In case your server response correctly and the request is the problem, you should add withCredentials: true to the xhrFields in the request:
$.ajax({
url: url,
type: method,
// This is the important part
xhrFields: {
withCredentials: true
},
// This is the important part
data: data,
success: function (response) {
// handle the response
},
error: function (xhr, status) {
// handle errors
}
});
Note: jQuery >= 1.5.1 is required
Well I struggled with this issue for a couple of weeks.
The easiest, most compliant and non hacky way to do this is to probably use a provider JavaScript API which does not make browser based calls and can handle Cross Origin requests.
E.g. Facebook JavaScript API and Google JS API.
In case your API provider is not current and does not support Cross Origin Resource Origin '*' header in its response and does not have a JS api (Yes I am talking about you Yahoo ),you are struck with one of three options-
Using jsonp in your requests which adds a callback function to your URL where you can handle your response.
Caveat this will change the request URL so your API server must be equipped to handle the ?callback= at the end of the URL.
Send the request to your API server which is controller by you and is either in the same domain as the client or has Cross Origin Resource Sharing enabled from where you can proxy the request to the 3rd party API server.
Probably most useful in cases where you are making OAuth requests and need to handle user interaction Haha! window.open('url',"newwindowname",'_blank', 'toolbar=0,location=0,menubar=0')
This is a summary of what worked for me:
Define a new function (wrapped $.ajax to simplify):
jQuery.postCORS = function(url, data, func) {
if(func == undefined) func = function(){};
return $.ajax({
type: 'POST',
url: url,
data: data,
dataType: 'json',
contentType: 'application/x-www-form-urlencoded',
xhrFields: { withCredentials: true },
success: function(res) { func(res) },
error: function() {
func({})
}
});
}
Usage:
$.postCORS("https://example.com/service.json",{ x : 1 },function(obj){
if(obj.ok) {
...
}
});
Also works with .done,.fail,etc:
$.postCORS("https://example.com/service.json",{ x : 1 }).done(function(obj){
if(obj.ok) {
...
}
}).fail(function(){
alert("Error!");
});
Server side (in this case where example.com is hosted), set these headers (added some sample code in PHP):
header('Access-Control-Allow-Origin: https://not-example.com');
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Max-Age: 604800');
header("Content-type: application/json");
$array = array("ok" => $_POST["x"]);
echo json_encode($array);
This is the only way I know to truly POST cross-domain from JS.
JSONP converts the POST into GET which may display sensitive information at server logs.
Using this in combination with Laravel solved my problem. Just add this header to your jquery request Access-Control-Request-Headers: x-requested-with and make sure that your server side response has this header set Access-Control-Allow-Headers: *.
I had the exact same issue where jquery ajax only gave me cors issues on post requests where get requests worked fine - I tired everything above with no results. I had the correct headers in my server etc. Changing over to use XMLHTTPRequest instead of jquery fixed my issue immediately. No matter which version of jquery I used it didn't fix it. Fetch also works without issues if you don't need backward browser compatibility.
var xhr = new XMLHttpRequest()
xhr.open('POST', 'https://mywebsite.com', true)
xhr.withCredentials = true
xhr.onreadystatechange = function() {
if (xhr.readyState === 2) {// do something}
}
xhr.setRequestHeader('Content-Type', 'application/json')
xhr.send(json)
Hopefully this helps anyone else with the same issues.
This function will asynchronously get an HTTP status reply from a CORS-enabled page. Only a page with the proper headers returns a 200 status if accessed via XMLHttpRequest -- whether GET or POST is used. Nothing can be done on the client side to get around this except possibly using JSONP if you just need a json object.
The following can be modified to get the data held in the xmlHttpRequestObject object:
function checkCorsSource(source) {
var xmlHttpRequestObject;
if (window.XMLHttpRequest) {
xmlHttpRequestObject = new XMLHttpRequest();
if (xmlHttpRequestObject != null) {
var sUrl = "";
if (source == "google") {
var sUrl = "https://www.google.com";
} else {
var sUrl = "https://httpbin.org/get";
}
document.getElementById("txt1").innerHTML = "Request Sent...";
xmlHttpRequestObject.open("GET", sUrl, true);
xmlHttpRequestObject.onreadystatechange = function() {
if (xmlHttpRequestObject.readyState == 4 && xmlHttpRequestObject.status == 200) {
document.getElementById("txt1").innerHTML = "200 Response received!";
} else {
document.getElementById("txt1").innerHTML = "200 Response failed!";
}
}
xmlHttpRequestObject.send();
} else {
window.alert("Error creating XmlHttpRequest object. Client is not CORS enabled");
}
}
}
<html>
<head>
<title>Check if page is cors</title>
</head>
<body>
<p>A CORS-enabled source has one of the following HTTP headers:</p>
<ul>
<li>Access-Control-Allow-Headers: *</li>
<li>Access-Control-Allow-Headers: x-requested-with</li>
</ul>
<p>Click a button to see if the page allows CORS</p>
<form name="form1" action="" method="get">
<input type="button" name="btn1" value="Check Google Page" onClick="checkCorsSource('google')">
<input type="button" name="btn1" value="Check Cors Page" onClick="checkCorsSource('cors')">
</form>
<p id="txt1" />
</body>
</html>
If for some reasons while trying to add headers or set control policy you're still getting nowhere you may consider using apache ProxyPass…
For example in one <VirtualHost> that uses SSL add the two following directives:
SSLProxyEngine On
ProxyPass /oauth https://remote.tld/oauth
Make sure the following apache modules are loaded (load them using a2enmod):
proxy
proxy_connect
proxy_http
Obviously you'll have to change your AJAX requests url in order to use the apache proxy…
This is a little late to the party, but I have been struggling with this for a couple of days. It is possible and none of the answers I found here have worked. It's deceptively simple.
Here's the .ajax call:
<!DOCTYPE HTML>
<html>
<head>
<body>
<title>Javascript Test</title>
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript">
$(document).domain = 'XXX.com';
$(document).ready(function () {
$.ajax({
xhrFields: {cors: false},
type: "GET",
url: "http://XXXX.com/test.php?email='steve#XXX.com'",
success: function (data) {
alert(data);
},
error: function (x, y, z) {
alert(x.responseText + " :EEE: " + x.status);
}
});
});
</script>
</body>
</html>
Here's the php on the server side:
<html>
<head>
<title>PHP Test</title>
</head>
<body>
<?php
header('Origin: xxx.com');
header('Access-Control-Allow-Origin:*');
$servername = "sqlxxx";
$username = "xxxx";
$password = "sss";
$conn = new mysqli($servername, $username, $password);
if ($conn->connect_error) {
die( "Connection failed: " . $conn->connect_error);
}
$sql = "SELECT email, status, userdata FROM msi.usersLive";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
echo $row["email"] . ":" . $row["status"] . ":" . $row["userdata"] . "<br>";
}
} else {
echo "{ }";
}
$conn->close();
?>
</body>
Trying to create a switch for a global session variable the ajax call never returns "success" nor "error".
The actions are called and the Session keys are set, but the success/error functions are never fired.
It is weird because I use the same structure with other calls to replace divs and it works.
Javascript
doesn't work
function SwitchHelpMode() {
debugger;
var helpmode = true;
$.ajax({
type: 'GET',
url: '/Session/GetSessionKey',
contentType: "application/json; charset=utf-8",
dataType: "json",
data: { key: "helpmode" },
sucess: function (data) {
alert(data);
//debugger;
//var ok = data.success;
//if (ok) {
// var algo = data.value;
// alert(algo);
// helpmode = !algo;
//}
},
error: function (xhr) {
//debugger;
alert(xhr);
alert('ERROR::SetSessionKey!' + xhr.responseText);
}
});
helpmode = false;
$.ajax({
type: 'GET',
url: '/Session/SetSessionKey',
data: { key: "helpmode", value: helpmode },
sucess: function (data) {
alert(data);
},
error: function (xhr) {
debugger;
alert('ERROR::SetSessionKey!' + xhr.responseText);
}
});
}
Controller
public ActionResult SetSessionKey(string key, string value)
{
Session[key] = value;
return Json(new { success = true }, JsonRequestBehavior.AllowGet);
}
public ActionResult GetSessionKey(string key)
{
if(Session[key] != null)
{
var value = Session[key];
return Json(new { success = true, data = value }, JsonRequestBehavior.AllowGet);
}
else
{
return Json(new { success = false }, JsonRequestBehavior.AllowGet);
}
}
Javascript works
function FilterInfoByFlightsCallback(values) {
//debugger;
var data = JSON.stringify(values);
var url = '/Campaign/FilterInfoByFlights';
$.ajax({
type: 'GET',
url: url,
data: { filter: data },
success: function (result) {
$('#infoList').html(result);
},
error: function (result) {
// handle errors
location.href = "/MindMonitor/"
}
});
}
Responses from inspector
http://localhost:50518/Session/GetSessionKey?key=helpmode
{"success":true,"data":"false"}
http://localhost:50518/Session/SetSessionKey?key=helpmode&value=false
{"success":true}
HTTP/1.1 200 OK
Cache-Control: private
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/8.0
X-AspNetMvc-Version: 5.2
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?
UzpcVlNTb3VyY2VcUHJvamVrdGVcTU1JXGJmdWVudGVzXE1NSVxNaW5kc2hhcmUuTU1JXE1NSVxTZXNzaW9uXEdldFNlc3Npb25LZXk=?=
Persistent-Auth: true
X-Powered-By: ASP.NET
WWW-Authenticate: Negotiate oRswGaADCgEAoxIEEAEAAABDh+CIwTbjqQAAAAA=
Date: Tue, 07 Jul 2015 12:45:03 GMT
Content-Length: 31
HTTP/1.1 200 OK
Cache-Control: private
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/8.0
X-AspNetMvc-Version: 5.2
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?
UzpcVlNTb3VyY2VcUHJvamVrdGVcTU1JXGJmdWVudGVzXE1NSVxNaW5kc2hhcmUuTU1JXE1NSVxTZXNzaW9uXFNldFNlc3Npb25LZXk=?=
Persistent-Auth: true
X-Powered-By: ASP.NET
WWW-Authenticate: Negotiate oRswGaADCgEAoxIEEAEAAABDh+CIwTbjqQAAAAA=
Date: Tue, 07 Jul 2015 12:45:03 GMT
Content-Length: 16
Any idea?
There is no extra c in - sucess: function (data) { because of this even though the response from server would be 200 OK but it will not fire traditional success because it is not able to find one.
It should be - success: function (data) {
AJAX can be difficult to troubleshoot if you don't have a lot of experience with it. The Developer Tools (or FireBug) available for all modern browsers are your friend. They make it much easier to see/understand what the server is returning as a response.
Since the request is using Ajax, the browser won't render any error pages that are returned.
Using Chrome (the other tools are similar and usually opened with CTRL + SHIFT + I or F12):
Open the Developer Tools pane with (CTRL + SHIFT + I).
Click the Network tab.
Click your page element to fire the click handler and send the Ajax request.
Find and click the network request in the Network tab (bottom-left).
The pane next to the network request has Tabs for 'Headers', 'Preview' and 'Response'.
Headers will show you the contents of the request (what got sent to the server).
Response will show you the content of the servers response. This might be JSON for a successful request or it might be HTML source for an error page if an error occured.
The Preview tab will render the servers Response (if possible). This is especially helpful if you receive an error response/page from the server since you won't have to wade through the raw HTML to find the error details.
If your AJAX call is failing, and your server returns a 500 error, you can always check your server logs or look at the Network > Preview tab to see the error detail that is returned. You can troubleshoot the error just as you would any traditional server response.
I build a page for mobiles, but i have problem when i send a POST with jQuery.ajax on my phone. It's works on my PC but not on my phone.
I have this code when i make the post request:
window.jQuery.ajax({
type: "POST",
url: "/Action/PageHandler.ashx?do=" + method,
cache: false,
data : postFormData,
dataType: "json",
success: function (data) {
DataHandler.GetResult(data, callBack);
},
error: function (oXhr, status, msg) {
callBack(false, msg);
}
});
The response when i use my phone is this:
HTTP/1.1 200 OK
Server: ASP.NET Development Server/11.0.0.0
Date: Wed, 25 Dec 2013 17:20:00 GMT
p3p: CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"
Cache-Control: private
Content-Type: application/json; charset=utf-8
Connection: Close
Content-Length: 69
{"ErrorMessage":"Wrong pasword or username!"}
When i run this code on my phone, the error function is called, status = error and msg is empty. I use jQuery mobile.
What's wrong with my code?