Checking HTTP Status Code in Selenium - selenium

How to get the HTTP status code in Selenium?
E.g. so I can test that if the browser requests /user/27 and no user with ID=27 exists, an HTTP 404 is returned?
My primary interest is Selenium RC, but if someone knows the answer for "normal" selenium, I can probably easily translate it into RC.
/Pete

This might not be the best use of Selenium for this type of test. There is unnecessary need to load a browser when you could do and have a faster running test
[Test]
[ExpectedException(typeof(WebException), UserMessage = "The remote server returned an error: (404) Not Found")]
public void ShouldThrowA404()
{
HttpWebRequest task; //For Calling the page
HttpWebResponse taskresponse = null; //Response returned
task = (HttpWebRequest)WebRequest.Create("http://foo.bar/thiswontexistevenifiwishedonedayitwould.html");
taskresponse = (HttpWebResponse)task.GetResponse();
}
If your test is redirecting to another page during a 404 Selenium could check the final page has what you expect.

I know this is a shocking hack, but this is what I've done:
protected void AssertNotYellowScreen()
{
var selenium = Selenium;
if (selenium.GetBodyText().Contains("Server Error in '/' Application."))
{
string errorTitle = selenium.GetTitle();
Assert.Fail("Yellow Screen of Death: {0}", errorTitle);
}
}
It gets the job done in the situation I needed it for, although I accept it's not ideal...

Since Selenium 2 includes HtmlUnit, you can utilize it in order to get access to the response directly.
public static int getStatusCode(long appUserId) throws IOException {
WebClient webClient = new WebClient();
int code = webClient.getPage(
"http://your.url/123/"
).getWebResponse().getStatusCode();
webClient.closeAllWindows();
return code;
}

You probably want to check out the captureNetworkTraffic() call. Right now it only works reliably with Firefox, unless you manually set up IE/Safari/etc to proxy traffic through port 4444.
To use it, just call selenium.start("captureNetworkTraffic=true"), and then later on in your script you can call selenium.captureNetworkTraffic("...") where "..." is "plain", "xml", or "json".

I haven't tried it, but if you don't mind limiting yourself to Firefox, and installing Firebug and Netexport, then Selenium can get access to the page status code (and everything else in Firebug's Net panel): http://selenium.polteq.com/en/using-netexport-to-export-firebugs-net-panel/

Try this, people
WebClient wc = new WebClient();
int countRepeats = 120; // one wait = 0.5 sec, total 1 minute after this code
boolean haveResult = false;
try {
HtmlPage pageHndl = wc.getPage(Urls);
for(int iter=0; iter<countRepeats; iter++){
int pageCode = pageHndl.getWebResponse().getStatusCode();
System.out.println("Page status "+pageCode);
if(pageCode == 200){
haveResult = true;
break;
}
else{
Thread.sleep(500);
}
}
} catch (IOException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}

If all else fails you could adapt your server side code, during testing, to output the HTTP status in the page as an element:
For example, on my 403 Permission Denied page, I have:
<h1 id="web_403">403 Access Denied</h1>
which can be easily checked via the WebDriver API:
public boolean is403(WebDriver driver) {
try {
driver.findElement(By.id("web_403"));
return true;
} catch (NoSuchElementException e) {
return false;
}
}
https://rogerkeays.com/how-to-get-the-http-status-code-in-selenium-webdriver

Related

WebRequest HTTP error code without try-catch (VB.NET) [duplicate]

I am in a situation where when I get an HTTP 400 code from the server, it is a completely legal way of the server telling me what was wrong with my request (using a message in the HTTP response content)
However, the .NET HttpWebRequest raises an exception when the status code is 400.
How do I handle this? For me a 400 is completely legal, and rather helpful. The HTTP content has some important information but the exception throws me off my path.
It would be nice if there were some way of turning off "throw on non-success code" but if you catch WebException you can at least use the response:
using System;
using System.IO;
using System.Web;
using System.Net;
public class Test
{
static void Main()
{
WebRequest request = WebRequest.Create("http://csharpindepth.com/asd");
try
{
using (WebResponse response = request.GetResponse())
{
Console.WriteLine("Won't get here");
}
}
catch (WebException e)
{
using (WebResponse response = e.Response)
{
HttpWebResponse httpResponse = (HttpWebResponse) response;
Console.WriteLine("Error code: {0}", httpResponse.StatusCode);
using (Stream data = response.GetResponseStream())
using (var reader = new StreamReader(data))
{
string text = reader.ReadToEnd();
Console.WriteLine(text);
}
}
}
}
}
You might like to encapsulate the "get me a response even if it's not a success code" bit in a separate method. (I'd suggest you still throw if there isn't a response, e.g. if you couldn't connect.)
If the error response may be large (which is unusual) you may want to tweak HttpWebRequest.DefaultMaximumErrorResponseLength to make sure you get the whole error.
I know this has already been answered a long time ago, but I made an extension method to hopefully help other people that come to this question.
Code:
public static class WebRequestExtensions
{
public static WebResponse GetResponseWithoutException(this WebRequest request)
{
if (request == null)
{
throw new ArgumentNullException("request");
}
try
{
return request.GetResponse();
}
catch (WebException e)
{
if (e.Response == null)
{
throw;
}
return e.Response;
}
}
}
Usage:
var request = (HttpWebRequest)WebRequest.CreateHttp("http://invalidurl.com");
//... (initialize more fields)
using (var response = (HttpWebResponse)request.GetResponseWithoutException())
{
Console.WriteLine("I got Http Status Code: {0}", response.StatusCode);
}
Interestingly, the HttpWebResponse.GetResponseStream() that you get from the WebException.Response is not the same as the response stream that you would have received from server. In our environment, we're losing actual server responses when a 400 HTTP status code is returned back to the client using the HttpWebRequest/HttpWebResponse objects. From what we've seen, the response stream associated with the WebException's HttpWebResponse is generated at the client and does not include any of the response body from the server. Very frustrating, as we want to message back to the client the reason for the bad request.
I had similar issues when trying to connect to Google's OAuth2 service.
I ended up writing the POST manually, not using WebRequest, like this:
TcpClient client = new TcpClient("accounts.google.com", 443);
Stream netStream = client.GetStream();
SslStream sslStream = new SslStream(netStream);
sslStream.AuthenticateAsClient("accounts.google.com");
{
byte[] contentAsBytes = Encoding.ASCII.GetBytes(content.ToString());
StringBuilder msg = new StringBuilder();
msg.AppendLine("POST /o/oauth2/token HTTP/1.1");
msg.AppendLine("Host: accounts.google.com");
msg.AppendLine("Content-Type: application/x-www-form-urlencoded");
msg.AppendLine("Content-Length: " + contentAsBytes.Length.ToString());
msg.AppendLine("");
Debug.WriteLine("Request");
Debug.WriteLine(msg.ToString());
Debug.WriteLine(content.ToString());
byte[] headerAsBytes = Encoding.ASCII.GetBytes(msg.ToString());
sslStream.Write(headerAsBytes);
sslStream.Write(contentAsBytes);
}
Debug.WriteLine("Response");
StreamReader reader = new StreamReader(sslStream);
while (true)
{ // Print the response line by line to the debug stream for inspection.
string line = reader.ReadLine();
if (line == null) break;
Debug.WriteLine(line);
}
The response that gets written to the response stream contains the specific error text that you're after.
In particular, my problem was that I was putting endlines between url-encoded data pieces. When I took them out, everything worked. You might be able to use a similar technique to connect to your service and read the actual response error text.
Try this (it's VB-Code :-):
Try
Catch exp As WebException
Dim sResponse As String = New StreamReader(exp.Response.GetResponseStream()).ReadToEnd
End Try
An asynchronous version of extension function:
public static async Task<WebResponse> GetResponseAsyncNoEx(this WebRequest request)
{
try
{
return await request.GetResponseAsync();
}
catch(WebException ex)
{
return ex.Response;
}
}
This solved it for me:
https://gist.github.com/beccasaurus/929007/a8f820b153a1cfdee3d06a9c0a1d7ebfced8bb77
TL;DR:
Problem:
localhost returns expected content, remote IP alters 400 content to "Bad Request"
Solution:
Adding <httpErrors existingResponse="PassThrough"></httpErrors> to web.config/configuration/system.webServer solved this for me; now all servers (local & remote) return the exact same content (generated by me) regardless of the IP address and/or HTTP code I return.

Continue session in Selenium cannot getAttribute()

I have created a session in Selenium, re-use it by getting the session id, local_url and put into a different session. That means the new session will continue the original session. Function getAttribute() does not work on the continued session but if I put it in the original session, it works fine. I only face the problem with getAttribute() while other selenium functions such as getText(), getCss() worked well.
This is the re-use code:
RemoteWebDriver driver = createDriverFromSession(session_id, local_url);
System.out.println(driver.findElement(By.xpath(xpath)).getAttribute(attribute));
Output:
{message=unknown error: a.getAttributeNode is not a function
(Session info: chrome=67.0.3396.99)
(Driver info: chromedriver=2.40.565498 (ea082db3280dd6843ebfb08a625e3eb905c4f5ab),platform=Windows NT 10.0.14393 x86_64)}
Somebody please help me. Thanks!
I did face some issue --> message=unknown error: a.getAttributeNode is not a function
As i started debugging more - I figured out - Chrome is not using W3C Codec. So i changed code to reflect accordingly. Changed capabilities as well.
new W3CHttpCommandCodec to new JsonHttpCommandCodec()
new W3CHttpResponseCodec to new JsonHttpResponseCodec()
new RemoteWebDriver(executor, new DesiredCapabilities()) to return
new RemoteWebDriver(url, DesiredCapabilities.chrome())
This worked for my sample. Using selenium version 3.14.0 But believe it shouldn't matter.
The answer above worked for me, but I wanted to provide a little more context.
I originally looked for a way to re-attach to an existing Selenium session instead of opening a new one. I found the createDriverFromSession method (below) from another article on the web (I can't find it to link it). That article contained the code below. I commented out the lines that needed changed from the answer above.
public static RemoteWebDriver createDriverFromSession(final SessionId sessionId, URL command_executor){
CommandExecutor executor = new HttpCommandExecutor(command_executor) {
#Override
public Response execute(Command command) throws IOException {
Response response = null;
if (command.getName() == "newSession") {
response = new Response();
response.setSessionId(sessionId.toString());
response.setStatus(0);
response.setValue(Collections.<String, String>emptyMap());
try {
Field commandCodec = null;
commandCodec = this.getClass().getSuperclass().getDeclaredField("commandCodec");
commandCodec.setAccessible(true);
// commandCodec.set(this, new W3CHttpCommandCodec());
commandCodec.set(this, new JsonHttpCommandCodec());
Field responseCodec = null;
responseCodec = this.getClass().getSuperclass().getDeclaredField("responseCodec");
responseCodec.setAccessible(true);
// responseCodec.set(this, new W3CHttpResponseCodec());
responseCodec.set(this, new JsonHttpResponseCodec());
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
} else {
response = super.execute(command);
}
return response;
}
};
// return new RemoteWebDriver(executor, new DesiredCapabilities());
return new RemoteWebDriver(executor, DesiredCapabilities.chrome());
}
I have also finally resolved this issue. It was something to do with W3C like mentioned above.
I was doing this:
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.setExperimentalOption("w3c", false);
capabilities.setCapability("chromeOptions", chromeOptions);
I simply removed these caps and it worked as intended.

httpwebrequest in windows phone 8 app throws "The remote server returned an error: NotFound."?

i am developing an windows phone 8 app , in my app i am calling services and downloading some data into my app.
i am testing my app in windows phone 8 emulator, many times it throws this error :
"The remote server returned an error: NotFound."
This is how i have created and used my httpwebrequest :-
public async Task<string> ServiceRequest(string serviceurl, string request, string methodname)
{
string response = "";
try
{
var httpwebrequest = WebRequest.Create(new Uri(serviceurl)) as HttpWebRequest;
httpwebrequest.Method = "POST";
httpwebrequest.Headers["SOAPAction"] = "http://tempuri.org/" + iTestservice + "/" + methodname + "";
httpwebrequest.ContentType = "text/xml";
byte[] data = Encoding.UTF8.GetBytes(request);
using (var requestStream = await Task<Stream>.Factory.FromAsync(httpwebrequest.BeginGetRequestStream, httpwebrequest.EndGetRequestStream, null))
{
await requestStream.WriteAsync(data, 0, data.Length);
}
var httpTask = httpRequest(httpwebrequest);
var completeTask = await Task.WhenAny(httpTask, TaskEx.Delay(300000));
if (completeTask == httpTask)
return await httpTask;
else
httpwebrequest.Abort();
throw new TimeoutException("Service Timed Out");
}
catch (TimeoutException Tex)
{
throw Tex;
}
catch (Exception ex)
{
throw ex;
}
}
public async Task<string> httpRequest(HttpWebRequest request)
{
string received;
using (var response = (HttpWebResponse)(await Task<WebResponse>.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null)))
{
using (var responseStream = response.GetResponseStream())
{
using (var sr = new StreamReader(responseStream))
{
received = await sr.ReadToEndAsync();
}
}
}
return received;
}
i am really not able to figure what was the issue
Please note :-
i tried to open the site (service URL which my app is trying to access) in my emulator browser , it opened correctly , i wasn't facing any issues.
1)is that the problem with my code, if so i request you please correct me ??
2)is this any emulator issue or any connectivity issue ??
3)is this any certification issue opening in emulator ??
Even after a long research to how to fix the issue i was not able to fix it .
Please Help me out.
Thanks in Advance.
I have come across this issue when the webservice requests take longer than 60 seconds. I have read reports that the emulator does not throw this error, but only an actual device. In my experience however, I have had this happen on both emulator and device. This is a default timeout setting that cannot be altered, even if you change it in the config. This issue has been around since WP7.
I've only found this question asked/blogged about once elsewhere. Seems that not a lot of people have picked this up.
AFAIK, Microsoft are aware of this, but don't plan on fixing it. (Proven by the fact that it has been around since WP7, and wasn't fixed for WP8). My guess is that they are of the opinion that web calls shouldn't be taking longer than 60 seconds in any case.
I just resolved it adding empty credentials to https requests, like this
httpwebrequest.Credentials = new NetworkCredential("", "");
here he explains why
http://blog.toetapz.com/2010/11/15/windows-phone-7-and-making-https-rest-api-calls-with-basic-authentication/

Selenium C# Webdriver How to detect if element is visible

Is there a way in the latest version of Selenium DotNet Webdriver (2.22.0) to check to see if an element is visible before clicking/interacting with it?
The only way I've found is to try to handle the ElementNotVisible exception that occurs when you try to send keys, or click on it. Unfortunately this only occurs after an attempt to interact with the element has been made. I'm using a recursive function to find elements with a certain value, and some of these elements are only visible in certain scenarios (but their html is still there no matter what, so they can be found).
It's my understanding that the RenderedWebElement class is deprecated as well other variants. So no casting to that.
Thanks.
For Java there is isDisplayed() on the RemoteWebElement - as well is isEnabled()
In C#, there is a Displayed & Enabled property.
Both must be true for an element to be on the page and visible to a user.
In the case of "html is still there no matter what, so they can be found", simply check BOTH isDisplayed (Java) / Displayed (C#) AND isEnabled (Java) / Enabled (C#).
Example, in C#:
public void Test()
{
IWebDriver driver = new FirefoxDriver();
IWebElement element = null;
if (TryFindElement(By.CssSelector("div.logintextbox"), out element)
{
bool visible = IsElementVisible(element);
if (visible)
{
// do something
}
}
}
public bool TryFindElement(By by, out IWebElement element)
{
try
{
element = driver.FindElement(by);
}
catch (NoSuchElementException ex)
{
return false;
}
return true;
}
public bool IsElementVisible(IWebElement element)
{
return element.Displayed && element.Enabled;
}
It seems the current answer to this question is outdated: With WebDriver 3.13 both the Displayed and Enabled properties will return true as long as the element exists on the page, even if it is outside of the viewport. The following C# code works for WebDriver 3.13 (from this StackOverflow answer):
{
return (bool)((IJavaScriptExecutor)Driver).ExecuteScript(#"
var element = arguments[0];
var boundingBox = element.getBoundingClientRect();
var cx = boundingBox.left + boundingBox.width/2, cy = boundingBox.top + boundingBox.height/2;
return !!document.elementFromPoint(cx, cy);
", element);
}
There is a simple way to do that, follow below:
public bool ElementDisplayed(By locator)
{
new WebDriverWait(driver, TimeSpan.FromSeconds(timeOut)).Until(condition: ExpectedConditions.PresenceOfAllElementsLocatedBy(locator));
return driver.FindElement(locator).Displayed ;
}
You can use the following:
WebDriver web = new FirefoxDriver(;
String visibility = web.findElement(By.xpath("//your xpath")).getCssValue("display");

Returning binary content from a JPF action with Weblogic Portal 10.2

One of the actions of my JPF controller builds up a PDF file and I would like to return this file to the user so that he can download it.
Is it possible to do that or am I forced to write the file somewhere and have my action forward a link to this file? Note that I would like to avoid that as much as possible for security reasons and because I have no way to know when the user has downloaded the file so that I can delete it.
I've tried to access the HttpServletResponse but nothing happens:
getResponse().setContentLength(file.getSize());
getResponse().setContentType(file.getMimeType());
getResponse().setHeader("Content-Disposition", "attachment;filename=\"" + file.getTitle() + "\"");
getResponse().getOutputStream().write(file.getContent());
getResponse().flushBuffer();
We have something similar, except returning images instead of a PDF; should be a similar solution, though, I'm guessing.
On a JSP, we have an IMG tag, where the src is set to:
<c:url value="/path/getImage.do?imageId=${imageID}" />
(I'm not showing everything, because I'm trying to simplify.) In your case, maybe it would be a link, where the href is done in a similar way.
That getImage.do maps to our JPF controller, obviously. Here's the code from the JPF getImage() method, which is the part you're trying to work on:
#Jpf.Action(forwards = {
#Jpf.Forward(name = FWD_SUCCESS, navigateTo = Jpf.NavigateTo.currentPage),
#Jpf.Forward(name = FWD_FAILURE, navigateTo = Jpf.NavigateTo.currentPage) })
public Forward getImage(final FormType pForm) throws Exception {
final HttpServletRequest lRequest = getRequest();
final HttpServletResponse lResponse = getResponse();
final HttpSession lHttpSession = getSession();
final String imageIdParam = lRequest.getParameter("imageId");
final long header = lRequest.getDateHeader("If-Modified-Since");
final long current = System.currentTimeMillis();
if (header > 0 && current - header < MAX_AGE_IN_SECS * 1000) {
lResponse.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
return null;
}
try {
if (imageIdParam == null) {
throw new IllegalArgumentException("imageId is null.");
}
// Call to EJB, which is retrieving the image from
// a separate back-end system
final ImageType image = getImage(lHttpSession, Long
.parseLong(imageIdParam));
if (image == null) {
lResponse.sendError(404, IMAGE_DOES_NOT_EXIST);
return null;
}
lResponse.setContentType(image.getType());
lResponse.addDateHeader("Last-Modified", current);
// public: Allows authenticated responses to be cached.
lResponse.setHeader("Cache-Control", "max-age=" + MAX_AGE_IN_SECS
+ ", public");
lResponse.setHeader("Expires", null);
lResponse.setHeader("Pragma", null);
lResponse.getOutputStream().write(image.getContent());
} catch (final IllegalArgumentException e) {
LogHelper.error(this.getClass(), "Illegal argument.", e);
lResponse.sendError(404, IMAGE_DOES_NOT_EXIST);
} catch (final Exception e) {
LogHelper.error(this.getClass(), "General exception.", e);
lResponse.sendError(500);
}
return null;
}
I've actually removed very little from this method, because there's very little in there that I need to hide from prying eyes--the code is pretty generic, concerned with images, not with business logic. (I changed some of the data type names, but no big deal.)