xpath preceding-sibling not working - xpath

I am trying to click on the first button which deletes the item which is the second button.
<tr>
<td>
<div class="btn-group">
<button class="btn btn btn-danger" name="delete" type="button">
</div>
</td>
<td>
<span class="class"></span>
</td>
<td>
<button class="btn" name="item" type="button">
</td>
</tr>
XPath
//button[contains(.,'${ITEM}')]/preceding-sibling::button[#name='delete']

I'm going to assume you're just not showing us the button text in your example HTML, since neither of your buttons seems to have any content.
preceding-sibling would not work here, since the two buttons are not siblings. However preceding::button should work in this case. Note the [1] at the end which is needed in order to select the closest match:
//button[contains(.,'${ITEM}')]/preceding::button[#name='delete'][1]
The following should also work, and is in my opinion a bit cleaner:
//tr[.//button[contains(., '${ITEM}')]]//button[#name ='delete']

Related

Thymeleaf iteration stuck at 0 in dynamically created form (Spring Boot)

I'm trying to create a table from a list phases where each row has forms that will relate to the list item phase for that row - so row 1 has a cell for "Phase 1" and then a button that will rename "Phase 1", then the next row has "Phase 2" and a button for that.
However, when I try to access the index of that list iteration from within the form it always returns 0, so the first cell of row 2 still says "Phase 2" but the form still passes the index of "Phase 1" to the HTTP request. It can definitely still see the list, because if I change it to return phaseStat.size rather than the phaseStat.indexit gives the correct number.
The cells containing the phase name work fine, it's only once I get inside the <form> tag that it gets stuck on the first item of the list. How do I get the form to keep pace with the iteration with the rest of the table?
<table class="table">
<tr th:each="phase : ${phases}">
<td class="table-light" th:text="${phase}"></td>
<td>
<form th:action="#{/tasks/phases/rename}">
<button type="button" class="btn btn-outline-primary btn-sm" title="Rename" onclick="openForm('renamephaseform')">Rename</button>
<div class="form-popup card mb-3" id="renamephaseform">
<h3 class="card-header">Rename
<button type="button" class="btn btn-outline-secondary btn-sm closebutton" title="Close menu" onclick="closeForm('renamephaseform')">⛌</button>
<br>
</h3>
<div class="card-body">
<input type="text" class="form-control" id="phasename" placeholder="Phase name" th:name="newname">
<button type="submit" class="btn btn-primary" title="Rename" th:name="phasenumber" th:value="${phaseStat.index}">Rename <span th:text="${phase}"></span></button>
</div>
</div>
</form>
</td>
</tr>
</table>
<script>
function openForm(name) {
document.getElementById(name).style.display = "block";
}
function closeForm(name) {
document.getElementById(name).style.display = "none";
}
</script>
Edit:
The weird thing is, the iteration works perfectly fine in this example and I can't see what the difference is...
<table class="table">
<tr th:each="album : ${albums}">
<td class="table-light" th:text="${album.name} + ' (' + ${album.artist} + ')'"></td>
<td>
<form th:action="#{/index}">
<button type="submit" class="btn btn-primary btn-sm" th:name="id" th:value="${album.id}">Open album</button>
</form>
</td>
</tr></table>
So, what I ended up doing that made this work (thanks to andrewJames) is including the iteration index in the form id to create a unique name.
So for the Open button I included
th:attr="onclick='openForm(\'renamephaseform' + ${phaseStat.index} + '\')'", in the Closebutton th:attr="onclick='closeForm(\'renamephaseform' + ${phaseStat.index} + '\')'" and in the form tag th:attr="id='renamephaseform' + ${phaseStat.index}".
Elswhere, I've sometimes used string values for this (eg the phase name, task name etc) to make it easier to review in the Inspector.

laravel delete form is not working

#extends('layouts.app')
#section('content')
<div class="row">
<div style="float:left;" class="col-md-8">
<h3>Currency</h3>
</div>
<div style="float:right;" class="col-md-4">
<i class="fa fa-edit" style="color:white;"></i>Add New
<input type="text" id="search" name="search" placeholder="search" class="form-control-sm col-md-8 ml-1" style="float:right;"><br><br>
</div>
</div>
#if(count($currencies) > 0 )
<table class="table table-striped table-sm" >
<thead>
<tr><th scope="col">ID</th><th scope="col">Currency</th><th scope="col">Country</th><th scope="col" colspan="2" style="text-align:right">Actions</th></tr>
</thead>
#foreach($currencies as $currency)
<tr><td scope="row">{{$currency->id}}</td>
<td>{{$currency->title}}</td>
<td>{{$currency->country}}</td>
{!!Form::open(['action'=>['CurrencyController#destroy', $currency->id], 'method'=>'POST'])!!}
{{Form::hidden('_method','DELETE')}}
#csrf
<td><button type="submit" class="btn btn-danger btn-sm" style="float:right"><i class="fa fa-remove" style="color:white;"></i>Delete</button>
</i>Edit</td></tr>
{!!Form::close() !!}
#endforeach
</table>
{{$currencies->links()}}
#else
<p> No Data Available </p>
#endif
#endsection
Hi all, The delete form is not submitting in this code and I tried so many thing but I could not figure out the issue. Please help me with this.
It looks to me that your html is wrong, you open, close your form and place #csrf outside your td tag while submit button is inside it
Try to move your form definition inside td tag like:
<td>
{!!Form::open(['action'=>['CurrencyController#destroy', $currency->id], 'method'=>'POST'])!!}
{{Form::hidden('_method','DELETE')}}
#csrf
<button type="submit" class="btn btn-danger btn-sm" style="float:right"><i class="fa fa-remove" style="color:white;"></i>Delete</button>
</i>Edit
{!!Form::close() !!}
</td>
Try changing the method in the actual form tag to DELETE? By default if you are using something like route::resource in your routes, it will automatically assign the DELETE method to the route, not the POST.
I can see you're specifying the delete method in a hidden element anyway, but its worth a try.
{!!Form::open(['action'=>['CurrencyController#destroy', $currency->id], 'method'=>'POST'])!!}
If you're never quite sure, run php artisan route:list in your terminal inside your project root directory, and it will give you a full list of the routes and methods for your application.

Not working below angularjs code

<tr data-ng-repeat="myTrack in myTrackList">
<td class="project-status" data-ng-switch="myTrack.opened">
<span data-ng-switch-when="true" class="label label-primary">Active</span>
<span data-ng-switch-when="false" class="label label-default">Inactive</span>
</td>
<td class="project-title"><a
id="{{myTrack.trackId}},{{myTrack.file.fileId}}"
href="getDocumentByFileId?fileId={{myTrack.file.fileId}}&trackId={{myTrack.trackId}}">{{myTrack.trackName}}</a>
<br /><small>Description: {{myTrack.description}}</small>
<br /> <small>Created: {{myTrack.createdTime}}</small></td>
<td class="project-people" colspan="2">
<div class="project-people" ng-repeat="persons in myTrack.personTrack">
<a href=""><img alt="image" title="persons.firstName"
class="img-circle" src="persons.profilePictureUrl"></a>
</div>
</td>
<td class="project-actions"><a href="#"
class="btn btn-white btn-sm"><i class="fa fa-folder"></i>
View </a></td>
</tr>
I taken list of objects and in single object there is set of user with their profile picture. I used ng-repeat in ng-repeat for repeating users set from list of objects but my inner ng-repeat not working correctly. please help me.
As for the code bellow :
<div class="project-people" ng-repeat="persons in myTrack.personTrack">
<img alt="image" title="persons.firstName" class="img-circle" src="persons.profilePictureUrl">
</div>
The browser do not know that you are using angular js variable for title or src. So you will need.
<div class="project-people" ng-repeat="persons in myTrack.personTrack">
<img alt="image" ng-attr-title="{{persons.firstName}}" class="img-circle" ng-src="{{persons.profilePictureUrl}}">
</div>
So you will need to include the ng tags when you want to use the angular js for tags.

Watir-Webdriver - Parsing through table and clicking start/stop toggle

Please be gentle. I'm very new to Ruby and Watir. In general also new to UI automation testing. I'm trying to parse through a table then click a toggle that start/stops an application. The applications that can be turned on and off are not set. They can range from 1 to 'infinite' number applications. I need something that will parse through each row and click the toggle. if the application is started, I need to turn it off and vice-versa. No matter how many rows exist. The row also contains an element in the first column that allows the application to be clicked and brought to another page that gives details about said application. The toggle exists in the last column of the table. Here is the HTML I'm looking at with two applications deployed. It may be something simple that I'm missing. I'm also normally an IT admin that just got thrown into this. Thanks for all the help
<table id="apps_data" class="table table-striped table-bordered table-hover ng-scope">
<thead>
<tr>
</thead>
<tbody>
<tr class="link ng-scope" ng-repeat="app in services.data | orderBy:services.sort">
<td class="ng-binding" ng-click="click_app(app.Id)">Zenoss</td>
<td class="ng-binding deploy-success" ng-class="app.deploymentClass">
<span class="glyphicon glyphicon-ok" ng-class="app.deploymentIcon"></span>
successful
</td>
<td class="ng-binding">default</td>
<td>
<div class="toggle btn-group" data-toggle="buttons">
<label class="ng-binding btn btn-success active" ng-click="clickRunning(app, 'start', servicesService)" ng-class="app.runningClass">
<input class="ng-pristine ng-valid" type="radio" value="1" ng-model="app.Running" name="running0">
started
</label>
<label class="ng-binding btn btn-default off" ng-click="clickRunning(app, 'stop', servicesService)" ng-class="app.notRunningClass">
<input class="ng-pristine ng-valid" type="radio" value="stopped" ng-model="app.Running" name="running0">
</label>
</div>
</td>
</tr>
<tr class="link ng-scope" ng-repeat="app in services.data | orderBy:services.sort">
<td class="ng-binding" ng-click="click_app(app.Id)">Zenoss</td>
<td class="ng-binding deploy-success" ng-class="app.deploymentClass">
<span class="glyphicon glyphicon-ok" ng-class="app.deploymentIcon"></span>
successful
</td>
<td class="ng-binding">default</td>
<td>
<div class="toggle btn-group" data-toggle="buttons">
<label class="ng-binding btn btn-success active" ng-click="clickRunning(app, 'start', servicesService)" ng-class="app.runningClass">
<input class="ng-pristine ng-valid" type="radio" value="1" ng-model="app.Running" name="running1">
started
</label>
<label class="ng-binding btn btn-default off" ng-click="clickRunning(app, 'stop', servicesService)" ng-class="app.notRunningClass">
<input class="ng-pristine ng-valid" type="radio" value="stopped" ng-model="app.Running" name="running1">
</label>
</div>
</td>
</tr>
</tbody>
</table>
I have this so far, but it's just going to the first line.
if ff.div(:class, 'toggle btn-group').label(:class, 'ng-binding btn btn-success active').exist?
ff.div(:class, 'toggle btn-group').label(:class, 'ng-binding btn btn-default off').click; sleep 1
ff.div(:class, 'toggle btn-group').label(:class, 'ng-binding btn btn-default off').exist?
ff.div(:class, 'toggle btn-group').label(:class, 'ng-binding btn btn-default off').click; sleep 1
end
This might do what you want:
apps = browser.table(:id => 'apps_data').tbody.trs
apps.each do |app|
set_radios = app.radios.find_all{ |radio| !radio.set? }
if set_radios.length == 2
# Neither radio button is set, so do nothing?
else
set_radios.first.set
end
end
What this does is:
Gets a collection of all tr elements in the table body. Each tr element is assumed to represent an "app".
Iterates through each row (app):
Counts the number of radio buttons that are not set.
If neither of the 2 radio buttons is set, it does nothing.
If only one unset radio button is found, it is set.
Note that since the 2 radio buttons of the app have the same name attribute value, setting the one radio button will automatically unset the other.

error Element //..... not found

I got an error [error] Element //div[#id='newslist_config']//button[#type='button'] not found when I use auto run to run my selenium test but if I click at the command and choose Execute this command The tests pass. Could you tell me why selenium can not find that element?
My selenium test is
<tr>
<td>click</td>
<td>//div[#id='newslist_config']//button[#type='button']</td>
<td></td>
</tr>
The html is
<div id="newslist_config" class="section-box span8">
<div class="accordion-group">
<div class="accordion-heading">
<h3>News-List Configuration</h3>
<a class="btn btn-danger close_newslist_config" data-dismiss="modal" href="#">remove widget</a>
<button class="btn btn-info collapse-btn" type="button" href="#collapse_newslist" data-parent="#newslist_config" data-toggle="collapse">
<span class="edit-btn-txt">
<span class="collapse-btn-txt">
</button>
</div>
<div id="collapse_newslist" class="collapse collapse-box">
</div>
</div>
You could instead try the xpath: //div[#id='accordion-heading']/button[#type='button']
This is a more direct path; if it does not work I would suggest trying to click one of the containing spans as sometimes, due to styling, clicking an elements span achieves more consistent results. I sometimes have this issue when working with WebDriver in KendoUI.
Approach:
1.Derive the CSS Selector from the given DOM.
css=#newslist_config .collapse-btn
2.Perform the click
driver.findElement(By.cssSelector("#newslist_config .collapse-btn")).click();

Resources