Selenium test an iterface where misses id and title and other sensible information - selenium

I'm working for a client who wants me to do selenium/junit tests but the whole user interface doesn't show any id for the html code nor title for the page, just content like "Welcome in ...", how whould you do to check that one is on the home page or in the page for the login for example?
This is an example of the html:
<div class="site-body m-welcome" data-module="welcome">
<div class="inner">
<h1 class="starred dark"><span>Welcome to ...</span></h1>
<div class="choices">
<div class="choice">
Become a xxxxx
</div>
<span class="or"><span>Or</span></span>
<form action="http://www.alink/welcome" method="post" class="choice" data-response-type="json">
<input type="text" name="plate_number" id="car_plate_validation_plate_number" value="" maxlength="8" class="plate required numberplate" placeholder="Enter number plate">
<button type="submit" class="btn btn-primary">Become an yyyyy</button>
<div class="invalid-message inline-modal" data-behavior="modal">
<h1>Sorry - you are not eligible to join the company</h1>
<p>See am I eligile? for full eligibility critera.</p>
</div>
</form>
</div>

You can use XPath to find almost all elements, I wouldn't use it often but in your case (where nothing has IDs) you'll probably need to use it very often:
IWebElement element = driver.FindElement(By.XPath, "//*[text='Welcome in ...']");
That will get you the first element of any type that has the text within it of "Welcome in ..."
For checking if you are on a certain page, I guess you'll have to search for an element that is unique to that page and no other pages.
You'll need to show us some of the HTML if you want more specific examples.

Example of html:
<div class="site-body m-welcome" data-module="welcome">
<div class="inner">
<h1 class="starred dark"><span>Welcome to ...</span></h1>
<div class="choices">
<div class="choice">
Become a xxxxx
</div>
<span class="or"><span>Or</span></span>
<form action="http://www.alink/welcome" method="post" class="choice" data-response-type="json">
<input type="text" name="plate_number" id="car_plate_validation_plate_number" value="" maxlength="8" class="plate required numberplate" placeholder="Enter number plate">
<button type="submit" class="btn btn-primary">Become an yyyyy</button>
<div class="invalid-message inline-modal" data-behavior="modal">
<h1>Sorry - you are not eligible to join the company</h1>
<p>See am I eligile? for full eligibility critera.</p>
</div>
</form>
</div>

Related

Generating a valid __RequestVerificationToken from C#

One of the most popular books on ASP.NET Core is "Pro ASP.NET Core 3" by Adam Freeman.
In chapters 7-11, he builds an example application, SportsStore.
As you can see, each product in the listing gets its own 'Add To Cart' button:
If we do 'view source' on this page, we'll see the following HTML for that item in the product list:
<div class="card card-outline-primary m-1 p-1">
<div class="bg-faded p-1">
<h4>
Kayak
<span class="badge badge-pill badge-primary" style="float:right">
<small>$275.00</small>
</span>
</h4>
</div>
<form id="1" method="post" action="/Cart">
<input type="hidden" data-val="true" data-val-required="The ID field is required." id="ID" name="ID" value="1" />
<input type="hidden" name="returnUrl" value="/" />
<span class="card-text p-1">
A boat for one person
<button type="submit" class="btn btn-success btn-sm pull-right" style="float:right">
Add To Cart
</button>
</span>
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8KKqNOS0gwdMvC0-bdjTwWlvCcBJldeidwIX5b2f24gYblS9X1sqCwJWIEsKKOSf8kut0SQsQRLF3R1XBSYZkPGnta9YzRK4tcQl8dq_0uWmjeUhm8yMe90fWDt_x0smmAD1lmb9-BxQF8y_7-IQSz4" /></form>
</div>
Note the input tag towards the bottom:
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8KKqNOS0gwdMvC0-bdjTwWlvCcBJldeidwIX5b2f24gYblS9X1sqCwJWIEsKKOSf8kut0SQsQRLF3R1XBSYZkPGnta9YzRK4tcQl8dq_0uWmjeUhm8yMe90fWDt_x0smmAD1lmb9-BxQF8y_7-IQSz4" />
If we look at the Views\Shared\ProductSummary.cshtml file in the SportsStore project, we'll see the code that is involved with generating these listing items:
#model Product
<div class="card card-outline-primary m-1 p-1">
<div class="bg-faded p-1">
<h4>
#Model.Name
<span class="badge badge-pill badge-primary" style="float:right">
<small>#Model.Price.ToString("c")</small>
</span>
</h4>
</div>
<form id="#Model.ID" asp-page="/Cart" method="post">
<input type="hidden" asp-for="ID" />
<input type="hidden" name="returnUrl" value="#ViewContext.HttpContext.Request.PathAndQuery()" />
<span class="card-text p-1">
#Model.Description
<button type="submit" class="btn btn-success btn-sm pull-right" style="float:right">
Add To Cart
</button>
</span>
</form>
</div>
As you can see, the form element in this case doesn't have an explicit inclusion of the input tag with the __RequestVerificationToken value. This form thus appears to be a tag helper which takes care of generting the input tag with the __RequestVerificationToken token.
As an experiment, let's suppose I have added the following method to Controllers\HomeController:
[HttpGet]
public ContentResult ButtonExample()
{
var token = "...";
return new ContentResult()
{
ContentType = "text/html",
StatusCode = (int)HttpStatusCode.OK,
Content =
String.Format(
#"<!DOCTYPE html>
<html>
<body>
<form id=""1"" method=""post"" action=""/Cart"">
<input type=""hidden"" data-val=""true"" id=""ID"" name=""ID"" value=""1"" />
<button type=""submit"">Add to Cart</button>
</form>
<input name=""__RequestVerificationToken"" type=""hidden"" value=""{0}"" />
</body>
</html>",
token)
};
}
As you can see, this generates a very simple page with a single button which is intended to add the product with ID value 1 (i.e. the Kayak) to the cart.
I of course need to pass an appropriate value for the __RequestVerificationToken.
My question is, is there a way to get this value from C# so that I can include it in the method above?
The idea as shown above would be to set the token value here:
var token = "...";
This is then interpolated into the string that generates the HTML using String.Format.
UPDATE
This page mentions the following:
To generate the anti-XSRF tokens, call the #Html.AntiForgeryToken method from an MVC view or #AntiForgery.GetHtml() from a Razor page.
So I guess the question is, how do we do the equivalent from C# directly instead of from an MVC view or Razor page?
You can add the below code to your form which will generate the __RequestVerificationToken. It is used to prevent CSRF attacks Prevent XSRF/CSRF attacks.
<form action="/" method="post">
#Html.AntiForgeryToken()
</form>

How to Select Radio button inside Fieldset using behat

Can any one please help me out how to select a radio button if it is inside a fieldset??
I can access individual radio button using foreach but when i try to select it or click it its giving some Ajax error.
HTML code is given below
I have tried to select it with radio button's label as well as given in above comment but not able to select it.
<fieldset id="edit-cvs-options" class="form-wrapper">
<legend>
<div class="fieldset-wrapper">
<div class="ios-content" style="display: none;">test</div>
<div class="form-item form-type-radio form-item-use-stored">
<label for="edit-use-stored">
<span>test</span>
<input id="edit-use-stored" class="form-radio" type="radio" name="use_stored" checked="TRUE" value="on" display-title-fix="1"/>
</label>
</div>
<fieldset id="edit-cvs-1" class="form-wrapper" style="display: inline-block;">
<div>
<div class="form-item form-type-radio form-item-use-uploaded">
<label for="edit-use-uploaded">
<span>test</span>
<input id="edit-use-uploaded" class="form-radio" type="radio" name="use_uploaded" display-title-fix="1" value="off"/>
</label>
</div>
</div>
</fieldset>
This is my Behat step definition:
$session = $this->getSession(); // get the mink session
$escapedValue = $session->getSelectorsHandler()->xpathLiteral('use_uploaded');
$radioButton = $session->getPage()->find('named', array('radio', $escapedValue));
$radioButton ->click();

Using Scrapy for Crawling Pages Post Authentication

Taking cues and ideas from a previous post , I tried to come up with my own code.
However, using my code I've noticed that it doesn't really scrape anything and probably doesn't go beyond the authentication level at all. I say this because I don't see any Error Logs even when I put an incorrect password.
My best guess is that the HTML for the authentication fields is not contained in a "Form" tag and hence the formdata is possibly overlooking it. Might be wrong.
My Code so far:
class LoginSpider(BaseSpider):
name = 'auth1'
start_urls = ['http://www.example.com/administration']
def parse(self, response):
return [FormRequest.from_response(response,
formdata={'employee[email]': 'xyz#abc.com', 'employee[password]': 'XYZ'},
formxpath='//div[#class="form-row"]',
callback=self.after_login)]
def after_login(self, response):
if "authentication failed" in response.body:
self.log("Login failed", level=log.ERROR)
return
# We've successfully authenticated, let's have some fun!
else:
return Request(url="http://www.liveyoursport.com/administration/customers",
callback=self.parse_tastypage)
def parse_tastypage(self, response):
sel = Selector(response)
item = Item()
item ["Test"] = sel.xpath("//h1/text()").extract()
yield item
Here's the HTML section:
<div class="content-row">
<div class="special-header-title span_full">
<h3><span class="blue-text">Sign </span>In</h3>
</div>
</div>
<div class="content-row">
<div class="form-section checkout-address-edit span_80" id="sign-in-form" >
<form accept-charset="UTF-8" action="/employees/sign_in" class="new_employee" id="new_employee" method="post"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /><input name="authenticity_token" type="hidden" value="HQYZa0hNZ2Y+UvtbIk9OxI48Hlsnt+MiYOeV9ql2yWo=" /></div>
<div>
<div class="form-row">
<div class="form-col-1"><label for="employee_email">Email</label></div>
<div class="form-col-2">
<input id="employee_email" name="employee[email]" size="30" type="email" value="" />
</div>
</div>
<div class="form-row">
<div class="form-col-1"><label for="employee_password">Password</label></div>
<div class="form-col-2">
<input id="employee_password" name="employee[password]" size="30" type="password" />
</div>
</div>
</div>
<div class="form-row form-row-controls">
<div class="form-col-1"></div>
<div class="form-col-2">
<input class="sign-in-button f-right" name="commit" type="submit" value="Sign in" />
</div>
</div>
</form> <br>
Forgot your password?<br />
Didn't receive unlock instructions?<br />
</div>
From the docs:
formxpath (string) – if given, the first form that matches the xpath
will be used.
but it seems that you are not matching the form, rather the parent div.
Try it like this:
return [FormRequest.from_response(response,
formdata={'employee[email]': 'xyz#abc.com', 'employee[password]': 'XYZ'},
formxpath='//form[#id="new_employee"]',
callback=self.after_login)]
Also, if you only have one form element on the page, you don't need to define formxpath.

How to render a google+ signin button for mobile and web view

I am building a website with a google+ login.
The site is responsive, so i have a different google+ button for web and mobile as follows:
signin button for mobile view -> hidden in web view
<div id="mobile" class="container visible-xs hidden-sm hidden-md hidden-lg">
<div class="row">
<div class="col-xs-12 mobile-signup-form">
<form class="form-signin">
<h2 class="form-heading visible-xs hidden-lg hidden-sm hidden-md">Find great tour guides.</h2>
<input type="text" class="form-control" placeholder="Pick a Username" autofocus>
<input type="text" class="form-control" placeholder="Your email">
<input type="password" class="form-control" placeholder="Create a Password">
<button id="submit-btn" class="btn btn-lg btn-primary btn-block" type="submit">Sign up for Tourbly</button>
<div class="hr-with-words">
<span class="smallor">or</span>
</div>
<div id="gSignInWrapper">
<div id="customBtn_M" class="customGPlusSignIn">
<span class="icon"></span>
<span class="buttonText">Google</span>
</div>
</div>
</form>
</div>
</div>
</div>
signin button for web view -> hidden in mobile view
<div id="gSignInWrapper" ng-show="immediateFailed">
<div id="customBtn" class="customGPlusSignIn">
<span class="icon"></span>
<span class="buttonText">Sign up with Google</span>
</div>
</div>
I use the following JS code to render the button for web view
gapi.signin.render('customBtn', {
'callback': 's_up_c_bks_loc',
'clientid': '1066634592899.apps.googleusercontent.com',
'cookiepolicy': 'single_host_origin',
'requestvisibleactions': 'http://schemas.google.com/AddActivity',
'scope': 'https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.email'
});
I can only pass one id to the render function, how can i get the right button rendered for the right view (mobile or web).
I have tried rendering both but the last one overrides the first.
I'm using angular js, so any suggestions/solutions which makes use of that will be appreciated.
Thanks
You can call the render function more than once, which might be the easiest way. You can move the second parameter to a var which you pass to both calls, or you might want to take advantage of thew new page level config: https://developers.google.com/+/web/signin/reference#page-config
This might be the easiest way, as it will trigger an immediate mode check (see whether the user has previously consented, and fire the callback) as soon as the page loads. This means you could choose which to render at that time, as part of the immediate failed (I notice you have a reference to an immediateFailed var in ng-show which is presumably only displaying if the immediate check failed, so you're doing the right sort of thing already).
If using page level config, you wouldn't even need to pass the parameters, just call:
gapi.signin.render('customBtn');
gapi.signin.render('customBtn_M');

Styling Data Validation Errors with Bootstrap

I am working on an ASP.NET MVC 4 Project. I want to style data validation errors on my login page with Bootstrap 3.0. When I debug the page and it gives data validation errors, this codes are disappeared in source of my login form:
<form action="/Account/Login" class="col-md-4 col-md-offset-4 form-horizontal well" method="post"><input name="__RequestVerificationToken" type="hidden" value="Zbg4kEVwyQf87IWj_L4alhiHBIpoWRCJ9mRWXF6syGH4ehg9idjJCqRrQTMGjONnywMGJhMFmGCQWWvBbMdmGFSUPqXpx6XaS4YfpnbFm8U1" /><div class="validation-summary-errors"><ul><li>The user name or password provided is incorrect.</li>
</ul></div> <div class="form-group control-group">
<div class="col-md-6 col-md-offset-3">
<input class="input-validation-error form-control" data-val="true" data-val-required="User name alanı gereklidir." id="UserName" name="UserName" placeholder="Kullanıcı Adı" type="text" value="" />
<span class="field-validation-error" data-valmsg-for="UserName" data-valmsg-replace="true">User name alanı gereklidir.</span>
</div>
</div>
<div class="form-group">
<div class="col-md-6 col-md-offset-3">
<input class="input-validation-error form-control" data-val="true" data-val-required="Password alanı gereklidir." id="Password" name="Password" placeholder="Şifre" type="password" />
<span class="field-validation-error" data-valmsg-for="Password" data-valmsg-replace="true">Password alanı gereklidir.</span>
</div>
</div>
<div class="form-group">
<div class="col-md-4 col-md-offset-4">
<button class="btn btn-default" type="submit">Giriş Yap</button>
</div>
</div>
</form>
How can I style these errors like "for=inputError" property of label with Bootstrap 3?
As it's shown in Bootstrap's docs, you need to apply class has-error to the div that contains the input and has class form-group:
<div class="form-group has-error">
...
</div>
It's a quite ugly to write a condition for each property you want to check and apply class has-error depending on the results of that condition, though you can do it like so:
<div class="form-group #(Html.ViewData.ModelState.IsValidField(Html.IdFor(x => x.UserName)) ? null : "has-error" )">
This takes care of the server side validation. However, there is also client side validation you need to think about. For that you'd need to write some jQuery that would check for existence of class field-validation-error and apply class has-error depending on the result.
You may do it all your self, though I suggest checking out TwitterBootstrapMVC which does all of that automatically for you. All you'd have to write is:
#Html.Bootstrap().FormGroup().TextBoxFor(m => m.UserName)
Disclaimer: I'm the author of TwitterBootstrapMVC. Using it in Bootstrap 2 is free. For Bootstrap 3 it requires a paid license.