Hi I've been trying to fill a number in an input box in Chrome (v 75.0.3770.142) using Selenium Basic ChromeDriver (v 75.0.3770.140) in Excel (2013) VBE
I've tried the below but get error message:
obj.FindElementById("cartPrdQtyBtn0").Value = ("100000")
obj.FindElementByCss("input.form-control.ng-pristine.ng-untouched.ng-
invalid.ng-invalid-required#cartPrdQtyBtn0").SendKeys ("10000")
obj.FindElementByXPath("//input[#class='form-control ng-pristine ng-
untouched ng-invalid ng-invalid-required' and
#id='cartPrdQtyBtn0']").SendKeys ("100000")
(1) HTML before clicking within the input element:
<div class="form-group" ng-class="{'has-error':
(entryItem.invalidProductQuantity || entryItem.invalidPallet ||
entryItem.pumpingQtyError || entryItem.lineItemQtyError)}" ng-
hide="entryItem.isPalletEnabled || entryItem.isCancelled"><!-- ngIf: !entryItem.isDecimal --><input id="cartPrdQtyBtn0" type="text"class="form-control ng-pristine ng-untouched ng-invalid ng-invalid-
required"
restrict="number" restrict-max="100000" required="" ng-
model="entryItem.productDisplayQuantity" ng-
readonly="entryItem.isReadOnly"
ng-blur="updateCartProduct(entryItem, $index)" ng-
if="!entryItem.isDecimal">
<!-- end ngIf: !entryItem.isDecimal -->
<!-- ngIf: entryItem.isDecimal -->
</div>
<p ng-bind="entryItem.productDisplayQuantity" ng-show="entryItem.isCancelled" class="ng-hide"></p>
(2) HTML after clicking within the input element:
<div class="form-group has-error" ng-class="{'has-error':
(entryItem.invalidProductQuantity || entryItem.invalidPallet ||
entryItem.pumpingQtyError || entryItem.lineItemQtyError)}" ng-
hide="entryItem.isPalletEnabled || entryItem.isCancelled">
<!-- ngIf: !entryItem.isDecimal -->
<input id="cartPrdQtyBtn0" type="text"
class="form-control ng-pristine ng-
invalid ng-invalid-required ng-touched" restrict="number" restrict-
max="100000" required="" ng-model="entryItem.productDisplayQuantity" ng-
readonly="entryItem.isReadOnly" ng-blur="updateCartProduct(entryItem,
$index)" ng-if="!entryItem.isDecimal">
<!-- end ngIf: !entryItem.isDecimal -->
<!-- ngIf: entryItem.isDecimal -->
</div>
<p ng-bind="entryItem.productDisplayQuantity" ng-show="entryItem.isCancelled" class="ng-hide"></p>
(3) HTML after sending some text manually (100000):
<div class="form-group" ng-class="{'has-error':
(entryItem.invalidProductQuantity || entryItem.invalidPallet ||
entryItem.pumpingQtyError || entryItem.lineItemQtyError)}" ng-
hide="entryItem.isPalletEnabled || entryItem.isCancelled">
<input id="cartPrdQtyBtn0" type="text" class="form-control ng-pristine
ng-untouched ng-valid ng-valid-required" restrict="number" restrict-
max="100000" required="" ng-model="entryItem.productDisplayQuantity" ng-
readonly="entryItem.isReadOnly" ng-blur="updateCartProduct(entryItem,
$index)" ng-if="!entryItem.isDecimal">
<p ng-bind="entryItem.productDisplayQuantity" ng-show="entryItem.isCancelled" class="ng-hide">100000</p>
To send a character sequence within the input field you can use either of the following Locator Strategies:
cssSelector:
obj.FindElementByCss("input.form-control.ng-pristine.ng-untouched.ng-invalid.ng-invalid-required[id^='cartPrdQtyBtn']").Click
obj.FindElementByCss("input.form-control.ng-pristine.ng-invalid.ng-invalid-required.ng-touched[id^='cartPrdQtyBtn']").SendKeys("10000")
xpath:
obj.FindElementByXPath("//input[#class='form-control ng-pristine ng-untouched ng-invalid ng-invalid-required' and starts-with(#id, 'cartPrdQtyBtn')]").Click
obj.FindElementByXPath("//input[#class='form-control ng-pristine ng-invalid ng-invalid-required ng-touched' and starts-with(#id, 'cartPrdQtyBtn')]").SendKeys("10000")
Note: As it is a dynamic element you need to induce a waiter for the element to be clickable
Reference
You can find a couple of relevant discussions in:
How to send text to some HTML elements?
Trying to fill text in input box with dynamic drop down
finally figured out that it works with the div class also in front:
obj.FindElementByXPath("//div[#class='form-group']/input[#class='form-control ng-pristine ng-untouched ng-invalid ng-invalid-required'and #id= 'cartPrdQtyBtn0']").SendKeys ("100000")
Related
When I use a text-input type , i can just give it a value and use that, even on another page
example:
<input type="text" class="form-control" name="name" value="<?php echo $row['name'];?>">
Can I do the same with a textarea?
example :
<textarea class="form-control" rows="3" cols="123" name="comments" value="<?php echo $row['comments'];?>" ></textarea>
This is my code in where I retrieve an existing row of information from a given ID. The info consists of a name, emailaddress and comments :
<form method="post">
<div class="row gy-2 text-left">
<div class="row">
<div class="col-auto gy-2">
<label>Name</label> <br>
<input type="text" class="form-control" name="name" value="<?php echo $row['naam'];?>">
</div>
</div>
<div class="row">
<div class="col-auto gy-2">
<label>Email address</label><br>
<input type="email" class="form-control" name="email" value="<?php echo $row['email'];?>">
</div>
</div>
<div class="row">
<div class="col-auto gy-2">
<label>Tell me about it</label><br>
<style>
textarea {resize: none;}
</style>
<textarea class="form-control" rows="3" cols="123" name="comments" value="<?php echo $row['comments'];?>" ></textarea>
</div>
<div class="row">
<div class="col-auto gy-3">
<button class="btn edit btn-info border border-dark" name="Update">Update</button>
</div>
</div>
</div>
</form>
For the textarea element, it goes between <textarea> and </textarea> tags:
<textarea><?php echo $row['comments'];?></textarea>
The <textarea> element does not use an HTML attribute named value like the <input> element does.
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea#attributes
However, when the HTML markup which contains a textarea element is parsed by the browser, an HTMLTextAreaElement object is created. This DOM element object, which represents the state of the textarea element on the web page does have a JavaScript object property named .value, which gives access via JavaScript to the text which the textarea element contains.
This JavaScript code logs the text that is contained in a textarea element:
console.info(document.querySelector('textarea').value);
https://developer.mozilla.org/en-US/docs/Web/API/HTMLTextAreaElement
Using Python 3.7 with Selenium on pages that include Angular, please advise how to best locate an element such as this:
<input type="radio" ng-model="section3.data.generalSection3.container[$index].lseCatTy" value="FEDERAL" ng-disabled="!section3.data.generalSection3.container[$index].editable" ng-class="classes('lseCatTy')" ng-change="section3.updateLseCatTy($index, section3.data.generalSection3.container[$index].lseCatTy)" class="ng-valid ng-not-empty ng-dirty ng-touched ng-valid-parse" name="759" style="">
or this
<button type="button" uib-tooltip="Edit" tooltip-placement="right" class="btn btn-primary" ng-click="section3.data.editContainer($index);" ng-disabled="editingDrilling1 || submissionTypeSR">
when it exists in blocks such as the following. What's tripping me up is the $index... The page has multiple fieldset tags and that number is DYNAMIC... For example, a user can add more of one type of the fieldset while editing the page- but only this one type.
<div ng-if="section3.data.generalSection3.srvyTyId != null && section3.data.generalSection3.srvyTyId != ''" class="ng-scope" style="">
<!-- ngRepeat: wellFeature in section3.data.generalSection3.container track by $index -->
<div ng-repeat="wellFeature in section3.data.generalSection3.container track by $index" class="ng-scope">
<!-- ngIf: section3.data.generalSection3.container[$index].deleteSegmentLocation == null -->
<fieldset class="legend-border ng-scope" ng-if="section3.data.generalSection3.container[$index].deleteSegmentLocation == null">
<legend/>
<div class="col-lg-12 panel panel-default">
<div class="row panel-heading ng-binding">
SHL <br>
<!-- ngIf: section3.data.generalSection3.container[$index].legBHLAttr == 'PPP' -->
<!-- ngIf: section3.data.generalSection3.container[$index].legBHLAttr != 'PPP' && section3.data.generalSection3.container[$index].legBHLAttr != 'SHL' -->
<!-- ngIf: section3.data.generalSection3.container[$index].legBHLAttr == 'SHL' -->
<div ng-if="section3.data.generalSection3.container[$index].legBHLAttr == 'SHL'" class="ng-scope"/>
<!-- end ngIf: section3.data.generalSection3.container[$index].legBHLAttr == 'SHL' -->
</div>
</div>
<div class="row">
<div class="col-lg-11">
<!-- ngIf: section3.data.generalSection3.srvyTyId=='1'|| section3.data.generalSection3.srvyTyId=='3' || section3.data.generalSection3.srvyTyId=='2' || section3.data.generalSection3.srvyTyId=='4' -->
<div ng-if="section3.data.generalSection3.srvyTyId=='1'|| section3.data.generalSection3.srvyTyId=='3' || section3.data.generalSection3.srvyTyId=='2' || section3.data.generalSection3.srvyTyId=='4'" style="padding-left: 15px; padding-right: 15px;" class="ng-scope">
<div class="row">
<div class="col-lg-6">
<div class="form-group">
<label class="required-field">Lease Type</label>
<br>
<div ng-class="classes('lseCatTy'+','+$index.toString(), [])">
<label class="radio-inline">
<input type="radio" ng-model="section3.data.generalSection3.container[$index].lseCatTy" value="FEDERAL" ng-disabled="!section3.data.generalSection3.container[$index].editable" ng-class="classes('lseCatTy')" ng-change="section3.updateLseCatTy($index, section3.data.generalSection3.container[$index].lseCatTy)" class="ng-valid ng-not-empty ng-dirty ng-touched ng-valid-parse" name="759" style=""> Federal
</label>
<label class="radio-inline">
What I have working is:
self.wait.until(EC.presence_of_element_located((By.XPATH, "//button[#ng-click='section3.data.editContainer($index);']"))).click()
And this gets the first instance of that button (in the top fieldset), but I don't know how to get an arbitrary instance of it.
driver.find_elements_by_css_selector('[ng-model*="$index"],[ng-click*="$index"]')
I learned to navigate the DOM using parent elements and finding elements within parent elements --
This became a matter of finding a unique parent (lines 1 and 2), then finding the edit button for that section (line 3), and finding the desired element (line 4).
shl_div = self.wait.until(EC.presence_of_element_located((By.XPATH, "//div[#class='row panel-heading ng-binding' and contains(text(),'SHL')]")))
shl_par = shl_div.find_element_by_xpath("..")
shl_par.find_element_by_xpath(".//button[#ng-click='section3.data.editContainer($index);']").click()
shl_par.find_element_by_xpath(".//input[#value='FEDERAL']").click()
I'm trying to click on a button with Selenium on python. The thing is that after I find the element using explicit waits, I get that another elements would recieve the click. I thought that maybe this button had a parent element with the same dimensions and this one was about to get clicked, but it isn't the case. I'm using chromedriver. I'll share the fragment of html code and what I'm doing:
<section id="main">
<div id="form-signin">
<img id="dynamic-logo" src="images/logo.svg" class="height-39px">
<h3 class="clear-margin-bottom margin-top-22px">Sign in</h3>
<div class="form-input margin-top-30px">
<label>
<input id="username" ng-model="data.user" ng-change="checkResetError()" ng-keyup="$event.keyCode == 13 && login()" ng-class="{'has-error': errorMessage !== undefined }" required="" class="ng-pristine ng-untouched ng-invalid ng-invalid-required">
<span class="placeholder">Enter your username</span>
</label>
</div>
<div class="form-input margin-top-30px">
<label>
<input id="password" type="password" ng-model="data.pass" ng-change="checkResetError()" ng-keyup="$event.keyCode == 13 && login()" ng-class="{'has-error': errorMessage !== undefined }" required="" class="ng-pristine ng-untouched ng-invalid ng-invalid-required">
<span class="placeholder">Password
<div class="frd-icon frd-icon-lock pull-right"></div>
</span>
</label>
</div>
<p class="font-xs font-bold fg-red pull-left margin-top-18px ng-binding"></p>
</div>
<button class="btn-frd btn-xl bg-blue btn-block" style="background-color: #00a8e1" type="submit" ng-click="login()">Login</button>
<span class="powered-text" ng-show="isFoundedLogo === true">Powered by Test</span>
And my code for the click part in python is like this:
login_button = WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.ID, "main"))).find_element_by_tag_name("button")
login_button.click()
I don't get why this happens. I also tried to find it by xpath, but the same error appeared.
Thanks
How can I check that checkbox using WATIR
<label title="Active-DC Cloud Management" class="custom-checkbox ng-scope folderSelector">
<span class="customCheckBox icn" ng-disabled="cDisabled">
<input class="ng-pristine ng-valid" ng-model="model" ng-change="changeCallback({$event:$event})" ng-disabled="cDisabled" type="checkbox">
</span> Active-DC Cloud Management<!-- ngIf: cFoldertype == 'ASP' || cFoldertype == 'VCE' || cFoldertype == 'CPL' -->
</label>
I have tried using the following but that doesn't work
#browser.label(:text,'Active-DC Cloud Management').parent.click
Here is more of the HTMl code
<li class="ng-scope" ng-repeat="subfolder in subfolder.subFolders" ng-class="{expandButton:subfolder.hasSubFolders,plus:subfolder.hasSubFolders, disabled:subfolder.folderAccess == 'NONE', selected:selectedFolderIdsArray.indexOf(subfolder.folderId) !== -1}" id="1001665955" ftpath="HOME\Order_12329753" ftname="Order_12329753" ftlevel="2" fttype="ORDER" ftaccess="VIEW">
<a name="&lpos=my : 263" href="javascript:void(0)" ng-click="toggleSelectFolder(subfolder.folderId,subfolder.fullFolderPath)" style="padding-left: 28px" data-this-tree="thisTree" complete-folder-stack="completeFolderStack" folder-data-ftype="subfolder.folderType">
<span class="expandCollapseIcon ng-hide" style="left: 15px" ng-show="subfolder.hasSubFolders" ng-click="expander($event,subfolder.folderAccess); ajaxLoad($event,subfolder)"> </span>
<label class="custom-checkbox ng-scope folderSelector">
<span class="customCheckBox icn" ng-disabled="cDisabled">
<input class="ng-valid ng-dirty" ng-model="model" ng-change="changeCallback({$event:$event})" ng-disabled="cDisabled" type="checkbox"></span>Order_12329753<!-- ngIf: cFoldertype == 'ASP' || cFoldertype == 'VCE' || cFoldertype == 'CPL' --></label></a>
<ul class="subfolder"><!-- ngRepeat: subfolder in subfolder.subFolders --></ul></li>
OK i figured this part out it seems like the div that contains all this code is set to be disabled (not invisible) so because of that I can not use the regular functions associated with the checkbox element but I can use the fire_event method of the browser to click on the checkbox b.input(:xpath,"//label[#title='Active-DC Cloud Management']/span/input").fire_event :click
I'm trying to refactor my app to use jade instead of ejs but am running into some problems setting up a login form.
Here's my original form in ejs:
<% if (message) { %>
<p><%= message %></p>
<% } %>
<form class="form-horizontal" action='/login' method="POST" id="loginForm">
<fieldset>
<div id="legend">
<legend class="">Login</legend>
</div>
<div class="control-group">
<!-- Username -->
<label class="control-label" for="username">Username</label>
<div class="controls">
<input type="text" id="username" name="username" placeholder="" class="input-xlarge">
</div>
</div>
<div class="control-group">
<!-- Password-->
<label class="control-label" for="password">Password</label>
<div class="controls">
<input type="password" id="password" name="password" placeholder="" class="input-xlarge">
</div>
</div>
<div class="control-group">
<!-- session-->
<label class="control-label" for="rememberme">Remember Me</label>
<div class="controls">
<input type="checkbox" name="rememberme"/>
</div>
</div>
<div class="control-group">
<!-- Button -->
<div class="controls">
<button class="btn btn-success">Login</button>
</div>
</div>
</fieldset>
</form>
And here's my new form in jade:
extends layout
block content
if message
p= message
form(class='form-horizontal',action='/login',method='POST',id='loginForm')
fieldset
div#legand
legend Login
div.control-group
label(for='username',class='control-label') Username
div.controls
input(type='text',id='username',name='username',placeholder='Username',class='input-xlarge')
div.control-group
label(for='password',class='control-label') Password
div.controls
input(type='text',id='password',name='password',placeholder='Password',class='input-xlarge')
div.control-group
label(for='rememberme',class='control-label') Remember Me
div.controls
input(type='checkbox',name='rememberme')
div.control-group
div.controls
input(type='submit',class='btn btn-success') Login
Codekit is throwing an error:
/Applications/CodeKit.app/Contents/Resources/engines/jade/lib/runtime.js:173
throw err;
^
Error: /Users/sm/Documents/Projects/Web_Applications/App/app/views/login.jade:27
25|
26|
> 27|
Invalid indentation, you can use tabs or spaces but not both
at Object.Lexer.indent (/Applications/CodeKit.app/Contents/Resources/engines/jade/lib/lexer.js:672:15)
at Object.Lexer.next (/Applications/CodeKit.app/Contents/Resources/engines/jade/lib/lexer.js:770:15)
at Object.Lexer.blank (/Applications/CodeKit.app/Contents/Resources/engines/jade/lib/lexer.js:179:19)
at Object.Lexer.next (/Applications/CodeKit.app/Contents/Resources/engines/jade/lib/lexer.js:744:15)
at Object.Lexer.blank (/Applications/CodeKit.app/Contents/Resources/engines/jade/lib/lexer.js:179:19)
at Object.Lexer.next (/Applications/CodeKit.app/Contents/Resources/engines/jade/lib/lexer.js:744:15)
at Object.Lexer.lookahead (/Applications/CodeKit.app/Contents/Resources/engines/jade/lib/lexer.js:106:46)
at Object.Parser.lookahead (/Applications/CodeKit.app/Contents/Resources/engines/jade/lib/parser.js:115:23)
at Object.Parser.peek (/Applications/CodeKit.app/Contents/Resources/engines/jade/lib/parser.js:92:17)
at Object.Parser.tag (/Applications/CodeKit.app/Contents/Resources/engines/jade/lib/parser.js:666:30)
How can I get past this indentation error and get this form to work? I'm only using tabs and no spaces so I don't understand what the problem is.
This is probably caused by a space in the trailing empty lines in your Jade template (which you don't post, but are there according to the error message).
I think your problem may be how you're specifying the button. Instead of:
div.control-group
div.controls
input(type='submit',class='btn btn-success') Login
Try:
div.control-group
div.controls
button(type='submit',class='btn btn-success') Login