WebDriver -- Unable to find dynamic span attribute - selenium

A website that I am testing at the moment derives value from the DB and it's dynamic. I need to be able to fetch the value from DB and validate that against what is present in UI which will not be static. The text I am trying to verify is below, for this, I need to identify the element and verify text by comparing the data from DB and what is present on the screen. The specific text here in this example is "Resource". The same span is repeated several times with different values in the same screen. Please help as to how can I identify the element as well validating against DB. I am new to selenium WebDriver.
<span class="card-title grey-text">Resource</span>

If span value "Resource" is dynamic every time, try to retrieve it by following :
driver.findElement(By.xpath("//span[#class='card-title grey-text']")).getText();

You could gather all spans in list and validate against DB values:
int iCnt=0;
List<String> listDB = new ArrayList();
public List<String> DBconnection(){
Class.forName("com.mysql.jdbc.Driver").newInstance();
Connection con = DriverManager.getConnection("jdbc:mysql://localhost/t", "", "");
Statement st = con.createStatement();
String sql = ("SELECT * FROM table ORDER BY id;");
ResultSet rs = st.executeQuery(sql);
if(rs.next()) {
listDB.add(rs.getString("second_column_name"));
}
con.close();
return list;
}
//testing part
public void testAginstDb(List<String> listDB){
List<WebElement> listSpan =
driver.findElement(By.cssSelector("span.card-title.grey-text"));
for(String itemDb : listDB){
for (WebElement item : listSpan) {
if(item.getText().equals(rs.value())){
iCnt+=1;
break;
}
}
Assert.equals(list.size(), iCNT);
}
}
Sorry code was written from head, maybe there are some mistakes, essentially I would make that approach.
Hope it helps,

Related

Which is the current method for table.raw in Cucumber

IDEA does not allow me to use table.raw();
I am new in cucumber so while I was learning/practising I tried to get the data from a DataTable by the following code
public void iEnterTheFollowingForLogin(DataTable table) {
List<List<String>> data = table.raw();
System.out.println("The value is : "+ data.get(1).get(0).toString());
System.out.println("The value is : "+ data.get(1).get(1).toString());
}
I realized that IDEA type the raw method in red so I think maybe it is obsolete and now I should use a newer one.
Rather then accessing the raw table you can address individual cells directly using cell(row, column) or use cells() to get a list of lists.
import io.cucumber.datatable.DataTable;
import java.util.List;
class Scratch {
public static void main(String[] args) {
DataTable data = //...create data table here
System.out.println("The value is : " + data.cell(1, 0));
System.out.println("The value is : " + data.cell(1, 1));
List<List<String>> cells = data.cells();
System.out.println("The value is : " + cells.get(1).get(0));
System.out.println("The value is : " + cells.get(1).get(1));
}
}
Just Want to explain MP's answer in detail for others easy understanding-
Yes you wont be able to use raw() method anymore as, its not supported by cucumber api with newer versions of cucumber i.e. io.cucumber. However One can still still use it with older info.cukes dependencies.
So an alternative to raw() is as answered by MP.
For ex- Let's say you have below- Sample gherkin Step:
Then I should see following sections in my app detail page
|Basic Details|Bank Details|Reconciliation|Summarised Options|Currency Code|
>> The Cucumber step definition for above step should be like belwo-
#Then("I should see following sections in my app detail page")
public void verifySectionsOnDetailPageUI(List<List<String>> dTable) {
//Create your table as below (notice- dataTable declared as- List<List<String>> in method argument above)
DataTable data= DataTable.create(dTable);
// to get number of rows from DataTable
int i=data.cells().size();
// To print entire row's column (iterate via for loop using size if u have more than one row defined in data table
System.out.println("All Cells Data: "+data.cells());
//Read cell by cell data as below, row index to be started from 1 if you have column headings provided in ur table
System.out.println(data.cell(0,0));
System.out.println(data.cell(0,1));
System.out.println(data.cell(0,2));
.....
......... so On .. to be used as per your step's objective .....
O/P:
Basic Details
Bank Details
Reconciliation

Apache Ignite Continuous Queries : How to get the field names and field values in the listener updates when there are dynamic fields?

I am working on a POC on whether or not we should go ahead with Apache Ignite both for commerical and enterprise use. There is a use case though that we are trying to find an answer for.
Preconditions
Dynamically creation of tables i.e. there may be new fields that come to be put into the cache. Meaning there is no precompiled POJO(Model) defining the attributes of the table/cache.
Use case
I would like to write a SELECT continuous query where it gives me the results that are modified. So I wrote that query but the problem is that when the listener gets a notification, I am not able to find all the field names that are modified from any method call. I would like to be able to get all the field names and field values in some sort of Map, which I can use and then submit to other systems.
You could track all modified field values using binary object and continuous query:
IgniteCache<Integer, BinaryObject> cache = ignite.cache("person").withKeepBinary();
ContinuousQuery<Integer, BinaryObject> query = new ContinuousQuery<>();
query.setLocalListener(events -> {
for (CacheEntryEvent<? extends Integer, ? extends BinaryObject> event : events) {
BinaryType type = ignite.binary().type("Person");
if (event.getOldValue() != null && event.getValue() != null) {
HashMap<String,Object> oldProps = new HashMap<>();
HashMap<String,Object> newProps = new HashMap<>();
for (String field : type.fieldNames()) {
oldProps.put(field,event.getOldValue().field(field));
newProps.put(field,event.getValue().field(field));
}
com.google.common.collect.MapDifference<Object, Object> diff = com.google.common.collect.Maps.difference(oldProps, newProps);
System.out.println(diff.entriesDiffering());
}
}
});
cache.query(query);
cache.put(1, ignite.binary().builder("Person").setField("name","Alice").build());
cache.put(1, ignite.binary().builder("Person").setField("name","Bob").build());

WebDriver dictionary of elements

I'm creating a list of IWebElements to access each of elements from same type, but the test works slowly when I want to access a certain element. I came with the idea to create a dictionary of elements and access each element by it's name (text that is stored in this element). I found some topics here but was unable to make them work for me. This is the way I'm accessing elements.
public IWebElement OneElement
{
get
{
return this.Driver.FindElement(By.Id("oneElement"));
}
}
public List<IWebElement> ListOfNames
{
get
{
return this.Driver.FindElements(By.Id("name")).ToList();
}
}
You can try the following code to get element by it's text and it is fast compared the list of elements as list needs to be searched till element found. it will take time if searched element is at the last position in the list. Below code will be direct fetch of particular element. Try it and let us know.
public IWebElement GetElementByText(String text)
{
get
{
return this.Driver.FindElement(By.xpath(String.Format("//*[#id='name'][text()='{0}']",text)));
}
}

Selenium Web Driver : How to map html elements to Java Object.

As part of Selenium Web-driver learning I came across a scenario. Please let me know the professional approach to proceed.
I am testing a eCommerce application where while I click on Mobile link all mobile phones are getting displayed.I want to check whether they are sorted based on name and price. So basically I need to get Name & price of all elements in the result page.
So My Question is there any way I can map html elements to java value objects ? Any API already available for doing this mapping for me ? Something similar to gson api for converting java objects to their corresponding Json representation ?
Deepu Nair
//Get all the mobile phones links into a list before sorting
List<WebElement> mobilelinks=driver.findElements(("locator"));
Map maps = new LinkedHashMap();//use linked hash map as it preserves the insertion order
for(int i=0;i<mobilelinks.size();i++){
//store the name and price as key value pair in map
maps.put("mobilelinks.get(i).getAttribute('name')","mobilelinks.get(i).getAttribute('price')" );
}
/*sort the map based on keys(names) store it in a separate list
sort the map based on values(prices) store it in a separate list
*/
/* Using webdriver click the sort by name and compare it with the list which we got after sorting
and also click sort by prices and compare it with the list*/
To catch an assertion and continue with the test after assertion failures override the Assertion class and create your own CustomAssertion or use SoftAssertions
CustomAssertion.java
public class CustomAssertions extends Assertion {
private Map<AssertionError, IAssert> m_errors = Maps.newLinkedHashMap();
#Override
public void executeAssert(IAssert a) {
try {
a.doAssert();
} catch(AssertionError ex) {
onAssertFailure(a, ex);
System.out.println(a.getActual());
System.out.println(ex.getMessage());
m_errors.put(ex, a);
}
}
public void assertAll() {
if (! m_errors.isEmpty()) {
StringBuilder sb = new StringBuilder("The following asserts failed:\n");
boolean first = true;
for (Map.Entry<AssertionError, IAssert> ae : m_errors.entrySet()) {
if (first) {
first = false;
} else {
sb.append(", ");
}
sb.append(ae.getKey().getMessage());
}
throw new AssertionError(sb.toString());
}
}
}
Instead of using Assertions class to verify the tests use CustomAssertions class
Ex:
//create an object of CustomAssertions class
CustomAssertions custom_assert=new CustomAssertions();
cust_assert.assertTrue(2<1);
cust_assert.assertEquals("test", "testing");
//and finally after finishing the test in aftersuite method call
cust_assert.assertAll();
Hope this helps you if you have any doubts kindly get back...

JSTL tag for accessing an arraylist so that it can be filled in a list box

I have seen two questions relating to my topic on stackoverflow, but those answers did not work for me, hence this question. I have the following object
public class CartProduct {
private ArrayList<String> accList = new ArrayList<String>();
public void setAccList(ArrayList<String> str)
{
this.accList = str;
}
public ArrayList<String> getAccList()
{
return accList;
}
I am using the following code to access this list and then its individual items using JSTL so that they can populate a list box in a JSP. But this code is not working and I dont seem to understand why?
<td><select name = "acc_no">
<Option value = "select">SELECT</Option>
<c:forEach items="${item.product.accList}" var="acno">
<option>${acno}</option>
</c:forEach>
</select>
The list box is empty except for the SELECT word.
The JSTL code looks fine. The JSP page is simply not accessing the instance you think it is accessing.
Check how you are sending the Customer class in the jsp page and check if the accList is empty or not?