How to click a button in row in a table using protractor js - testing

I am writing protractor test cases. I want to click on edit button. When I am checking by id it is not found.
Code:
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>Code</th>
<th>Start Date</th>
<th></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="batch in batches.list">
<td><a ui-sref="root.courses.detail.batches.assessments({ batch_id: batch.id,assessment_status: 'published'})">BID00{{batch.id}}</a></td>
<td>{{batch.start_date}}</td>
<td>
<button id="edit" type="button" class="btn btn-default btn-sm" tooltip-placement="top" tooltip="Edit" ng-controller="batchesCtrl" ng-click="edit_batch(batch.id)"><i class="glyphicon glyphicon-edit"></i></button>
<button type="button" id="delete(batch.id)" class="btn btn-danger btn-sm" tooltip-placement="top" tooltip="Delete" ng-click="remove_batch(1, batch.id)" confirmation-needed="Do you really want to delete this batch?"><i class="glyphicon glyphicon-trash" ></i></button>
</td>
</tr>
</tbody>
</table>
How can I make it work?

There are a few problems in your example. In html an ID should be unique on a page. So you can't use an id inside an element that repeats.
You have several options. You could address the button by one of it's styleclasses that the other button does no have like
element(by.repeater('batch in batches.list').row(0)).element(by.css('button.btn-default')).click();
You can also just specify you want the first button it finds like
element(by.repeater('batch in batches.list').row(0)).element(by.css('button:first-of-type')).click();
Alternatively you can also address the element with only css. Sometimes that is easier to maintain than the repeater:
element(by.css('tr:first-of-type > td:last-child > button:first-of-type')).click();

Here i am not sending delay so what happen i am checking for the button which is not loaded
ptor.sleep(500); fixes my problem. It took so much time to identify

Related

listen for server sent event (SSE) with HTMX and append to a table

I made a simple Go backend that renders an html table (from a SQLite database).
In the same backend i have an /updates endpoint with SSE events when a new row is added to the database.
I want to use htmx to listen for events and then add a row to the table.
What is the right pattern to do this?
I've read https://htmx.org/extensions/server-sent-events/
the example here is to trigger a GET when an event arrives:
<div hx-ext="sse" sse-connect="/updates">
<div hx-get="/table" hx-trigger="sse:rowadded">
...
</div>
</div>
In this way i request the entire table at every update.
How could i add only a single row to the existent rendered table?
You can do this with client side templates.
See https://htmx.org/extensions/client-side-templates/
Example:
<table>
<thead>
<tr>
<th>
Manufacturer
</th>
<th>
Model
</th>
<th>
Power (KW)
</th>
</tr>
</thead>
<tbody id="idTableBody">
<tr id="ModelId_250">
<td>Husqvarna</td>
<td>701 Supermoto</td>
<td>55</td>
</tr>
</tbody>
</table>
In this example mustache is used as templating engine.
<div hx-ext="client-side-templates">
<div hx-ext="sse" sse-connect="/sse-motorbikes">
<div sse-swap="new_bike"
hx-swap="afterbegin"
hx-target="#idTableBody"
mustache-template="idTemplateInsertModel">
</div>
</div>
</div>
Note: EventName is new_bike
Here is the template:
<template id="idTemplateInsertModel">
<tr id="modelId_{{modelId}}">
<td>
{{manufacturer}}
</td>
<td>
{{model}}
</td>
<td>
{{power}}
</td>
</tr>
</template>
With this sse event
type: "new_bike"
data:'{"modelId":208,"manufacturer":"Honda","model":"CRF 1100 L Africa Twin","power":75}'
this row will be inserted into the table body
<tr id="modelId_208">
<td>Honda</td>
<td>CRF 1100 L Africa Twin</td>
<td>75</td>
</tr>
Update
If you want to use a GET request to fetch the new row from the server, you can pass the data sent with the sse event (e.g. an id) to the request.
Check out the answer to this question.
https://stacko...how-to-get-url-for-htmx-get-from-an-sse-event-which-itself-triggers-the-hx-get-c

Selenium XPath multiple selection

I want to find all elements in the table that match the following conditions:
-div text contains '2019';
-div class='excellent';
here is the HTML code excerpt:
<tr>
<td>Name of Person1</td>
<td>
<div class="testDate">21/12/2019</div>
<div class="excellent"></div>
</td>
</tr>
<tr>
<td>Name of Person2</td>
<td>
<div class="testDate">01/12/2017</div>
</td>
</tr>
I tried this solution:
//tr/td[2][div/text()='21/12/2019'][div[#class='starred']]
but I need the year only and not entirely date.
Use the below xpath.
//tr/td[div[contains(.,'2019')]and div[#class='excellent']]
Screenshot:

How to have an always editable column with footable

I would like to use footable (I've already use footable for its responsive exploding display )and this to show records coming from a database but with a need to have a column (which display the stock quantity of products) that thye user can modify just by typing. Is there any way of having some sort of content editable column....
Any idea will be welcome
You can render the column as HTML, which will prevent footable from taking over the content of the cell, and have an <input type="text" /> for each row.
Something like:
<table>
<thead>
<tr>
<th>Name</th>
<th data-type="html">In stock</th>
</tr>
</thead>
<tbody>
<tr>
<td>Apples</td>
<td><input type="number" step="any" value="3"/></td>
</tr>
<tr>
<td>Oranges</td>
<td><input type="number" step="any" value="0"/></td>
</tr>
</tbody>
</table>
Check the documentation at https://fooplugins.github.io/FooTable/docs/getting-started.html , look for "Column Options" > "Type" .
After rendering you can attach an event listener to the input fields and send ajax calls accordingly.

xpath with following-sibling

I want to access the table with classname 'table table-hover' that should be under the class=='box-title' that contains the text 'OODR Items for next 20 Days'. Can any one please help me out to get the xpath for this ? I tried with following-sibling but no luck. Thanks in advance.
<?xml version="1.0" encoding="UTF-8"?>
<div id="topTenSellers" class="box box-solid box-primary frontpageWidget">
<div class="box-header">
<i class="fa fa-group" />
<h3 class="box-title">OODR Items for next 20 Days</h3>
<div class="box-tools pull-right">
<button class="btn btn-primary btn-sm" data-widget="collapse">
<i class="fa fa-minus" />
</button>
</div>
</div>
<!-- /.box-header -->
<div class="box-body no-padding">
<table class="table table-hover">
<tbody>
<tr>
<th style="width: 10px">#</th>
<th>Booking</th>
<th>Item Start Date</th>
<th>Site</th>
<th>Supplier</th>
</tr>
<tr>
<td>
<strong>1</strong>
</td>
<td>
(642143)
</td>
<td>21/10/2017 00:00:00</td>
<td>Ski</td>
<td>OODR - Out of Date Range</td>
</tr>
</tbody>
</table>
</div>
<!-- /.box-body -->
</div>
You can try following instead of following-sibling as mentioned h3 and table nodes are not siblings:
//div[#id="topTenSellers"]//h3[#class="box-title" and .="OODR Items for next 20 Days"]/following::table[#class="table table-hover"]
If there is only one element of that class name then either of these will work. One thing to note though, selenium can struggle with spaces in class names depending on the version and browser. If you find that is the case, then use multiple contains to handle the spaces.
//table[contains(#class,'table table-hover')]
//table[#class = 'table table-hover']
If you need that the element as a child of that OODR Items for the next 20 days
//h3[contains(text(),'OODR Items for the next 20 days')]/parent::div/following-sibling::div/table[#class ='table table-hover']
This path uses your anchor point, "OODR Items..", then goes to the parent, then sibling, then to the item with the specified class name. Good luck!

Disabling many drop down list all at once using javascript

<table align="center" border="0" id="typeTable" >
<%for(int i=1;i<=count;i++){%>
<tr id="a">
<td align="left" valign="top">
<p>Problem Type <%=i+1 %></p>
</td >
<td align="left" valign="middle">
<p>Number of question to generate: </p>
</td>
<td align="left" valign="middle" >
<select name="type<%=i %>" id="mySelect" >
<option>0</option>
<option>5</option>
<option>10</option>
<option>20</option>
</select>
</td>
</tr>
<%}%>
<input type="hidden" name="totalNumOfType" value="<%=count%>"/>
</table>
Hi, I have the code above to do a for loop for the table row when I get a count from the database to show how many types of problems in math topic.
The drop down menu list name I have put the int I for the name to have each row an individual name so that I can pass the value of each drop down list selected to the next page which I can do successfully.
The issue now is I have problem disabling all the drop down menu list at onece using the javascript as it will not know how many count there will be.
I have used the following code to disable the drop down menu for example.
<script type="text/javascript">
function disable()
{
document.getElementById("mySelect").disabled=true;
}
function enable()
{
document.getElementById("mySelect").disabled=false;
}
</script>
I have been thinking but no avail. any help would be much appreciated. Thank you!
did you tryed jquery prop function : $("#mySelect").prop("disabled",true) ?