Retrieve an element by XPath/CSS from HTML - webdriver

I am trying retrieve an element "Nature News Standard Article in Nature News & Comment" which is part of below HMTL code.
I have following WebDriver code in selenium:
if ("Polopoly CM".equals(driver.getTitle())) {
System.out.println("----> Title of page <----");
driver.findElement(By.xpath("//*[starts-with(#id,'nav_') and #class='p_textOutput']"));
System.out.println("----> Xpath Selected <----");
driver.findElement(By.xpath("//*[starts-with(#id,'nav_') and #class='p_textOutput']")).click();
System.out.println("----> Xpath Clicked <----");
}
Problem is: i am unable to retrive the required element through Xpath/CSS from HTML
HTML:
<document>
<html xmlns:polopoly="http://www.polopoly.com/polopoly/cm/app/gui" xmlns="http://www.w3.org/1999/xhtml" style="cursor: default;">
<head>
<body id="nav_3" class="navFrameBody" onbeforeunload="busyCursor();" onload="onLoad(); idleCursor();">
<script type="text/javascript"> <!-- Jasmine.createFrame('nav'); //--> </script>
<form id="mainform" name="mainform" method="post" action="CM">
<input type="hidden" value="2852906396" name="owid"/>**
<input type="hidden" value="1332852912984" name="ofid"/>
<input type="hidden" value="nav" name="ofn"/>
<input type="hidden" value="true" name="ofs"/>
<input id="nav_1" type="hidden" value="0" name="nav_1"/>
<input id="nav_2" type="hidden" value="0" name="nav_2"/>
<div id="nav_13_placeHolder" class="ajax_placeHolder">
<fieldset id="nav_14" class="field"/>
<div id="nav_4" class="p-group quickCreator expanded">
<div id="nav_4_state">
<input id="nav_15" type="hidden" value="expanded" name="nav_15"/>
</div>
<div class="toggleIcon clearfix"/>
<script lang="javascript">$(document).ready(function() {p_makeExpandable('nav_4', 'nav_15')});</script>
<fieldset id="nav_16" class="contentCreator field topContentCreator">
<div class="quickCreator contentCreator container">
<div class="quickCreator header clearfix">
<h2> Create New </h2>
<a id="nav_17" class="customize" href="javascript:actionEventData({$contentId:"18.232.1319560059", $action:"edit", $target:"work", $opentab:"menu/quickCreatorLayout"})">Customize</a>
</div>
<div class="list">
<div class="quickCreator link">
<input type="hidden" value="" name="nav_18"/>
<a id="nav_18" href="javascript:submitForm(document.mainform, document.mainform.nav_18, "x")">
<img id="nav_19" class="centered" alt="" src="images/icons/transparentIcon.png"/>
<span id="nav_20" class="p_textOutput">Nature News Standard Article in Nature News & Comment</span>
</a>
</div>
</div>
</div>
</fieldset>
</div>
<div id="nav_5" class="p-group contentTree expanded">
<div id="nav_5_state">
<input id="nav_21" type="hidden" value="expanded" name="nav_21"/>
</div>
<div class="toggleIcon clearfix"/>
<script lang="javascript">$(document).ready(function() {p_makeExpandable('nav_5', 'nav_21')});</script>
<div class="field contentTree">
<div id="nav_6_placeHolder" class="ajax_placeHolder">
<div class="header">
<span class="label">Content Tree</span>
<button id="nav_9" type="button" value="Refresh tree" name="nav_9">
<img id="nav_22" class="centered" alt="" src="images/icons/refresh.png"/>
<span id="nav_23" class="p_textOutput"> Refresh tree</span>
<script type="text/javascript"> <!-- jQuery(document).ready(function() { addOnClickEvent("nav_9",null, "nav_9_placeHolder", null, new IndicatorLifecycleHook('p.std_ajaxIndicator', true, 0.8, "createImageTop('images/ajax/busy_indicator_big_green.gif')")); }); //--> </script>
</button>
</div>
<div class="tree">
<div id="nav_8_placeHolder" class="ajax_placeHolder">
<script type="text/javascript"> jQuery.require(["script/polopoly-ui.js"]); </script>
<input id="nav_8" type="hidden" value="" name="nav_8"/>
<script type="text/javascript"> jQuery.require(["script/polopoly-ui.js"]); </script>
<ul id="nav_8_tree" class="tree">
</div>
</div>
</div>
</div>
</div>
<fieldset id="nav_24" class="field clipboard">
<input id="nav_25" type="hidden" value="" name="nav_25"/>
</fieldset>
</form>
<script type="text/javascript"> <!-- jQuery(document).ready(function() { if(window.parent.SeleniumPageLoadCountnav==null) { window.parent.SeleniumPageLoadCountnav=1; window.parent.SeleniumPageLoadCountnavOld=0; } else { window.parent.SeleniumPageLoadCountnav+=1; } }); //--> </script>
</body>
</html>
</document>

I see two elements which can be selected by your xpath locator. Try to find both of them.
List<WebElement> elements = webDriver.findElements(By.xpath("your_xpath"));
for (Element element : elements) {
element.click();
}

Your HTML code is:
Nature News Standard Article in Nature News & Comment
So, You can use id or xpath to retrieve the element text as follows:
Using id:
String s = driver.findElement(By.id("nav_20")).getText();
System.out.println(s);
Using xpath:
String s1 = driver.findElement(By.xpath("//span[#id='nav_20']")).getText();
System.out.println(s1);

css=a[href*='javascript:submitForm'] > span.p_textOutput
Try the above CSS Selector. I am sure it will work out.
Please Let me know is it working or NOT.

Related

How to change the class of the parent element with different forms with angular2+ or css?

I have a list of elements with a header, body and a checkbox to display the body, Like accordion:
<form class="search-box" [ngClass]="{'classname' : condition}">
<input
(click)="addClasstoBody"
type="checkbox"
name="showBody"
/>
<header>
<span class="body">
Body
</span>
</header> </div>
<div class="search-box" [ngClass]="{'classname' : condition}">
<input
(click)="addClasstoBody"
type="checkbox"
name="showBody"
/>
<header>
<span class="body">
Body
</span>
</header></form>
With the easy way of setting on true by add the class to all the components.
Can I use something like form.checkbox.checked?
i edited the answer
create elementRef and bind to your HTML element
then pass the elementRef onClick for further manipulate
edit your component.ts
...
#ViewChild('container1') container1: ElementRef;
#ViewChild('container2') container2: ElementRef;
....
addClasstoBody(containerModel: HTMLElement, event){
var targetContainer = event.target;
var isChecked = targetContainer.checked;
console.dir(isChecked)
console.dir(containerModel)
console.dir(event)
if(isChecked){
containerModel.classList.add("show");
}else{
containerModel.classList.remove("show");
}
}
edit your component.html
<form class="search-box">
<div [ngClass]="{'classname' : true}" #container1>
<input
(click)="addClasstoBody(container1, $event)"
type="checkbox"
name="showBody"
[(ngModel)]="container1.isCheck"
>
<header>
<span class="body">
Body1
</span>
</header>
</div>
<div class="search-box" [ngClass]="{'classname' : true}" #container2>
<input
(click)="addClasstoBody(container2, $event)"
type="checkbox"
name="showBody"
[(ngModel)]="container2.isCheck"
>
<header>
<span class="body">
Body2
</span>
</header>
</div>
</form>
you may also did all in the html, remove the addClasstoBody function but edit your container as below
<div [ngClass]="{'classname' : container1.isCheck}" #container1>

Recpatcha not rendering until refresh page in Angular js

Recaptcha not rendering until I refresh the page
I'm using Recaptcha in my angular js project for security stuff.
I just implemented the captcha with following below steps:
1. I added below link to my page (in the head tag before every styles and scripts file):
<script src="https://www.google.com/recaptcha/api.js?hl=fa" async ></script>
2. In my form, I added captcha
<div class="g-recaptcha" data-sitekey="my_site_key"></div>
so my page is something like this
<html>
<head>
<title>reCAPTCHA demo: Simple page</title>
<script src="https://www.google.com/recaptcha/api.js?hl=fa" async ></script>
</head>
<body>
<form action="?" method="POST">
<div class="g-recaptcha" data-sitekey="my_site_key"></div>
<br/>
<input type="submit" value="Submit">
</form>
</body>
</html>
Apparently, everything is fine, but Recaptcha not rendering until I refresh the page. actually, it's not gonna work when the page request by ajax but after page reloading, Recaptcha will render on the page!
So how can I render Recaptcha with the first render??
I figure out how can I fix this problem.
instead of adding this script
<script src="https://www.google.com/recaptcha/api.js?hl=fa" async ></script>
to layout page, I added it in every page that I want to render captcha so after routing to the special page, in addition, to render the page content captcha will render for us too.
for exmaple the content page template will be something like this:
contactus.html content
<script src="https://www.google.com/recaptcha/api.js?hl=fa" async></script>
<form name="contactUsForm" novalidate>
<section class="well">
<div class="form-horizontal form-widgets col-sm-6">
<div class="form-group has-feedback" ng-class="{'has-error': contactUsForm.firstName.$error.required && contactUsForm.firstName.$dirty, 'has-success': !contactUsForm.firstName.$error.required }">
<label class="control-label col-sm-4" for="firstName">Name</label>
<div class="col-sm-8 col-md-6">
<input type="text" id="firstName" name="firstName" ng-model="contactUs.firstName" class="form-control" ng-class="{'form-control-error': contactUsForm.firstName.$error.required && contactUsForm.firstName.$dirty, 'form-control-success': !contactUsForm.firstName.$error.required }" placeholder="Name" required />
<span ng-show="contactUsForm.firstName.$error.required && contactUsForm.firstName.$dirty" class="glyphicon glyphicon-remove form-control-feedback" aria-hidden="true"></span>
<span ng-show="!contactUsForm.firstName.$error.required" class="glyphicon glyphicon-ok form-control-feedback" aria-hidden="true"></span>
<div class="text-danger" ng-show="contactUsForm.firstName.$error.required && contactUsForm.firstName.$dirty">Name is required</div>
</div>
</div>
<div class="form-horizontal form-widgets col-sm-12 col-sm-offset-2" style="display: flex;justify-content: flex-start;margin-bottom: 2rem;">
<div class="g-recaptcha" data-sitekey="my-sitekey"></div> <!-- Server -->
<!--<div class="g-recaptcha" data-sitekey="my-sitekey"></div>--> <!-- Local -->
</div>
<div class="buttons-wrap col-sm-offset-2" style="text-align:right;padding-right:1.6rem">
<button class="btn btn-primary" ng-disabled="contactUsForm.$invalid" data-toggle="modal" data-target="#confirmModal"><i class="glyphicon glyphicon-save"></i><span>&submit</span></button>
</div>
</section>
</form>

How to position ngshow messages in angular js

How to have ng-show messages beside the text box rather than underneath it. Right now it is displaying all the validation messages underneath the input box.
<!DOCTYPE html>
<html ng-app="myApp" >
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script>
"use strict";
var app = angular.module('myApp', []);
app.controller('MainCtrl', function ($scope) {
$scope.cityArray = ["hyderabad", "secunderabad", "delhi", "mumbai"];
$scope.submit = function ($event) {
if ($scope.myForm.$invalid) {
// Or some other update
$scope.myForm.$submitted = true;
$event.preventDefault();
}
};
});
app.directive('uniqueUsername', function ($http) {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attrs, ngModel) {
element.bind('blur', function (e) {
ngModel.$setValidity('unique', true);
$http.post('CheckUserName2.do').success(function (data) {
if (data) {
ngModel.$setValidity('unique', false);
}
});
});
}
};
});
</script>
</head>
<body ng-controller="MainCtrl">
<div class="container">
<div class="col-md-6 col-md-offset-0">
<div class="panel panel-login">
<div class="panel-body">
<div class="row">
<div class="col-lg-12">
<h2 class="text-muted">Registration form</h2>
<div>
<form name="myForm" action="RegistrationServlet.do" method="POST" >
First name:<input type="text" class="form-control input-sm" name="uname" ng-pattern="/^[a-zA-Z]{3,20}/" ng-model="uname" unique-username="" placeholder="First Name" required/>
<span style="color:red" ng-show="myForm.uname.$error.pattern">First name cannot be less than 3 letters with no digits</span>
<span style="color:red" class="error" ng-if="myForm.$submitted && myForm.uname.$error.required">Please fill field above<br></span><br/>
<span style="color:red" class="hide-while-in-focus" ng-show="myForm.uname.$error.unique">Username already exist<br/></span>
<button class="form-control btn btn-success" type="submit" ng-click="submit($event)">Submit</button>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
Here's the plunker
You don't have space to the right to display error messages beside the input box. Putting error messages just above the submit button will cause a minor UI issue: with each error, your form submit-button will flicker vertically.
Viz.
- Submit your form without entering any input to get the error message.
- type/erase any character in the input box to see the flickering
Workaround:
Either keep the error messages below submit button or provide dedicated height to error messages to avoid undesirable effects or both
<form name="myForm" action="RegistrationServlet.do" method="POST" >
First name:<input type="text" class="form-control input-sm" name="uname" ng-pattern="/^[a-zA-Z]{3,20}/" ng-model="uname" unique-username="" placeholder="First Name" required/><br><br>
<button class="form-control btn btn-success" type="submit" ng-click="submit($event)">Submit</button>
<div style="height=100px">
<span style="color:red" ng-show="myForm.uname.$error.pattern">First name cannot be less than 3 letters with no digits</span>
<span style="color:red" class="error" ng-if="myForm.$submitted && myForm.uname.$error.required">Please fill field above<br></span><br/>
<span style="color:red" class="hide-while-in-focus" ng-show="myForm.uname.$error.unique">Username already exist<br/></span>
</div>
</form>
Demo

Bootstrap 3.2 won't style Spring MVC form:form

I have a simple Spring MVC 4.x (tiles) scenario. Where in response to a URI a form is displayed, however, Bootstrap styling is not kicking in:
JSP:
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%# taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<br/><br/><br/>
<form:form modelAttribute="car" method="post">
<div class="form-group">
<label for="title">Make</label>
<form:input path="make"/>
</div>
<div class="form-group">
<label for="isbn">Model (Long Label)</label>
<form:input path="model"/>
</div>
<div class="form-group">
<label for="isbn">Color</label>
<form:input path="color"/>
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form:form>
Rendered HTML:
<body>
<div class="container">
<div class="row">
<div class="header">
</div>
<div id="main-content-container">
<!-- main body -->
<br/><br/><br/>
<form id="car" action="/libms/carsx" method="post">
<div class="form-group">
<label for="title">Make</label>
<input id="make" name="make" type="text" value=""/>
</div>
<div class="form-group">
<label for="isbn">Model (Long Label)</label>
<input id="model" name="model" type="text" value=""/>
</div>
<div class="form-group">
<label for="isbn">Color</label>
<input id="color" name="color" type="text" value=""/>
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
<div class="footer">
</div>
</div>
</div>
</body>
Looks like this on screen:
I have verified if Spring's form:form is removed and <form> is used instead, the styling kicks in.
You need to include jquery and bootstrap on your page. For example:
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js">
</script>
You may also want to make of use some other bootstrap elements such as cssClass.
For example:
<form:form modelAttribute="car" method="post">
...can be changed to:
<form:form modelAttribute="car" cssClass="form-horizontal" method="post">
And:
<label for="title">Make</label>
...can be changed to:
<label for="title" class="col-sm-2 control-label">Make</label>
And:
<form:input path="make"/>
...can be changed to:
<div class="col-sm-2">
<form:input path="make" cssClass="form-control"/>
</div>
As you mention, the Spring form functionality also kicks in since you're including the Spring form taglib as well.
Have you Included Bootstrap in your jsp page Like
<html>
<head>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">
<title>Products</title>
</head>
<body>
<div class="jumbotron">
<div class="container">
<h1>Products</h1>
<p>Add products</p>
</div>
</div>
....
I can't see it in your page

Have to double click the Submit button twice to execute POST. Bootstrap, Jquery Validate

This registration form actually works as designed when all the fields are populated. The issue that I am having is when the "Create Account" button is clicked, it fires a Submit/Post and the reCaptcha buttons are moved to below the reCaptcha input text and does nothing after the first click. I have to click the "Create Account" button again to actually achieve the post action.
Can someone analyze my code below and help me fix this behavior?
!DOCTYPE html>
<!--[if IE 8]>
<html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
<link rel="stylesheet" href="/static/css/bootstrap.min.css" />
<script type="text/javascript" src="/static/js/jquery-min.js"></script>
<script type="text/javascript" src="/static/js/jquery.validate.min.js"></script>
<script type="text/javascript" src="/static/js/additional-methods.min.js"></script>
<script type="text/javascript" src="/static/js/bootstrap.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
</head>
<body>
<!-- This block code is the place holder for the content files -->
<script type="text/javascript" src="http://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>
<div class='container'>
<form id='reguser' class="form-horizontal" action='' method='POST'>
<fieldset>
<legend> Create User Account </legend>
<div class="control-group">
<div class="control-group">
<label class="control-label" for="email">Email</label>
<div class="controls">
<input type="text" class="input-large" name="email" id="email" >
</div>
</div>
<label class="control-label" for="fname">First Name</label>
<div class="controls">
<input type="text" class="input-large" name="fname" id="fname" >
</div>
</div>
<div class="control-group">
<label class="control-label" for="lname">Last Name</label>
<div class="controls">
<input type="text" class="input-large" name="lname" id="lname" >
</div>
</div>
<div class="control-group">
<label class="control-label" for="pwd">Password</label>
<div class="controls">
<input type="password" class="input-large" name="pwd" id="pwd" >
</div>
</div>
<div class="control-group">
<label class="control-label" for="cpwd">Confirm Password</label>
<div class="controls">
<input type="password" class="input-large" name="cpwd" id="cpwd" >
</div>
</div>
<!-- reCaptcha is engaged here -->
<script type="text/javascript">
var RecaptchaOptions = {
theme : 'custom',
custom_theme_widget: 'recaptcha_widget'
};
</script>
<div id="recaptcha_widget" style="display:none">
<div class="control-group">
<label class="control-label">reCAPTCHA:</label>
<div class="controls">
<a id="recaptcha_image" class="thumbnail"></a>
</div>
</div>
<div class="control-group">
</div>
<div class="control-group">
<label class="recaptcha_only_if_image control-label" for="recaptcha_response_field" >Enter the words above:</label>
<label class="recaptcha_only_if_audio control-label">Enter the numbers you hear:</label>
<div class="controls">
<div class="input-append">
<input type="text" id="recaptcha_response_field" name="recaptcha_response_field"class="input-recaptcha" placeholder="Enter the capctha here" name="recaptcha_response_field" />
<a class="btn" href="javascript:Recaptcha.reload()"><i class="icon-refresh"></i></a>
<a class="btn recaptcha_only_if_image" href="javascript:Recaptcha.switch_type('audio')"><i title="Get an audio CAPTCHA" class="icon-headphones"></i></a>
<a class="btn recaptcha_only_if_audio" href="javascript:Recaptcha.switch_type('image')"><i title="Get an image CAPTCHA" class="icon-picture"></i></a>
<a class="btn" href="javascript:Recaptcha.showhelp()"><i class="icon-question-sign"></i></a>
</div>
</div>
</div>
</div>
<script type="text/javascript"
src="https://www.google.com/recaptcha/api/challenge?k=6LclG-QSAAAAAMS-Ywg49zrMdm209o9CKxgyOqvr">
</script>
<noscript>
<iframe src="https://www.google.com/recaptcha/api/noscript?k=6LclG-QSAAAAAMS-Ywg49zrMdm209o9CKxgyOqvr"
height="300" width="500" frameborder="0"></iframe><br>
<textarea name="recaptcha_challenge_field" rows="3" cols="40">
</textarea>
<input type="hidden" name="recaptcha_response_field" value="manual_challenge">
</noscript>
<div class="form-actions">
<button type="submit" class="btn btn-primary">Create Account</button>
<button type="reset" class="btn">Cancel</button>
</div>
</fieldset>
</form>
</div>
<!--
<form id='frmRegister' action='/account/new' method='POST'>
<label for >Create Account</label><br>
<label>First Name</label><input id='fname' name='fname' type="text" required><br>
<label>Last Name</label><input id='lname' name='lname' type="text" required><br>
<label>email</label><input id='email' name='email' type="text" required><br>
<label>password</label><input id='pwd' name="pwd" type="password" required><br>
<label>confirm password</label><input id='confpwd'name="confpwd" type="password" required><br><br>
<div name ="recap" id="recap"></div>
<input type="button" value="Show reCAPTCHA" onclick="showRecaptcha('recap');"></input>
<input type="submit" value="Create Account">
</form>
-->
<script>
$(document).ready(function(){
$('#reguser').validate({
rules: {
fname: {
minlength: 2,
required: true
},
lname: {
minlength: 2,
required: true
},
email: {
required: true,
email: true
},
pwd: {
minlength: 6,
required: true
},
cpwd: {
minlength: 6,
required: true,
equalTo: "#pwd"
},
recaptcha_response_field:{
required: true
}
},
messages:{
email:{
required: "Please provide a valid email address.",
email: "Your email address must be in the format of name#domain.com"
}
},
highlight: function(element) {
$(element).closest('.control-group').removeClass('success').addClass('error');
},
success: function(element) {
element
.addClass('valid')
.closest('.control-group').removeClass('error').addClass('success');
}
});
});
</script>
</body>
</html>

Resources