Form submission verification through Ruby script - ruby

I have a file which has a form the following HTML code:
<label for="subject">Subject</label>* : <input name="subject" id="subject" type="text">
<br>
<label for="message">Message</label>* : <textarea type="text" name="message" id="message"></textarea>
<br>
<input name="name" id="name" value="" type="hidden">
<input value="Submit Ticket" onclick="submitTicket()" type="button">
After I submit the form, the respective ticket will be in a table which has the following HTML code:
<table class="list" width="100%">
<tbody><tr class="messagelist">
<th>#</th>
<th>ID</th>
<th>Name</a></th>
<th>Subject</a></th>
<th>Owner</a></th>
<th>Priority</a></th>
</tr>
<tr class="list_row">
<td>1.</td>
<td>14</td>
<td class="name">X</td>
<td class="subject">Test1</td>
<td class="owner">AB</td>
<td class="priority">High</td>
</tr>
<tr class="list_row">
<td>2.</td>
<td>22</td>
<td class="name">Y</td>
<td class="subject">Test2</td>
<td class="owner">CD</td>
<td class="priority">Low</td>
</tr>
<tr class="list_row">
<td>3.</td>
<td>31</td>
<td class="name">Z</td>
<td class="subject">Test3</td>
<td class="owner">EF</td>
<td class="priority">Medium</td>
</tr>
<tr class="list_row">
<td>4.</td>
<td>42</td>
<td class="name">A</td>
<td class="subject">Test4</td>
<td class="owner">GH</td>
<td class="priority">High</td>
</tr>
<tr class="list_row">
<td>5.</td>
<td>34</td>
<td class="name">B</td>
<td class="subject">Test5</td>
<td class="owner">IJ</td>
<td class="priority">Low</td>
</tr>
<tr class="list_row">
<td>6.</td>
<td>43</td>
<td class="name">C</td>
<td class="subject">Test6</td>
<td class="owner">KL</td>
<td class="priority">Medium</td>
</tr>
</tbody></table>
I am writing a RUBY code for the above form and ticket. I want to verify the submitted form and ticket with respect to subject Test1. Based on the subject, I want to click the ID link of Test1.
Could anyone please help how to do this?
Here is what I tried:
require 'watir'
browser.tds(:class, 'list_row').each do |tds_row|
if tds_row.text =~ /Test1/
tds_row.a(:href, 'index.html').click
end
end

You can iterate over the table rows, and element of the iterated row will be a table cell. Then, you can examine the text of that cell. If the value of the 4th cell is the one you're looking for (i.e. "Test1"), then click the link in the second cell, and break out of the iteration. Here's a contrived example:
require 'watir'
b = Watir::Browser.new :chrome
b.goto("http://some_url")
b.button(:value => "Submit Ticket").click
b.trs.each do |tr|
if tr[3].text == "Test1"
tr[1].a.click
break
end
end
b.close
It's still clunky and fragile, so it might be better to target the cells based on their class attributes.
Also--in your watir example--it looks like you are trying to locate table cells based on the parent row's class attribute (i.e. browser.tds(:class, 'list_row') instead of browser.tds(:class, 'list_row').

Given that the HTML is well marked-up, iterating through the rows is more complicated than it has to be. It would be easier to find the specific subject cell and then navigate to its parent row.
# Find the cell with the specific subject text
subject = browser.td(class: 'subject', text: 'Test1')
# Get the row
row = subject.parent
# Click the tracking code link
row.link(class: 'trackingcode').click

Related

Ruby fastest way to select button in large table

I'm trying to interact with a site that has a large table that looks something like this:
<table id="tblID" cellspacing="1" cellpadding="0" border="0" width="100%">
<tbody><tr valign="top" align="left">
<td colspan="6" height="10"></td>
</tr>
<tr><td bgcolor="#666666" height="1" colspan="6"><img src="img.gif" width="1" height="1" border="0"></td></tr>
<tr class="GridHeader" valign="top" align="left">
<td width="60"><b>Select</b></td>
<td width="210" colspan="2"><b>Account Type</b></td>
<td width="160" colspan="2"><b>Number</b></td>
<td width="200"><b>Account known as</b></td>
</tr>
<tr align="left" valign="middle">
<td class="normal"><input type="radio" id="radButton" name="radButton" value="1233399,1515636"></td>
<td class="normal">ACCTYPE</td>
<td class="normal" width="10"> </td>
<td class="normal">ACCNUMBER</td>
<td class="normal" width="10"> </td>
<td class="normal">ACCNAME</td>
</tr>
<tr align="left" valign="top">
<td height="1" colspan="6" bgcolor="#cccccc"><img src=".img.gif" width="1" height="1" border="0"></td>
</tr>
<tr align="left" valign="middle">
<td class="normal"><input type="radio" id="radButton" name="radButton" value="2263763,2777747"></td>
<td class="normal">ACCTYPE</td>
<td class="normal" width="10"> </td>
<td class="normal">ACCNUMBER</td>
<td class="normal" width="10"> </td>
<td class="normal">ACCNAME</td>
</tr>
This goes on for many hundreds of rows.
My code's aim is to search the rows based on ACCNUMBER, and select the associated radio button. My code does this, but takes a LONG time to do it.
my ruby code so far is this:
require 'watir'
require 'nokogiri'
html = browser.html
doc = Nokogiri::HTML(html)
*csv import and loop stuff*
bkacc = CSV[0]
*nokogiri go fast!*
rows = doc.css("table[id='tblID'] tbody tr")
rows.each do |row|
target = row.text[bkacc]
if !target.nil?
cells = row.css("td[class='normal']")
#pushme = cells[0].css('input')[0]['value']
end
end
*watir goes slow*
browser.table(:id,"tblMaintenance").tbody.trs(:valign,"middle").find do |tr|
temp = tr.td(index: 0).radio(:id => "radButton").attribute_value("value")
if temp == #pushme
tr.td(index: 0).radio(:id => "radButton").set
break
end
end
*other commands and loop to next line in csv*
The finding of the :value of the button I want to push is very fast with nokogiri, but once found, using that :value to look for and set the button with watir is very slow.
My question is; how can I speed this up? I thought perhaps by using mechanize I could but the syntax escapes me. I'm still very new to Ruby so am probably missing some basic knowledge.
Assuming that the combination of the id and value attribute is unique for each radio button, you could locate the radio button directly. The entire Watir loop could be replaced by just:
browser.radio(:id => "radButton", :value => #pushme).set
Alternatively, I would try replacing both loops with the following. Finding the row will be a touch slower than the Nokogiri approach, but the code would be a lot simpler.
row = browser.table(id: 'tblID').tr(text: /#{bkacc}/)
row.radio.set

Using input fields instead of td, h3, o values in List.js

On the List.js site, they show how to use tables and even provide an example at http://www.listjs.com/examples/table.
<tr>
<td class="name">Jonny Stromberg</td>
<td class="born">1986</td>
</tr>
However, I want to use input values instead.
<tr>
<input class="name" value="Jonny Stromberg">
<input class="born" value="1986">
</tr>
The outcome is unexpected, with the input values rendering as empty. However, the ultimate goal is to give the input values names and save the columns/rows in a session. Has anyone been in the same boat?
Try wrapping the <input> in a <td></td> tag. You have set the value of the <inputs> tags correctly and so they should populate correctly.
Something like so worked fine for me:
<table>
<!-- IMPORTANT, class="list" have to be at tbody -->
<tbody class="list">
<tr>
<td><input class="name" value="Jonny Stromberg"></td>
<td><input class="born" value="1986"></td>
</tr>
<tr>
<td><input class="name" value="Jonas Arnklint"></td>
<td><input class="born" value="1985"></td>
</tr>
<tr>
<td><input class="name" value="Martina Elm"></td>
<td><input class="born" value="1986"></td>
</tr>
<tr>
<td><input class="name" value="Gustaf Lindqvist"></td>
<td><input class="born" value="1983"></td>
</tr>
</tbody>
</table>
JSFiddle - https://jsfiddle.net/oLbey91h/1/
I was able to achieve the desired result using an input field and filling the value attribute. Here's a Pastebin: http://pastebin.com/dEfjdNCi.
Notice that in "options" the class name points to the attribute "value."
<div id="users">
<table>
<!-- IMPORTANT, class="list" have to be at tbody -->
<tbody class="list">
<tr>
<td style="display:none;"><input class="id" type="hidden"></td>
<td><input class="name"></td>
<td><input class="born"></td>
</tr>
</tbody>
</table>
</div>
<script>
$(document).ready(function () {
var options = {
valueNames: [
{attr: 'value', name: 'id'},
{attr: 'value', name: 'name'},
{attr: 'value', name: 'born'},
]
};
</script>

Getting a table with Mechanize in Ruby

I'd like to get items from this table:
<table style="margin: auto;width: 800px" id="myTable" class="tablesorter">
<thead>
<tr class="TableHeader">
<th >Game</th><th>Icon</th><th>Achievement</th>
<th>Achievers</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr>
<td><img alt="Logo" src="http://cdn.akamai.steamstatic.com/steamcommunity/public/images/apps/440/07385eb55b5ba974aebbe74d3c99626bda7920b8.jpg" width=133 height=50 ></td>
<td> <table>
<tr>
<td class="AchievementBox" style="background-color: #347C17">
<a href="Steam_Achievement_Info.php?AchievementID=169&AppID=440"> <img alt="Icon" src="http://cdn.akamai.steamstatic.com/steamcommunity/public/images/apps/440/924764eea604817d3c14de9640ae6422c7cdfb7a.jpg" height='50' width='50'>
</a> </td>
</tr>
</table>
</td>
<td style="text-align: left" >Race for the Pennant<br>Run 25 kilometers.</td>
<td style="text-align: right">35505</td><td style="text-align: right">1.3</td>
The table has an id myTable so what I'd like to do is this:
go inside <tbody>
for each <tr> in table:
do something; maybe go inside <td> or get a link from <href>
I have:
require 'mechanize'
agent = Mechanize.new
page = agent.get("http://astats.astats.nl/astats/TopListAchievements.php?DisplayType=2")
puts page.body
This prints the page but how do I actually iterate through the table rows?
Using css selector, to print text and href attribute values:
require 'nokogiri'
doc = Nokogiri::HTML(page.body)
doc.css('table#myTable tbody td[3] a').each {|a|
puts a.text, a[:href]
}

Listing job offers (schema.org’s JobPosting)

I have a page with list of jobs jobs offers and every job in list is link to page with job offer.
And I have a problem with Microdata, and my question is, which variant is better?
First variant:
<table itemscope itemtype="http://schema.org/JobPosting">
<tr>
<td itemprop="title" itemtype="http://schema.org/JobPosting" itemscope>job 1</td>
</tr>
<tr>
<td itemprop="title" itemtype="http://schema.org/JobPosting" itemscope>job 2</td>
</tr>
<tr>
<td itemprop="title" itemtype="http://schema.org/JobPosting" itemscope>job 3</td>
</tr>
</table>
Second variant:
<table>
<tr itemscope itemtype="http://schema.org/JobPosting">
<td itemprop="title"><a href..>job 1</a></td>
</tr>
<tr itemscope itemtype="http://schema.org/JobPosting">
<td itemprop="title"><a href..>job 2</a></td>
</tr>
<tr itemscope itemtype="http://schema.org/JobPosting">
<td itemprop="title"><a href..>job 3</a></td>
</tr>
</table>
Your first variant means: There is a JobPosting which has three titles. Each of these titles consists of another JobPosting.
Your second variant means: There are three JobPostings, each one has a title.
So you want to go with your second variant.
Note that you have an error on your current page. Instead of the example contained in your question, on your page you use itemprop="title" on the a element. But then the href value is the title, not the anchor text.
So instead of
<td>
<a itemprop="title" href="…" title="…">…</a>
</td>
<!-- the value of 'href' is the JobPosting title -->
you should use
<td itemprop="title">
<a class="list1" href="…" title="…">…</a>
</td>
<!-- the value of 'a' is the JobPosting title -->
And why not use the url property here?
<td itemprop="title">
<a itemprop="url" href="…" title="…">…</a>
</td>
The second one. The first one is describing a table as JobPosting which isn't a JobPosting.

How to display the similar information in every view?

I would like to display the information about user's registration state. It should be displayed on every view, but i consider, that writting this code for about 20 times is a bad idea. By the way, this is the code, it works, i guarantee that:
View/RegistrationInfo:
<table width="95%" border="0" cols="2">
<tr>
<td width="50%" height="124"><h2><strong>Simple Blog </strong></h2></td>
<td width="50%" height="124">
#if (System.Web.HttpContext.Current.User.Identity.IsAuthenticated)
{
using (Html.BeginForm("LogOff", "Account"))
{
<table width="95%" height="86" border="0">
<tr>
<td width="50%" valign="middle">Hello, #System.Web.HttpContext.Current.User.Identity.Name</td>
<td width="50%" valign="middle" align = "right"><input type="submit" value="Exit" /></td>
</tr>
</table>
}
}
else
{
using (Html.BeginForm("LogIn", "Home"))
{
<table width="95%" height="86" border="0">
<tr>
<td width="45%" valign="bottom">Login:</td>
<td width="45%" valign="bottom">Password:</td>
<td width="10%"></td>
</tr>
<tr>
<td width="45%">
<p>
<input type="text" name="login" />
</p>
</td>
<td width="45%">
<p>
<input type="password" name="password" />
</p>
</td>
<td width="10%" align="left">
<input type="submit" value="Enter" />
</td>
</tr>
<tr>
<td width="45%" valign="top">
#Html.ActionLink("Register", "Register", "Account")
</td>
</tr>
</table>
}
}
</td>
</tr>
</table>
<hr align="left" width="100%" size="2" />
As you can see, this view doesn't require to be strongly typed... and i don't know, should I modify any controllers (because, all information is stored in HTML Context), and how. I tried to call
#Html.RenderAction("RegistrationInfo", "Home");
or
#Html.RenderPartial("RegistrationInfo", "Home");
and every time i receive compile error with message about invalid parametres
While Darin's answer perfectly covers your question, I would point out that registration information seems like it's part of your layout more (master page for the .aspx-inclined) than an actual action.
So what I would do (and indeed, do do) is put it either in the header part of your layout in the top right or under your side menu or something, and let the layout handle all the details of rendering it (with a conditional around it to hide it when you're not logged in, so you don't see it on the login screen).
The following should work:
#Html.Partial("~/Views/Home/RegistrationInfo.cshtml")
Or if you are inside a view of the Home controller simply:
#Html.Partial("RegistrationInfo")
Or if you put this partial in ~/Views/Shared/RegistrationInfo.cshtml you will be able to reference with the shorthand syntax.

Resources