I develop my Selenium automation test (C#, Selenium).
I have a web application which contains Item Code and Next Available Dates corresponding to the items codes on the web page:
I need to add Item Codes (A7030 and A4604 ) values and there dates (see the screen shot) accordingly to the list, so that I can in the next following steps to assert that dates are calculated correct for the corresponding items.
So, I declared web elements lists:
private IList<IWebElement> ItemNextAvailableDates => Driver.FindElements(By.XPath("//*[contains(@id, 'ctl00_ctl00_c_c_rgItems_ctl00')]/td[4]"));
private IList<IWebElement> ItemProcCodes => Driver.FindElements(By.XPath("//*[contains(@id, 'ctl00_ctl00_c_c_rgItems_ctl00')]/td[1]"));
I created the class:
public class ProcCodesDates
{
public string ProcCodeDate { get; set; }
public string ProcCode { get; set; }
}
The class allows to have Items codes AND there dates in one object.
So, now I can add the objects of this class to the list.
My list is supposed to have only 2 objects btw.
And then I created the method GetItemProcCodeAndNextAvilableDates() which adds objects of the class created (see above) to the list and returns the list of the objects of the class ProcCodesDates. The method is:
public SalesOrderTemplateBase GetItemProcCodeAndNextAvilableDates(out List<ProcCodesDates> listik)
{
List<ProcCodesDates> listOfProcCodesDates = new List<ProcCodesDates>();
foreach (var x in ItemNextAvailableDates)
{
foreach (var y in ItemProcCodes)
{
listOfProcCodesDates.Add(item: new ProcCodesDates { ProcCodeDate = x.GetValue(), ProcCode = y.GetValue() });
}
}
listik = listOfProcCodesDates;
return this;
}
Of course I call the method created in my test.
However, because my loop is not right instead of 2 (two) records in the list at the end I have 4 records:
I expect to have the list as following:
I tried to find out correct decision, but I ran out of ideas.
So, I have 2 questions:
How to get my list returned with correct values, in other words what would be thew algorithm to add items to the list in the loop, so that they added each code with the corresponding date?
How to use method ".Sort()" applied to the list returned, so that it will sort my list by Items Codes? In other words, how to overload the List() that it will sort the list by items codes - descending, or ascending.
My list is supposed to have only 2 objects btw.
Well if you will only have 2 objects at any given time, then you could simply assume so and access those via their index:
public SalesOrderTemplateBase GetItemProcCodeAndNextAvilableDates(out List<ProcCodesDates> listik)
{
listik = new List<ProcCodesDates>
{
new ProcCodesDates { ItemNextAvailableDates[0].GetValue(), ItemProcCodes[0].GetValue() },
new ProcCodesDates { ItemNextAvailableDates[1].GetValue(), ItemProcCodes[1].GetValue() }
};
return this;
}
But...
ItemNextAvailableDates
and ItemProcCodes
have at least two items. This can be a potential source of IndexOutOfRangeException
, so you may want to have try/catch
block around it.So what you could try instead is:
const string expectedItemsCount = 2;
public SalesOrderTemplateBase GetItemProcCodeAndNextAvilableDates(out List<ProcCodesDates> listik)
{
listik = new List<ProcCodesDates>();
for (int i = 0; i < expectedItemsCount ; i++)
{
listik.Add(new ProcCodesDates
{
NextAvailableDate = ItemNextAvailableDates[i].GetValue(),
ProcCode = ItemProcCodes[i].GetValue()
});
}
return this;
}
Looks cleaner! But you still have the same issue of IndexOutOfRangeException
. Thus, we can take it a step further and use Math.Min
. This will take the lowest value of the given 2 arrays, and even in the worst case scenario won't throw an exception.
public SalesOrderTemplateBase GetItemProcCodeAndNextAvilableDates(out List<ProcCodesDates> listik)
{
listik = new List<ProcCodesDates>();
// Check if both lists have at least 2 items to avoid out of range exceptions
int itemsCount = Math.Min(ItemNextAvailableDates.Count, ItemProcCodes.Count);
for (int i = 0; i < itemsCount; i++)
{
listik.Add(new ProcCodesDates
{
NextAvailableDate = ItemNextAvailableDates[i].GetValue(),
ProcCode = ItemProcCodes[i].GetValue()
});
}
return this;
}
For the ordering, if you have access to LINQ, use .OrderBy()
. For example:
listik.OrderBy(x => x.ProcCodeDate);
listik.OrderByDescending(x => x.ProcCodeDate);
A good example is here
Update:
If you need to use .Sort()
method, then here is a good example