Selenium with Angular - XPath how to get to elements when $index present? - python-3.x

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()

Related

Angular hide div on click function

i am new to angular and typescript and i need to hide div section *ngIf="stu.notes != null" on save button click.
i can display the respective divs when clicked on the respective buttons, but i am not able to hide the other one.
Can anyone hep me out here.
Thanks in advance.
HTML File:
<nb-accordion-item-body>
<div class="row">
<div *ngIf="notes_area != null">
<h5> <span class="col-md-8" style="font-weight : bold; font-size : 16px;"
[innerHTML]="notes_area"></span>
</h5>
<br/>
</div>
<div class="col-md-3" *ngFor = "let stu of studentData">
<div *ngIf="stu.notes != null" >
<div class="row">
<div class="col-md-8">
<br/>
<h5 style="font-weight : bold;" > {{stu?.notes.slice(3,-4)}}
</h5>
<br/>
</div>
</div>
</div>
</div>
</div>
<br/>
<div class="row" *ngIf="addNote == true">
<div class="col-md-6">
<tinymce [(ngModel)] = "notes" ></tinymce>
</div>
<div class="col-md-6">
<button nbButton (click)="saveNotes()">Save</button>
</div>
</div>
</nb-accordion-item-body>
.ts File:
saveNotes() {
this.api.saveNotes(this.my_app_data[0].app_id,this.notes).subscribe(data => {
this.notes_area = data['data'];
console.log(this.app_id);
console.log('log',this.notes);
});
}

Selenium ClickInterceptedException

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 extract the text from a div tag with style attribute set as "display: none;" through selenium

My html looks like this:
<div class="row">
<div class="col-md-7">
<ul class="breadcrumb">
<li id="get_data">Get data</li>
<li id="sampling_task">Sampling</li>
<li id="confirm_task">Confirmation</li>
</ul>
<div class="container-fluid">
<form action="#" method="post" enctype="multipart/form-data" role="form" class="form-horizontal">
{% csrf_token %}
<div class="form-group">
<label for="id_fileA" class="col-sm-3 control-label" style="text-align: left">
Select dataset A<span class='required_label'>*</span>
</label>
<div class="col-sm-9">
{{ form.fileA|attr:"class:form-control" }}
</div>
</div>
<div class="form-group"></div>
<div class="form-group">
<label for="id_fileB" class="col-sm-3 control-label" style="text-align: left">
Select dataset B<span class='required_label'>*</span>
</label>
<div class="col-sm-9">
{{ form.fileB|attr:"class:form-control" }}
</div>
</div>
<div class="form-group"></div>
<div class="form-group" id="sample_btn" style="display: none">
<label class="col-sm-3 control-label"></label>
<div class="col-sm-9">
<input type="button" name="theButton" id="sample-step" value="Start Sampling" class="btn btn-success btn-large disabled" style="border-radius: 5px;">
</div>
</div>
<div class="form-group">
<div class="col-sm-9 col-sm-offset-3" id="sample_msg" style="display: none;">
<p id="sample_text" style="font-size: medium">
Some ABCD message
</p>
</div>
</div>
<div class="form-group">
<div class="col-sm-9 col-sm-offset-3" id="get_sample_confirm_msg" style="display: none;">
<p>
<input type="button" style="height: 40px; width: 140px; border-radius: 5px" name="YesButton" id="accept-step" value="Accept & Continue" class="btn btn-success disabled">
<input type="button" style="height: 40px; width: 140px; border-radius: 5px" name="NoButton" id="cancel-step" value="Cancel Sampling" class="btn btn-danger disabled">
</p>
</div>
</div>
</form>
</div>
</div>
<div class="col-md-5">
</div>
</div>
The backend is a javascript and on button click, it do processing and if something fails the javascript code update the message.
var error = "<div class='alert alert-danger'><p>We encountered an error while sampling: <br /><strong>Sampling failed!!</strong></p>"; error += "<p>Please <a href='mailto:abcd#gmail.com'>contact us</a> if this error persists.</p>";
error += "</div>";
$('#sample_msg').html(error);
Now, in my selenium code if I do this:
sample_msg = self.driver.find_element_by_id('sample_msg')
I get an empty list result. What I want is to do is read the error in the "sample_msg" class if any and I have tried few things but its not working out. Help is appreciated. Thanks.
If you want to get access to hidden text you might need to use below code:
sample_msg = self.driver.find_element_by_id('sample_msg').get_attribute('textContent').strip()
Note that text property allows to get text from visible elements only
As you are trying to extract the error message Some ABCD message it is contained within a <p> tag which have parent <div> tag with style attribute set as display: none;. So to extract the text you can use the following code block :
element = driver.find_element_by_xpath("//div[#class='form-group']/div[#id='sample_msg']")
driver.execute_script("arguments[0].removeAttribute('style')", element)
print(driver.find_element_by_xpath("//div[#class='form-group']/div[#id='sample_msg']/p").get_attribute("innerHTML"))
So, you have to wait for sometime after clicking the button and once some message appears then you need to extract that message.
Try below:-
WebDriverWait wait = new WebDriverWait(webDriver, timeoutInSeconds);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id));
or
wait.until(ExpectedConditions.elementToBeClickable(By.id));
to be precise.
See also:
org.openqa.selenium.support.ui.ExpectedConditions for similar shortcuts for various wait scenarios.
org.openqa.selenium.support.ui.WebDriverWait for its various constructors.
You can check the python syntax also on the above links.

ExpressJS only sending 200 status code for index on first load. 304 everytime after that

So I have a local project running ExpressJS and I'm using ejs as my template engine. Whenever I start the server and go to the home page the index.html file renders properly, but every subsequent load of the index gives me the un-rendered index.html file and the status is 304. All other pages render fine everytime. If I restart the server, the first time I hit the home page it is rendered correctly, but still serves the un-rendered file after every page load after that. If I put a breakpoint in the route (I'm using WebStorm) I can hit the break point the first time, but never again. I assume this is because of the 304. I also have app.disable('etag'). Any help is much appreciated.
UPDATE
This is what is the browser will display when receiving a 304 status.
<%- include('includes/header.html'); %>
<%- include('includes/navigation.html'); %>
<!-- Top Slider and Booking form -->
<div id="home-top-section">
<!-- Main Slider -->
<div id="main-slider">
<div class="items">
<a href="http://google.com">
<img src="assets/img/slider/1.jpg" alt="3"/><!-- Change the URL section based on your image\'s name -->
</a>
</div>
<div class="items">
<a href="http://google.com">
<img src="assets/img/slider/3.jpg" alt="3"/>
</a>
</div>
<div class="items">
<a href="http://google.com">
<img src="assets/img/slider/4.jpg" alt="4"/>
</a>
</div>
<div class="items">
<a href="http://google.com">
<img src="assets/img/slider/2.jpg" alt="2"/>
</a>
</div>
</div>
<!-- Booking Form -->
<div class="booking-form-container container">
<div class="booking-form-inner-container">
<div id="main-booking-form" class="style-2">
<h2>Find A <span>Room</span></h2>
<form class="booking-form clearfix" action="#"><!-- Do Not remove the classes -->
<div class="input-daterange clearfix">
<div class="booking-fields col-xs-6 col-md-12">
<input placeholder="Choose check in date" class="datepicker-fields check-in" type="text" name="start" /><!-- Date Picker field ( Do Not remove the "datepicker-fields" class ) -->
<i class="fa fa-calendar"></i><!-- Date Picker Icon -->
</div>
<div class="booking-fields col-xs-6 col-md-12">
<input placeholder="Choose check out date" class="datepicker-fields check-out" type="text" name="end" />
<i class="fa fa-calendar"></i>
</div>
</div>
<div class="booking-fields col-xs-6 col-md-12">
<!-- Select boxes ( you can change the items and its value based on your project's needs ) -->
<select name="room-type">
<option value="">How Many Adult?</option><!-- Select box items ( you can change the items and its value based on your project's needs ) -->
<option value="2">1</option>
<option value="3">2</option>
<option value="4">3</option>
<option value="5">4</option>
<option value="6">5</option>
</select>
<!-- End of Select boxes -->
</div>
<div class="booking-fields col-xs-6 col-md-12">
<select name="guest">
<option value="">How Many Children ?</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
</div>
<div class="booking-button-container">
<input class="btn btn-default" value="Check Availability" type="submit"/><!-- Submit button -->
</div>
</form>
</div>
</div>
</div>
</div>
<!-- End of Top Slider and Booking form -->
<!-- Luxury Rooms -->
<div id="luxury-rooms">
<!-- Heading box -->
<div class="heading-box">
<h2>Luxury <span>Rooms</span></h2><!-- Title -->
<div class="subtitle">Best rooms with Best services</div><!-- Subtitle -->
</div>
<!-- Room Box Container -->
<div class="room-container container">
<!-- Room box -->
<div class="room-boxes">
<img src="assets/img/rooms/1.jpg" alt="King Suit" class="room-img"><!-- Room Image -->
<div class="room-details col-xs-6 col-md-4">
<div class="title">King Suit</div><!-- Room title -->
<div class="description"><!-- Room Description -->
Short description of rooms will be located in this section that you can describe some special features and equipment of rooms. Visitors can get more information about this rooms by clicking on "Details" button.
</div>
Details<!-- Detail link -->
</div>
<div class="price-container col-xs-6 col-md-8">
<div class="price">
<span>$550</span>
- Per Night
</div>
</div>
</div>
<!-- Room box -->
<div class="room-boxes right">
<img src="assets/img/rooms/2.jpg" alt="Royal Suit" class="room-img">
<div class="room-details col-xs-6 col-md-4">
<div class="title">Royal Suit</div>
<div class="description">
Short description of rooms will be located in this section that you can describe some special features and equipment of rooms. Visitors can get more information about this rooms by clicking on "Details" button.
</div>
Details
</div>
<div class="price-container col-xs-6 col-md-8">
<div class="price">
<span>$490</span>
- Per Night
</div>
</div>
</div>
<!-- Room box -->
<div class="room-boxes">
<img src="assets/img/rooms/3.jpg" alt="Deluxe Two-bedroom Suite" class="room-img">
<div class="room-details col-xs-6 col-md-4">
<div class="title">Deluxe Two-bedroom Suite</div>
<div class="description">
Short description of rooms will be located in this section that you can describe some special features and equipment of rooms. Visitors can get more information about this rooms by clicking on "Details" button.
</div>
Details
</div>
<div class="price-container col-xs-6 col-md-8">
<div class="price">
<span>$370</span>
- Per Night
</div>
</div>
</div>
</div>
</div>
<!-- End of Luxury Rooms -->
<!-- Special Packages -->
<div id="special-packages" class="container">
<!-- Heading box -->
<div class="heading-box">
<h2>Special <span>Packages</span></h2><!-- Title -->
<div class="subtitle">Choose one of our special offers</div><!-- Subtitle -->
</div>
<!-- Package Container -->
<div class="package-container clearfix">
<!-- Package Box -->
<div class="package-box wow fadeInUp col-sm-6 col-md-4">
<div class="package-inner">
<div class="title">Diamond</div>
<div class="price"><span>$450</span>per night</div>
<div class="package-details">
<ul>
<li>Flight Ticket</li>
<li>Restaurant ( Lunch / Dinner )</li>
<li>Music Concert</li>
<li>Airport Pick-up</li>
<li>Sport Activities</li>
</ul>
</div>
Select Package
</div>
</div>
<!-- Package Box -->
<div class="package-box wow fadeInUp col-sm-6 col-md-4" data-wow-delay="0.5s">
<div class="package-inner">
<div class="title">Gold</div>
<div class="price"><span>$340</span>per night</div>
<div class="package-details">
<ul>
<li>Flight Ticket</li>
<li>Restaurant ( Lunch )</li>
<li>Music Concert ( 50% off )</li>
<li>Airport Pick-up</li>
<li>Sport Activities</li>
</ul>
</div>
Select Package
</div>
</div>
<!-- Package Box -->
<div class="package-box wow fadeInUp col-sm-6 col-md-4" data-wow-delay="1s">
<div class="package-inner">
<div class="title">Silver</div>
<div class="price"><span>$230</span>per night</div>
<div class="package-details">
<ul>
<li>Flight Ticket</li>
<li>Restaurant ( 20% off Lunch )</li>
<li>Music Concert ( 30% off )</li>
<li>Airport Pick-up</li>
<li>Sport Activities</li>
</ul>
</div>
Select Package
</div>
</div>
</div>
</div>
<!-- End of Special Packages -->
<!-- Gallery -->
<div id="gallery">
<!-- Heading box -->
<div class="heading-box">
<h2>Pinar <span>Gallery</span></h2><!-- Title -->
</div>
<!-- Gallery Container -->
<div class="gallery-container">
<div class="sort-section">
<div class="sort-section-container">
<div class="sort-handle">Filters</div>
<ul class="list-inline">
<li>All</li>
<li>Restaurant</li>
<li>Bars</li>
<li>Pool</li>
<li>Rooms</li>
<li>Lobby</li>
</ul>
</div>
</div>
<ul class="image-main-box clearfix">
<li class="item col-xs-6 col-md-3 lobby">
<figure>
<img src="assets/img/gallery/1.jpg" alt="11"/>
Enlarge
<figcaption>
<h4><span>Great</span> View</h4>
</figcaption>
</figure>
</li>
<li class="item col-xs-6 col-md-6 pool">
<figure>
<img src="assets/img/gallery/2.jpg" alt="11"/>
Enlarge
<figcaption>
<h4><span>Outdoor</span> Pool</h4>
</figcaption>
</figure>
</li>
<li class="item col-xs-6 col-md-3 bars">
<figure>
<img src="assets/img/gallery/3.jpg" alt="11"/>
Enlarge
<figcaption>
<h4><span>Delicious</span> Foods</h4>
</figcaption>
</figure>
</li>
<li class="item col-xs-6 col-md-3 restaurant">
<figure>
<img src="assets/img/gallery/4.jpg" alt="11"/>
Enlarge
<figcaption>
<h4><span>International</span> Foods</h4>
</figcaption>
</figure>
</li>
<li class="item col-xs-6 col-md-3 pool">
<figure>
<img src="assets/img/gallery/5.jpg" alt="11"/>
Enlarge
<figcaption>
<h4><span>Cozy</span> Spaces</h4>
</figcaption>
</figure>
</li>
<li class="item col-xs-6 col-md-3 rooms">
<figure>
<img src="assets/img/gallery/6.jpg" alt="11"/>
Enlarge
<figcaption>
<h4><span>Comfortable </span> Rooms</h4>
</figcaption>
</figure>
</li>
<li class="item col-xs-6 col-md-3 pool">
<figure>
<img src="assets/img/gallery/7.jpg" alt="11"/>
Enlarge
<figcaption>
<h4><span>Relaxation</span> Spaces</h4>
</figcaption>
</figure>
</li>
<li class="item col-xs-6 col-md-6 pool">
<figure>
<img src="assets/img/gallery/8.jpg" alt="11"/>
Enlarge
<figcaption>
<h4><span>Indoor</span> Pool</h4>
</figcaption>
</figure>
</li>
</ul>
More ...
</div>
</div>
<!-- End of Gallery -->
<%- include('includes/footer.html'); %>
instead of the rendered version. Notice the includes at the top and bottom of the page.
So, the issue was simply because I was using .html templates instead of .ejs. Word to the wise, if you buy a template that has static .html files and want to use a templating engine such as .ejs, make sure you change .html to .ejs or you will run into all types of issues.

mdl-switch not working inside mdl-grid & mdl-card

I am trying to put an mdl-switch inside an mdl-card which sits inside an mdl-grid.
the mdl-switch works fine if placed outside the card but just appears as a checkbox inside the card.
<script type="text/ng-template" id="nodes.html">
<h4 class="mdl-typography--display-1 pageTitle">asdf</h4>
<div class="mdl-grid">
<div ng-repeat="a in b" class="mdl-cell mdl-cell--4-col">
<div class="status-card mdl-card mdl-shadow--2dp status-green">
<div class="mdl-card__title mdl-card--expand">
<h4 style="width: 100%">
<label class="mdl-switch mdl-js-switch mdl-js-ripple-effect" for="BSL">
<input type="checkbox" id="BSL" class="mdl-switch__input" ng-model="a.asdfChk" />
<span class="mdl-switch__label">
<small>ASDF</small>
</span>
</label>
</h4>
</div>
<div class="mdl-card__actions mdl-card--border">
<div class="mdl-layout-spacer"></div>
</div>
</div>
</div>
</div>

Resources