grabTextFrom finds anticipated string that assertion using Locator::contains cannot - codeception

I have an interesting case with the following HTML and a Codeception Acceptance test using PhpBrowser, which I've not been able to find a similar issue for on StackOverflow.
I am looking to assert that the content of a P tag (as part of the only table on the page) contains an anticipated phrase.
// representative code
$anticipatedValue = "updated text description";
$xpath = "//table/tbody/tr[position() = 1]/td[position() = 2]/descendant::p";
$val = $I->grabTextFrom($xpath); // this equals the value of $anticipatedValue;
echo "the value is[" .$val."][".$anticipatedValue."]"; // these match perfectly, no trimming needed
$I->see(Locator::contains($xpath,$anticipatedValue)); //this fails
$I->see(Locator::contains($xpath,$val)); //so does this
The fail HTML output does not display anything out of the ordinary. I am hoping someone with more experience of XPath in PhpBrowser can point out what I am missing.
The HTML portion I am looking at is below. This is a legacy application I am adding tests to, so the HTML is at present, as you can see, not optimal.
<table id="calendar" class="unitable" cellspacing=0 cellpadding=0>
<thead>
<tr>
<th>Time</th>
<th></th>
</tr>
</thead>
<tbody>
<tr class="past"><td>10 Dec 00:00</td>
<td class="entry" rowspan=2>
<div class="time">Tue 10 09:00 - Tue 10 17:00</div>
<div class="stage">new stage B</div>
<p class="description">updated text description</p>
</td>
</tr>
<tr class="past">
<td>10 Dec 12:00</td>
</tr>
<tr class="past">
<td>11 Dec 00:00</td>
<td class="entry" rowspan=1>
<div class="time">Wed 11 09:00 - Wed 11 11:30</div>
<div class="stage">new stage C</div>
<p class="description">this is new stage C</p>
</td>
</tr>
<tr class="past">
<td>11 Dec 12:00</td>
<td></td>
</tr>
<tr class="past">
<td>12 Dec 00:00</td>
<td></td>
</tr>
<tr class="past">
<td>12 Dec 12:00</td>
<td class="entry" rowspan=1>
<div class="time">Thu 12 13:30 - Thu 12 17:00</div>
<div class="stage">new stage D</div>
<p class="description">this is new stage D</p>
</td>
</tr>
</tbody>
<tfoot></tfoot>
</table>
and the failure report reads:
Failed asserting that on page ...
{short snippet of upper page HTML - not from the area under scrutiny, followed by}
[Content too long to display. See complete response in '/var/www/public/vhosts/system/tests/_output/' directory]
--> contains "//table/tbody/tr[position() = 1]/td[position() = 2]/descendant::p[contains(., 'updated text description')]".
Many thanks for your consideration of this issue.

Your problem is that you pass result of Locator::contains to $I->see() method,
see expects to get a string as a first parameter and it is looking for that exact text in HTML.
Start with
$I->see('updated text description');
If you want to check if the text is displayed in specific location, pass XPath expression as a second parameter:
$I->see('updated text description', '//table/tbody/tr[position() = 1]/td[position() = 2]/descendant::p');
as documented at https://codeception.com/docs/modules/PhpBrowser#see

Related

WebBrowser - Get/Read data from generic Tables with no ID, no TagName, no Class

As title, I'm trying to read data from some tables in a page.
I often use WebBrowser1.Document.GetElementById for lot of similar things, but in this case I'm unable to access data, since in this page all tables are simply defined by <table class="table">
Here is what I'm trying to access :
<div class="col-md-6">
<div class="panel panel-primary">
<!-- Default panel contents -->
<div class="panel-heading">
<h3 class="panel-title">Ryzen 3000 - Mainstream</h3>
</div>
<!-- Table -->
<table class="table">
<tbody>
<tr>
<th>Ryzen 5 3500</th>
<td>3.6 - 4.1</td>
</tr>
<tr>
<th>Ryzen 5 3500X</th>
<td>3.6 - 4.1</td>
</tr>
<tr>
<th>Ryzen 5 3600</th>
<td>3.6 - 4.2</td>
</tr>
<tr>
<th>Ryzen 5 Pro 3600</th>
<td>3.6 - 4.2</td>
</tr>
<tr>
<th>Ryzen 5 3600X</th>
<td>3.8 - 4.4</td>
</tr>
<tr>
<th>Ryzen 5 3600XT</th>
<td>3.8 - 4.5</td>
</tr>
</tbody>
</table>
</div>
<!--</panel>-->
</div>
I searched a lot on the web, but I was unable to found a valid solution.
Does anyone have hints?
I recommend you to use HtmlAgilityPack and Xpath analytical formula.
Sample code:
Query specific th label text:
Dim doc As HtmlAgilityPack.HtmlDocument
Dim path As String = "https://www..."
Dim web As New HtmlWeb
doc = web.Load(path)
Dim node As HtmlAgilityPack.HtmlNode
'The text within the fourth <th></th>
node = doc.DocumentNode.SelectNodes("//table[#class='table']//th")(3)
Dim st As String = node.InnerText 'Ryzen 5 Pro 3600
Query all tr text:
Dim doc As HtmlAgilityPack.HtmlDocument
Dim path As String = "https://www..."
Dim web As New HtmlWeb
doc = web.Load(path)
Dim nodes As HtmlAgilityPack.HtmlNodeCollection
nodes = doc.DocumentNode.SelectNodes("//table[#class='table']//tr")
For Each node As HtmlNode In nodes
RichTextBox1.AppendText(node.InnerText)
Next
Result:

Get specific value based on column & row name from dynamic Web table in which columns & rows position also dynamic

I have to print a specific value based on column and row names.
Bt the problem is that columns position and rows position changes every time. And table data is dynamic, values are changing continuously. All the values are not constantmy dynamic web table is. and i want specific value of month April in year 2001.
Here is the sample table based on the attached screenshot.
<html>
<table id='table1' border=" 1px solid black">
<tr>
<th>Month/Year</th>
<th>2003</th>
<th>2004</th>
<th>2001</th>
<th>2005</th>
<th>2002</th>
</tr>
<tr>
<td>May</td>
<td>122</td>
<td>84</td>
<td>7777</td>
<td>12</td>
<td>122</td>
</tr>
<tr>
<td>Feb</td>
<td>45</td>
<td>445</td>
<td>565</td>
<td>222</td>
<td>122</td>
</tr>
<tr>
<td>April</td>
<td>3556</td>
<td>212</td>
<td>21</td>
<td>1546</td>
<td>855</td>
</tr>
</table>
<span>-----------------------------------------------</span>
<table id='table2' border=" 1px solid black">
<tr>
<th>Month/Year</th>
<th>2002</th>
<th>2001</th>
<th>2003</th>
<th>2004</th>
<th>2005</th>
</tr>
<tr>
<td>April</td>
<td>120</td>
<td>243</td>
<td>221</td>
<td>21</td>
<td>65</td>
</tr>
<tr>
<td>May</td>
<td>96</td>
<td>146</td>
<td>454</td>
<td>452</td>
<td>4566</td>
</tr>
<tr>
<td>March</td>
<td>788</td>
<td>139</td>
<td>10</td>
<td>1001</td>
<td>013</td>
</tr>
<tr>
<td>Feb</td>
<td>552</td>
<td>1245</td>
<td>545</td>
<td>41</td>
<td>41</td>
</tr>
</table>
</html>
Below is the xpath to get the value of "April/2001" from table 1.
//table[#id='table1']//td[position()=count(//th[normalize-space(.)='Month/Year']/preceding-sibling::th)+1 and normalize-space(.)='April']/ancestor::tr//td[position()=count(//table[#id='table1']//th[normalize-space(.)='2001']/preceding-sibling::th)+1]
And xpath to get the value of "April/2001" from table 2.
//table[#id='table2']//td[position()=count(//th[normalize-space(.)='Month/Year']/preceding-sibling::th)+1 and normalize-space(.)='April']/ancestor::tr//td[position()=count(//table[#id='table2']//th[normalize-space(.)='2001']/preceding-sibling::th)+1]
The only difference between the 2 xpaths' above is table id **//table[#id='tableX**. Please update the table locator as per your application values.
Let me know if this is helpful.

How to create table for my perl output using perl cgi?

Here is my code and output i was unable to create the different row for my each line using perl?
Here is my code:
use strict;
use warnings;
use CGI;
open(my $file1,"as.txt");
my $firstline=<$file1>;
$firstline=~s/.*=//g;
my #words=split /,/,$firstline;
my $finalline=join("\n",#words);
close $file1;
print "Content-type:text/html\n\n"
print<<"EOF";
<html><body>
<table style="width:100%">
<tr>
<th>UserName</th>
<th>Access</th>
</tr>
<tr>
<td>$finalline</td>
<td>
<input type="checkbox" value="check2" mulitple checked>Read
<input type="checkbox" value="check2" mulitple>Write
<input type="checkbox" value="check2" mulitple>Owner
</td>
</tr>
</table></body></html>
EOF
MY OUTPUT FOR PERL (I.E $finalline)
sankar
morien3
i got the following table as my output in table format:
UserName Access
sankar morien3 Read Write Owner
Expected output:
UserName Access
sankar Read Write Owner
morien3 Read Write Owner
Input file:(i.e as.txt)
cskTeam = sankar, mobrien3
[csk:/]
* = r
#cskTeam = rw
You must know about how HTML layout will work.
Even your code won't give your expected result in terminal.
In html \n not make sense, <br> it is for new line in html. But this logic also won't work in your code.
You are joining the array with \n, then printing the data it will execute the comment line by line what you have mentioned.
First you have printing the $finalline variable so it result is
sankar \n morien3
\n will not consider in html. Storing in one cell as per <td>
Then you are creating the another cell which holds the permission detail.
Finally your code should be as follows.
#!/usr/bin/perl
use warnings;
use strict;
use CGI;
use CGI::Carp qw(fatalsToBrowser);
print "Content-Type: text/html \n\n";
open my $file1,"<","as.txt";
my $firstline=<$file1>;
$firstline=~s/.*=//g;
my #words=split /,/,$firstline;
close $file1;
print<<"EOF";
<html><body>
<table style="width:50%; ">
<tr>
<th style="text-align:left">UserName</th>
<th style="text-align:left">Access</th>
</tr>
EOF
foreach (#words)
{
print <<EOF;
<tr>
<td>$_</td>
<td>
<input type="checkbox" value="check2" mulitple checked>Read
<input type="checkbox" value="check2" mulitple>Write
<input type="checkbox" value="check2" mulitple>Owner
</td>
</tr>
EOF
}
print <<EOF;
</table></body></html>
EOF

SQL select statement with AND and OR operators issue

I'm fetching records from the SQL Server 2000 database using Classic ASP. This is what the code I have used.
ASP Code:
<form name="search" method="post" onsubmit="return attention();">
<table width="60%" border="0" cellpadding="2" cellspacing="0" style="margin:0 auto">
<tr>
<td colspan="2"><h1 style="color:#003399;">Search for Certificate of Analysis</h1></td>
</tr>
<tr>
<td valign="bottom">Product number <sup style="color:#EE0000;font-size:1.3em">*</sup></td>
<td valign="bottom">Lot number</td>
</tr>
<tr>
<td width="30%" valign="top">
<input type="text" name="input1" size="20"/>
</td>
<td valign="top">
<input type="text" size="20" name="input2"/>
<input style="background-color:#ffffff;border:0px;cursor:pointer" size="10" type="submit" name="sub" value=">>" />
</td>
</tr>
</table>
<%
if request.Form("sub") <> "" then
Dim fname, lname
fname= request.Form("input1")
lname= request.Form("input2")
session("n") = fname & lname
sql = "Select * from search where cat_no_batch_no LIKE '"&request.Form("input1")&"%' OR cat_no_batch_no='"&session("n")&"'"
rs.open sql, con, 1, 2
if rs.eof then
response.write("Please provide a valid Cat No.")
else
do while not rs.eof
%>
<table border="1" cellpadding="5" cellspacing="0" width="60%" style="margin:0 auto; border-collapse:collapse;border-color:#999999">
<tr>
<td width="50%"><%=rs("cat_no_batch_no")%></td>
<td width="10%">Click to open <a target="_blank" href="http://localhost/search1/<%=rs("pdf_path")%>"><%=rs("cat_no_batch_no")%></a></td>
</tr>
</table>
<%
rs.movenext
loop
end if
rs.close
end if
%>
</form>
Above the LIKE statement works as expected and displays multiple records which contains similar Cat No..
Issue rises when I input a Cat No in first Input box and Lot Number in another. My desired output should have been just a single record to display as I have given Cat No. and Lot Number , but it shows multiple records.
I have provided the images to be more clear.
In this image below I have put 6106021 as the product number so it displays two entries.
In this image I have put 6106021 as the product number and 218111 as the Lot Number, it shows two entries instead of 1. This is what the issue, it should show one entry as Lot number are unique while cat number can be the same.
Read your question to yourself and think about what you are saying:
You state "My desired output should have been just a single record to display as I have given Cat No. and Lot Number"
But in your SQL you write where cat_no_batch_no LIKE '"&request.Form("input1")&"%' OR cat_no_batch_no='"&session("n")&"'
The key words are AND vs. OR
In your mind you are thinking both conditions must be true, but your query says otherwise. If you want both conditions to be true then you must use the AND operator.
Naoki is on to something - you are going to have to modify your SQL depending upon which criteria are specified.
I guess you can write two separate SQL queries, according as the "Lot number" is provided or not.
Your code may goes like below:
if lname = "" then
sql = "Select * from search where cat_no_batch_no LIKE '"&request.Form("input1")&"%'"
else
sql = "Select * from search where cat_no_batch_no LIKE '"&session("n")&"%'"
end if
I hope this could help

Selenium compare stored Text with NOT or != operator

i'm trying to compare the content of two variables in order to return if variable1 != variable2.
I found some different examples, how to compare variables, but not how to use this with an operator.
First of all, i store text, wait 5 minutes and store text again. If the text is different, so the testis passed.
<tr>
<td>storeText</td>
<td>id=newsdiv_1</td>
<td>newsBox1</td>
</tr>
<!--wait 6 min for ajax update-->
<tr>
<td>pause</td>
<td>360000</td>
<td></td>
</tr>
<tr>
<td>storeText</td>
<td>id=newsdiv_1</td>
<td>newsBox2</td>
</tr>
<tr>
<td>verifyExpression</td>
<td>${newsBox1}</td>
<td>regexp=!(${newsBox2})</td>
</tr>
verifyExpressionworks perfect in comparing if 2 variables are equal.
But the last test should work like this: if newsBox1!=newsBox2 than return true
You can do a verifyNotExpression, which is basically a not of the verifyExpression:
<tr>
<td>verifyNotExpression</td>
<td>${newsBox1}</td>
<td>${newsBox2}</td>
</tr>