Get n from findelement in findelements iteration - c#

I'm searching an element inside elements list. And if an element found I return the n of iteration.
I'm wondering is there is another faster way to do that? Currently I can do that purpose this way. But it takes time to process.
var iBtnFix = 0;
var elProfiles = driver.FindElements(By.ClassName("xxx")); // list
for (var i = 0; i < elProfiles.Count; i++)
{
try
{
elProfiles[i].FindElement(By.XPath(".//button[contains(#class,'yyy')]"));
iBtnFix = i;
break;
}
catch (Exception ex)
{
}
}

Better to use if-else condition with return statement instead of try-catch block. You can create method isElementVisible() which return boolean based on visibility of element and use its response in your if condition.
For example :
if(isElementVisible("your locator")
{
return index;
}
Method for example :
public boolean isElementVisible(By by){
boolean isElement = false;
try{
isElement = driver.findElement(by).isDisplay();
}catch(NoSuchElementFoundException e){
isElement = false;
}
return isElement;
}
This is java code. You can write according in C#.

Related

How to LINQ-ify the following loop?

I have a method in a C# program. It enumerates all the .cs files in a certain folder and then runs through the list. For each file, I read all the lines using File.ReadAllLines on it. I only want to process a file if it contains a class, whether conventional, static, or abstract, whose name begins with a certain phrase and does not end with the word Tests. Moreover, I wish to find the line index in the line of lines containing the declaration of the class --- i.e., the public static class Foo part.
Given that I take the result of File.ReadAllLines and call ToList() on it to create a List<string>, I wish to use the FindIndex method to find the index of the line matching my criteria (if it exists) using a Predicate.
My question is: What is a good way to write such a predicate?
I realize I could probably use more sophisticated methods, but I am just putting this code into a quick-and-dirty LINQPad script. So, I don't have to get super fancy.
Let me show you what I have so far (assume that the outermost namespace and class are already suitably declared):
void Main()
{
var files = Directory
.EnumerateDirectories(
Path.Combine(
Environment.GetFolderPath(
Environment.SpecialFolder.UserProfile
), #"source\repos\astrohart\MFR"
), "*", SearchOption.TopDirectoryOnly
).SelectMany(
x => Directory.EnumerateFiles(
x, "FileSystemEntry*.cs", SearchOption.AllDirectories
)
)
.Where(x => !"FileSystemEntry.cs".Equals(Path.GetFileName(x)))
.ToList();
if (files == null || !files.Any()) return;
foreach (var file in files)
{
var contents = string.Empty;
try
{
contents = File.ReadAllText(file);
}
catch (Exception ex)
{
Console.WriteLine($"ERROR: {ex.Message}");
contents = string.Empty;
}
if (string.IsNullOrWhiteSpace(contents)) continue;
if (contents.Contains("[TestFixture]")) continue;
if (contents.Contains("[Log(AttributeExclude = true)]")) continue;
file.Dump();
var lines = new List<string>();
lines.TrimExcess();
try
{
lines = File.ReadAllLines(file).ToList();
}
catch (Exception ex)
{
Console.WriteLine($"ERROR: {ex.Message}");
lines = new List<string>();
lines.TrimExcess();
}
if (lines == null || !lines.Any()) continue;
var index = -1;
for (var i = 0; i < lines.Count; i++)
{
var currentLine = lines[i].Trim();
if (currentLine.EndsWith("Tests")) continue;
if (currentLine.StartsWith("public static class FileSystemEntry"))
{
index = i;
break;
}
if (currentLine.StartsWith("public class FileSystemEntry"))
{
index = i;
break;
}
if (currentLine.StartsWith("public abstract class FileSystemEntry"))
{
index = i;
break;
}
}
if (index < 0) continue;
/*...*/
}
}
How do I translate the for loop in:
var index = -1;
for (var i = 0; i < lines.Count; i++)
{
var currentLine = lines[i].Trim();
if (currentLine.EndsWith("Tests")) continue;
if (currentLine.StartsWith("public static class FileSystemEntry"))
{
index = i;
break;
}
if (currentLine.StartsWith("public class FileSystemEntry"))
{
index = i;
break;
}
if (currentLine.StartsWith("public abstract class FileSystemEntry"))
{
index = i;
break;
}
}
if (index < 0) continue;
into a call thus:
var index = lines.FindIndex(currentLine => /*...*/);
I need help with how to derive the proper body of the lambda expression that matches what the for loop does.
Thanks in advance!
EDIT 1
I squinted my eyes at my loop just a little more. I am looking for a predicate to use specifically with the FindIndex method. I thought a little harder and I figured out maybe I can get away with:
var index = lines.FindIndex(currentLine => !currentLine.Trim.EndsWith("Tests") && currentLine.Trim().StartsWith("public static class FileSystemEntry") || currentLine.Trim().StartsWith("public class FileSystemEntry") || currentLine.Trim().StartsWith("public abstract class FileSystemEntry"));
Perhaps I can implement an extension method
public static bool StartsWithAnyOf(this string value, params string[] testStrings)
{
var result = false;
try
{
if (string.IsNullOrWhiteSpace(value.Trim())) return result;
if (testStrings == null || !testStrings.Any()) return result;
foreach(var element in testStrings)
if (value.Trim().StartsWith(element))
{
result = true;
break;
}
}
catch
{
result = false;
}
return result;
}
Then I'd declare another method:
public static bool KeepLine(string currentLine)
{
if (string.IsNullOrWhiteSpace(currentLine.Trim())) return false;
if (currentLine.Trim().EndsWith("Tests")) return false;
return currentLine.StartsWithAnyOf(
"public static class FileSystemEntry",
"public class FileSystemEntry",
"public abstract FileSystemEntry"
);
}
Then use it thus:
var index = lines.FindIndex(KeepLine);
Would that work?
I havent tested this thoroughly but it seems to pass basic sanity if I compare to original code supplied above. Note that this is not best when it comes to measuring performance. The 'foreach' loop with anonymous function has flaw that you cannot break away from the anonymous function. The only way to come out of a foreach is to run all foreach statements. In order to preserve first index where criteria matches against line contents, I am using index in else if() comparison statement. This means the foreach loop will run for all lines despite of having the first occurrence of matching lines found.
lines.ForEach((l) =>
{
if (l.EndsWith("Tests")) ;
else if (index ==0 && (l.StartsWith("public static class FileSystemEntry") ||
l.StartsWith("public class FileSystemEntry") ||
l.StartsWith("public abstract class FileSystemEntry")))
{
index = lines.IndexOf(l);
}
});

Creating reusable method with variable conditional logic

I have several variations of the following code within methods that are being used for Selenium testing (waits for certain events before returning) and I would like to refactor it and make it reusable so I have the logic controlling the delay & try/catch as a generic method but be able to swap in and out conditions depending on situation.
Is there an easy way to achieve this?
Code:
for (int second = 0; second <= 10; second++)
{
try
{
// bit that needs to vary
matchedAddresses = driver.FindElements(By.ClassName("addresslookup"));
if (matchedAddresses.Count > 0)
{
break;
}
}
catch (Exception)
{
}
Thread.Sleep(1000);
}
return matchedAddresses.Count;
You want function that takes argument of something like Func<int> - method that returns number of elements (or enumerable Func<IEnumerable<sometype>>)
public int GetCountOfElementsWithWait(Func<int> test)
{
.....
var count = test();
....
}
Seems a bit too obvious, but would this work?
public int GetCountOfElementsByClassName(string className)
{
for (int second = 0; second <= 10; second++)
{
try
{
// bit that needs to vary
matchedElements = driver.FindElements(By.ClassName(className));
if (matchedElements.Count > 0)
{
break;
}
}
catch (Exception)
{
}
Thread.Sleep(1000);
}
return matchedElements.Count;
}

Combining for and if loops together

New to programming and reading a how to book. Question is about loops. I have the following code:
public bool DoThisJob(string job, int numShift) {
if (!string.IsNullOrEmpty(currentJob))
return false;
for (int i = 0; i < jobsICanDo.Length; i++) {
if (jobsICanDo[i] == job) {
currentJob = job;
this.shiftsToWork = numberOfShifts;
shiftsWorked = 0;
return true;
}
return false;
If the currentJob string is not empty then return false or return true? There is no else statement so how do we know what to do if it is true?.
Next run a for loop and again is the for loop ran because it returned false or true? Last run an if statement which is self explanatory.
There is no else because of the "return" statement. It immediately aborts execution of the function and returns to the calling function. You could write it with an else and it will function the same.
There is no else statement so how do we know what to do if it is true?.
in an if ... else (or classically called if .. then .. else) construct else if optional and in its absence it would fall through to the next statement outside the if block, in this case its the for statement
Your above function can be equivalently though to be similar to
public bool DoThisJob(string job, int numShift) {
if (!string.IsNullOrEmpty(currentJob))
return false;
else {
for (int i = 0; i < jobsICanDo.Length; i++) {
if (jobsICanDo[i] == job) {
currentJob = job;
this.shiftsToWork = numberOfShifts;
shiftsWorked = 0;
return true;
}
return false;
}
If the currentJob string is null then the if statement won't be run, and it will fall through to the for loop.
If the conditions in the for loop trigger it to return true then the method returns true and the last return is never reached.
If the for loop doesn't return true it will fall onto the last line and the method will return false.
A return statement stops the execution of the function at that point and returns control to the calling procedure.
public bool DoThisJob(string job, int numShift) {
if (!string.IsNullOrEmpty(currentJob))
return false; // If it is not empty then function call returns from this statement
// Else, flow control falls through and below code is executed
for (int i = 0; i < jobsICanDo.Length; i++) {
if (jobsICanDo[i] == job) {
currentJob = job;
this.shiftsToWork = numberOfShifts;
shiftsWorked = 0;
return true;
}
return false;
}
I hope, this clarifies the question.
Your function can be simplified as follows without a loop;
public bool DoThisJob(string job, int numShift) {
if (!string.IsNullOrEmpty(currentJob) || !jobsICanDo.Contains<string>(job))
{
//if currentJob NOT null/empty OR
//job is not in the jobsICanDo[] array
return false;
}
else
{
currentJob = job;
this.shiftsToWork = numberOfShifts;
shiftsWorked = 0;
return true;
}
}

How to fail test if UI element is not found?

I use a method that searches an UI element:
public static bool findtopuielm(string uiitemname)
{
bool res = false;
try
{
AutomationElement desktopelem = AutomationElement.RootElement;
if (desktopelem != null)
{
Condition condition = new PropertyCondition(AutomationElement.NameProperty, uiitemname);
AutomationElement appElement = desktopelem.FindFirst(TreeScope.Descendants, condition);
if (appElement != null)
{
res = true;
}
}
return res;
}
catch (Win32Exception)
{
// To do: error handling
return false;
}
}
This method is called by another one that waits an element until it appears on desktop.
public static void waittopuielm(string appname, int retries = 1000, int retrytimeout = 1000)
{
for (int i = 1; i <= retries; i++)
{
if (findtopuielm(appname))
break;
Thread.Sleep(retrytimeout);
}
}
The thing is that when I call the last function for example:
waittopuielm("Test");
It always returns true even if the element is not found, in that case I want the test to fail.
Any suggestion would be welcomed.
It looks like your waittopuielem method returns void - did you mean to post something like this version, which returns a bool?
public static bool waittopuielm(string appname, int retries = 1000, int retrytimeout = 1000)
{
bool foundMatch = false;
for (int i = 1; i <= retries; i++)
{
if (findtopuielm(appname))
{
foundMatch = true;
break;
}
else
{
Console.WriteLine("No match found, sleeping...");
}
Thread.Sleep(retrytimeout);
}
return foundMatch;
}
Other than that, your code seems to work as expected for me.
One suggestion: In your findtopuielm method, change the TreeScope value in the desktop element search from TreeScope.Descendants to TreeScope.Children:
AutomationElement appElement = desktopelem.FindFirst(TreeScope.Children, condition);
TreeScope.Descendants is probably doing more recursive searching than you want - all children of the desktop element will be searched, as well as every child of those elements (i.e. buttons, edit controls, and so forth).
So, the chances of finding the wrong element when searching for a relatively common string are high, unless you combine your NameProperty PropertyCondition with other properties in an AndCondition to narrow your search.

List<T> moving to the next element

I searched SO and found some posts, but could not get them to work.
Question: How would I loop to the next item in my List Collection (custLoginHist[1] etc)?
List<eCommCustomer.oCustomer> custLoginHist = new List<eComm.oCustomer>();
eCommCustomerDAL.GetCustomerPrevLogin(custLoginHist, oCust);
if (custLoginHist.Count > 0)
{
eCommSecurityFactory oSecFactory = new eCommSecurityFactory();
if (oCust.CustHash == oSecFactory.CreateHash(custLoginHist[0].CustSalt, custLoginHist[0].CustHash))
{
//Password has been used before;
return false;
}
else
{
// Valid password;
return true;
}
}
return true;
}
foreach(eCommCustomer.oCustomer cust in custLoginHist)
{
//Do something with cust here.
}
OR:
for(int i = 0; i != custLoginHist.Count; ++i)
{
eCommCustomer.oCustomer cust = custLoginHist[i];
//Do something with cust here.
}
In this case, we want to return false for any single match, and true otherwise, so:
foreach(eCommCustomer.oCustomer cust in custLoginHist)
if(oCust.CustHash == oSecFactory.CreateHash(custLoginHist[0].CustSalt, custLoginHist[0].CustHash)
return false;
return true;//if we reached here, no matches.
This is a bad idea though, because you've made breaking into the system easier. If I try to set my password to something, and you refuse, I now know that one of your users uses that password. You are much better off letting this case happen, though you should perhaps be blocking some of the more likely offenders ("password", "password1", etc) with a quality check.
List<eCommCustomer.oCustomer> custLoginHist = new List<eComm.oCustomer>();
eCommCustomerDAL.GetCustomerPrevLogin(custLoginHist, oCust);
foreach (var custLogin in custLoginHist)
{
eCommSecurityFactory oSecFactory = new eCommSecurityFactory();
if (oCust.CustHash == oSecFactory.CreateHash(custLogin.CustSalt, custLogin.CustHash))
{
//Password has been used before;
return false;
}
}
return true;
Try something like this, maybe you have to customize your return statements but it should give you an insight how it works.
foreach(var item in yourList)
{
//Iterate;
}
If you want break , you can use : break;
If you want finish you can use : continue;
List<T> implements IEnumerable<T>, so you can just use foreach or if you to be able to edit T in the loop, you can use for.
foreach(var item in custLoginHist)
{
}
Or
for (int i = 0; i < custLoginHist.Count; i++)
{
}
Then if you need to exit out of the loop before it is completed (such as if you have a condition that is true, you can just use break; to exit the loop, or you can return from a loop too if you want to return a value.
You can you loop for this. For example foreach or for:
foreach (var custLogin in custLoginHist)
{
eCommSecurityFactory oSecFactory = new eCommSecurityFactory();
if (oCust.CustHash == oSecFactory.CreateHash(custLogin.CustSalt, custLogin.CustHash))
{
//Password has been used before;
return false;
}
else
{
// Valid password;
return true;
}
}
List<eCommCustomer.oCustomer> custLoginHist = new List<eComm.oCustomer>();
eCommCustomerDAL.GetCustomerPrevLogin(custLoginHist, oCust);
return custLoginHist.Select(c=>oSecFactory.CreateHash(c.CustSalt,c.CustHash))
.Any(x=>x==oCust.CustHash)

Categories

Resources