Loop in table with Watir - watir

Stuck with watir trying to create a loop to click in all the links included in a table. Currently the table has this format:
<table id="test">
<tbody><tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Link</th>
</tr>
<tr>
<td>Jill</td>
<td>Smith</td>
<td>http://facebook.com</td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>http://google.com</td>
</tr>
</tbody></table>
And my current attempt looks like:
browser.table(:id => "test").rows do |tr|
tr.each do |td|
td.links.click
end
end
This code above does nothing in the browser & neither returns something in the terminal (no errors, no outputs).
Also tried a different approach using columns:
columns = browser.table(:id => "test").strings.transpose
browser.columns.each do |t|
t.click
browser.back
end
That outputs this error: jsfiddle.rb:24:in <main>': undefined methodcolumns' for # (NoMethodError)

The newer versions of Watir, version 6.0, automatically attempts to relocate stale elements. As a result, as long as the initial page does not change each time you reload it, you no longer need to save some sort of reference data before clicking the links.
It simply becomes:
my_table = browser.table(:id, 'test')
my_table.links.each do |link|
link.click
browser.back
end

This should work to click on each link in the table:
my_table = browser.table(:id, 'test')
table_links = my_table.links.map(&:text)
table_links.each do |link_text|
my_table.link(:text, link_text).click
browser.back
end
Largely based on Justin Ko's answer here.

Related

Import CSV to Django, save data and show results within template

I need your help with uploading data(CSV) to django app and save data to database. Also i want to show row wise results within the template. Attached is the page image for your reference. Please guide how can i implement the same.image
I had worked in some similar project similar, recive a csv and upload the data in different databases.
I used pandas to deal with different types of user friendly tabular extensions, but if you gonna work only with csv you can use the csv lib from python.
you can simply put some form for upload the csv to allow the user to send the file to django application.
these example we used this to catch a xlsx file and then transform in a dataframe(using pandas) to be easy to deal.
archiveXLSX = request.FILES['xlsx_file']
df = pd.read_excel(archiveXLSX,keep_default_na=False)
now you have the data inside the django backends and need transform these data and make shure who these data are Ok to load in the database.
after all verification we put the data in a list(without save this).
list_example = [
ExampleModel(data1,data2,data3),
ExampleModel(data1,data2,data3),
]
To upload to database, is interesting insert the data using bulk_create(to avoid execute multiples inserts) bulk_create can do it more fast than create one per one .
Ex:
ExampleModel.objects.using('database').bulk_create(list_example)
so if you want show these data in a template i recommend you to create some table in the database who will indicate the date of upload, file that user uploaded and the id of the data upload from these file. ex:
id, file_name , date , id_data
1 ,example.csv,20 - 04 - 2020, 2
2 ,example.csv,20 - 04 - 2020, 4
3 ,example.csv,20 - 04 - 2020, 2
Now. To deal whit these two models you need to create the csv model objects while create the model objects for the data from csv (make sure you will save first the model of the Data from csv in these case is ExampleModel).
Let's suppose who after verify these data, processing and these common things. You put them in some dictionary, the function to save them can be like this:
csvDataToCreate = []
dataToCreate = []
for data in dataDict:
example = ExampleModel(data['data1'],data['data2'],data['data3'])
dataToCreate.append(example)
csvData = ExampleCsvModel(filename, datetime.now().date(), example)
csvDataToCreate.append(csvData)
now you have all the information you need.
The view for csvData can be a simple select.
csvData.objects.filter(file_name='file.csv',date='xx-xx-xxxx')
and the template is simple too:
<table class="table table-striped">
<thead>
<tr>
<th scope="col" style="width: 35%;">data1</th>
<th scope="col" style="width: 45%;">data2</th>
<th scope="col" style="width: 5%;">data3</th>
</tr>
</thead>
<tbody>
{% for csv in csvitens %}
<tr>
<td style="width: 35%;"><div class='btn'>{{csv.id_data.data1}}</div></td>
<td style="width: 35%;"><div class='btn'>{{csv.id_data.data2}}</div></td>
<td style="width: 35%;"><div class='btn'>{{csv.id_data.data3}}</div></td>
<tr>
{% endfor %}
</tbody>
</table>
for this task you can use the css framework of your choice, here i ised boostrap4 .

Return value from an HTML class/scope?

I have a webpage that I'm trying to return a value from, however I can't find the right way to grab it with Selenium.
Here's the relevant HTML part:
<table class="table table-striped">
<tbody>
<tr class="hidden-sm hidden-xs">
<th scope="row"><a style="cursor: pointer"
onClick="document.formShip.P_IMO.value='9526942';document.formShip.submit();">
9526942</a>
</th>
I'm trying to get 9526942.
I've tried:
imo = driver.find_element_by_xpath("//*[contains(text(), 'document.formShip.P_IMO.value')]")
and looked around here, but don't know what element this is. I tried looking for the class hidden-sm hidden-xs, to no avail:
imo = driver.find_element_by_class_name('hidden-sm hidden-xs')
if you want to get the text you need to use .text. The .text method can be used with a webelement which some text in that.
in your first example which you tried, you are passing a different parameter with text(). usually when you use text(), you need to pass the value which is there between closing and open tags (the text which you see on the screen)
you simply try this.
imo = driver.find_element_by_xpath(.//tr[#class='hidden-sm hidden-xs']).text

mark all check boxes in internet explorer using excel vba

I'm trying to create excel macro which will mark 75 check boxes in a certain table on internet explorer page
the code of that table is :
<TABLE id=ctl00_MasterMain_ucGenConfig_ucConfigContainer_ucConfigPopup_cblSchemes border=0><TBODY>
<TR>
<TD><INPUT id=ctl00_MasterMain_ucGenConfig_ucConfigContainer_ucConfigPopup_cblSchemes_0 type=checkbox name=ctl00$MasterMain$ucGenConfig$ucConfigContainer$ucConfigPopup$cblSchemes$0><LABEL for=ctl00_MasterMain_ucGenConfig_ucConfigContainer_ucConfigPopup_cblSchemes_0>Start</LABEL></TD></TR>
<TR>
<TD><INPUT id=ctl00_MasterMain_ucGenConfig_ucConfigContainer_ucConfigPopup_cblSchemes_1 type=checkbox name=ctl00$MasterMain$ucGenConfig$ucConfigContainer$ucConfigPopup$cblSchemes$1><LABEL for=ctl00_MasterMain_ucGenConfig_ucConfigContainer_ucConfigPopup_cblSchemes_1>Start2</LABEL></TD></TR>
<TR>
<TD><INPUT id=ctl00_MasterMain_ucGenConfig_ucConfigContainer_ucConfigPopup_cblSchemes_2 type=checkbox name=ctl00$MasterMain$ucGenConfig$ucConfigContainer$ucConfigPopup$cblSchemes$2><LABEL for=ctl00_MasterMain_ucGenConfig_ucConfigContainer_ucConfigPopup_cblSchemes_2>Default</LABEL></TD></TR>
<TR>
and so on
I have tried various ways but it doesn't want to play
With IE.document.getElementsByName("ctl00_MasterMain_ucGenConfig_ucConfigContainer_ucConfigPopup_cblSchemes")
.Item.Click
end with
and
With IE.document.getElementsByName("checkBoxlist(ctl00_MasterMain_ucGenConfig_ucConfigContainer_ucConfigPopup_cblSchemes)")
.Item(0).Checked = True 'Entered
End With
and
For Each htmlelement In IE.document.getElementsByName("ctl00_MasterMain_ucGenConfig_ucConfigContainer_ucConfigPopup_cblSchemes")
htmlelement.Item(0).Click
Next htmlelement
Thanks in advance for any help or leads :)
I am making an assumption here that the checkboxes that have an id like this:
ctl00_MasterMain_ucGenConfig_ucConfigContainer_ucConfigPopup_cblSchemes_0
Have an identifier that begins at 0, as above, and increments by 1 to 74 (corresponding to your request for 75 checkboxes).
If that is the case, something like this may work:
Dim sBaseName As String
Dim i As Integer
'The base id of the checkboxes
sBaseName = "ctl00_MasterMain_ucGenConfig_ucConfigContainer_ucConfigPopup_cblSchemes_"
For i = 0 To 74 '75 checkboxes
ie.Document.getElementByID(sBaseName + CStr(i)).Click
Next i
Of course you must be sure you have set ie appropriately, navigated to the page, etc.
This code will first grab and click
ctl00_MasterMain_ucGenConfig_ucConfigContainer_ucConfigPopup_cblSchemes_0
Then i increments by 1, so it will grab and click
ctl00_MasterMain_ucGenConfig_ucConfigContainer_ucConfigPopup_cblSchemes_1
And so on, to 74.

Adding new xElement after ALL found Descendants

I have an xDocument with multiple various xElements.
I can successfully find a specific xElement by searching via it's xAttributes & then Add a new xElement after it using the code below:
xDocument.Descendants("td").LastOrDefault(e => ((string)e.Attribute("ID")) == "3").Add(new XElement("b", "Just a test."));
The problem is that I wish to Add this new xElement after all found instances of the Descendants, not just LastOrDefault or FirstOrDefault.
My xDocument is created dynamically & there is no way before hand to know how many 'td' xElements with 'ID' = '3' that there are going to be.
Any help would be appreciated.
Thanks
ADDED CODE AS REQUESTED
<html> .... etc....
<body>
<table>
<tr>
<td>Image</td>
<td>Description</td>
<td>Date</td>
</tr>
<tr>
<td ID="1">*.jpg</td>
<td ID="2">some image</td>
<td ID="3">01/01/1901</td> <--CHANGING THIS PART OF CODE-->
<--THIS TABLE ROW REPEATS AN UNDETERMINED NUMBER
OF TIMES RELATING TO THE NUMBER OF FILES CONTAINED IN WHATEVER DIRECTORY IS BEING SEARCHED USING A FOREACH LOOP IN ANOTHER PART OF
THE CODE-->
</tr>
</table>
</body>
</html>
So I am trying to add a tag between the <td> with ID = 3.
This <b> tag also contains a string variable i.e.
new xElement("b", DateTaken)
& needs to be created at runtime and not hard coded as it relates to each loaded image at the start of the table row.
So I am trying to add this <b> tag to every occurrence of <td> with ID=3 & not just the first or the last.
Hope this extra info helps.

Get the text of a link within a table cell

I have a table similar to this one:
<table id="space-list" class="aui list-container">
<tr class="space-list-item" data-spacekey="BLANKSPACEEXAMPLE">
<td class="entity-attribute space-name">
<a title="Blank Space Example" href="https://q-leap.atlassian.net/wiki/display/BLANKSPACEEXAMPLE/Blank+Space+Example+Home">
Blank Space Example
</a>
</td>
<td class="entity-attribute space-desc">
<span>
An example of a "Knowledge Base" type space, freely editable, accessible to everyone, may be deleted at any time.
</span>
</td>
</tr>
</table>
My PageObject code looks like this
class Space < PageObject::Elements::TableRow
def name
cell_element(index: 0).link_element(href: /q-leap/).text
end
def description
cell_element(index: 1).text
end
end
PageObject.register_widget :space, Space, :tr
class SpaceDirectoryPage
include PageObject
spaces(:space) do
table_element(:id => 'space-list')
.group_elements(:tag_name => 'tr')[1..-1]
end
end
And now I am iterating over all the rows in the table to get the content of each cell:
while true
on(SpaceDirectoryPage).space_elements.each_with_index do |space|
puts space.name
puts space.description
end
end
Which is working fine for the description, but I have no clue how to access the text of the link within the first column; tried 100s of things, nothing worked.
Thanks in advance!

Resources