URL: http://bcmprod.brill.com/rsuite-cms/
I am trying to automate downloading of manuscripts from the client site above. I am using selenium phantomjs in C#.
I have the user credentials. But the elements that make up the login form (e.g. username, password) are not existing in the page source, but are existing when you inspect those elements in the browser.
These are the xpaths I'm using to locate them from "Inspect element" (IDs are dynamically assigned that's why I didn't use them):
string xpathUsername = ".//input[#name='user']";
string xpathPassword = ".//input[#name='pass']";
string xpathBtnLogin = ".//button[#type='submit'][#aria-label='Log In']";
How can I successfully login when the source returned by the driver has no login elements thus cannot be found, but yet existing when I inspect them in the browser?
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.IO;
using OpenQA.Selenium;
using OpenQA.Selenium.PhantomJS;
using OpenQA.Selenium.Support.UI;
using WebCrawler.Helper;
namespace WebCrawler.Webcodes
{
class RSuite : IWebcode
{
List<string> errors = new List<string>();
string xpathUsername = ".//input[#name='user']";
string xpathPassword = ".//input[#name='pass']";
string xpathBtnLogin = ".//button[#type='submit'][#aria-label='Log In']";
public RSuite()
{ }
public List<Record> GetRecords()
{
Console.WriteLine(string.Format("Crawling: {0}", Config.Url));
List<Record> recordList = new List<Record>();
try
{
PhantomJSDriverService service = PhantomJSDriverService.CreateDefaultService();
service.HideCommandPromptWindow = true;
using (IWebDriver driver = new PhantomJSDriver(service))
{
driver.Navigate().GoToUrl(Config.Url);
Console.WriteLine("\nChecking elements availability ...");
// code exception here: I couldn't get all these elements
IWebElement username = Element("User ID", GetElement(driver, xpathUsername));
IWebElement password = Element("Password", GetElement(driver, xpathPassword));
IWebElement btnlogin = Element("Login Button", GetElement(driver, xpathBtnLogin));
// input credentials
Console.WriteLine("\nAttempting to login ...");
if (username != null && password != null && btnlogin != null)
{
username.Clear();
username.SendKeys(Config.Username);
password.Clear();
password.SendKeys(Config.Password);
// is button clicked & loaded a new page? (If true, login is successful)
if (IsPageLoaded(driver, btnlogin))
{
Console.WriteLine("Logged in successfully.");
// do some action
// download files
}
else
{ ErrorHandler("Login failed."); }
}
else
{ ErrorHandler("Login failed."); }
}
// release
service.Dispose();
}
catch (Exception err)
{ ErrorHandler(err.GetBaseException().ToString()); }
// generate report for caught errors, if any
if (errors.Count() > 0)
Config.ErrorReport(this.GetType().Name.Trim().ToUpper(), string.Join("\n\n", errors));
return recordList;
}
private IWebElement GetElement(IWebDriver driver, string xPath)
{
IWebElement element = null;
try
{
// wait for elements to load
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(60));
Func<IWebDriver, IWebElement> waitForElement = new Func<IWebDriver, IWebElement>((IWebDriver d) =>
{
element = d.FindElement(By.XPath(xPath));
if (element != null)
{ return element; }
return null;
});
return wait.Until(waitForElement);
}
catch (Exception err)
{
ErrorHandler(err.GetBaseException().ToString());
return null;
}
}
private IWebElement Element(string label, IWebElement element)
{
if (element != null)
{ Console.WriteLine(string.Format("{0}: Yes", label)); }
else
{ Console.WriteLine(string.Format("{0}: No", label)); }
return element;
}
private bool IsPageLoaded(IWebDriver driver, IWebElement element)
{
try
{
// page redirected? Or is the element still attached to the DOM?
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(60));
element.Click();
return wait.Until(ExpectedConditions.StalenessOf(element));
}
catch (Exception err)
{
ErrorHandler(err.GetBaseException().ToString());
return false;
}
}
private void ErrorHandler(string error)
{
Console.WriteLine(error);
errors.Add(error);
}
}
}
As per your question the url http://bcmprod.brill.com/rsuite-cms/ is based on Ember.js so you have to induce WebDriverWait inconjunction with ExpectedConditions method ElementToBeClickable() while you look out for the elements.
The Locator Strategies to identify the desired fileds are as follows:
User ID:
string username = "//input[#class='ember-view ember-text-field finput text-field component' and #name='user']";
Password:
string password = "//input[#class='ember-view ember-text-field finput text-field component' and #name='pass']";
Log In:
string loginbtn = "//label[#class='ui-button-text']";
Related
I want to make an auto injection scanner in any given website and I have to use c#.
I tried some things that I found online and none of them worked for me, until i find selenium but i keep getting this error message: "OpenQA.Selenium.ElementNotInteractableException: 'element not interactable", and I have no idea why.
I didn't find anything helpful online and I think the problem may be with selenium.
I tried to find SQL, JS and BASH injections, but the script fails when i try to interact with an input. I am using OWASP juice shop to test my code.
This is my code:
static int _crntTypeOfInjection;
const int ESQL = 0, EJS = 1, EBASH = 2;
static public bool IsImportantInput(string type)
{
bool valid = false;
string[] importantTypes = new string[] { "text", "email", "password", "search", "url" };
foreach (string check in importantTypes)
{
if (type == check)
{
return true;
}
}
return false;
}
public static string getCrntInjection()
{
switch (_crntTypeOfInjection)
{
case ESQL:
return "\' OR 1=1;--";
break;
case EBASH:
return "; echo Test";
break;
case EJS:
return "<img src=\"http:\\\\url.to.file.which\\not.exist\" onerror=alert(\"JS injection success\");>";
break;
}
return "defult";
}
static public bool AttackSuccessful(string normalPage, string InjectedPage, string MainUrl, string afterClickUrl)
{
if (afterClickUrl != MainUrl || InjectedPage.Contains("Internal Server Error") || InjectedPage.Contains("JS injection success") || InjectedPage.Contains("Test"))
{
return true;
}
return false;
}
static public void Injection(string url)
{
string InjectedPage = "", NormalPage = "", AfterClickUrl = "";
var driver = new ChromeDriver("C:\\Users\\nirya\\");
driver.Url = url;
Console.WriteLine(driver.PageSource);
Actions a = new Actions(driver);
foreach (var button in driver.FindElements(By.CssSelector("button")))
{
// INJECTED PAGE
a.MoveByOffset(0, 0).Click().Perform();
foreach (IWebElement input in driver.FindElements(By.TagName("input")))
{
Console.WriteLine(input.Text);
Console.WriteLine(input.TagName);
try
{
if (IsImportantInput(input.GetAttribute("type")))
{
input.Click(); // *** HERE IS THE PROBLEM ***
input.Clear();
input.SendKeys(getCrntInjection());
}
}
catch (NoSuchElementException)
{
continue;
}
}
button.Click();
InjectedPage = driver.PageSource;
AfterClickUrl = driver.Url;
driver.Navigate().Back();
// NORMAL PAGE
a.MoveByOffset(0, 0).Click().Perform();
foreach (IWebElement input in driver.FindElements(By.CssSelector("input")))
{
try
{
if (IsImportantInput(input.GetAttribute("type")))
{
input.Clear();
input.SendKeys("normal");
}
}
catch (NoSuchElementException)
{
continue;
}
}
button.Click();
NormalPage = driver.PageSource;
driver.Navigate().Back();
if (AttackSuccessful(NormalPage, InjectedPage, url, AfterClickUrl))
{
// add to database
}
}
}
static void Main(string[] args)
{
Injection("http://localhost:3000/#/login");
}
Is there a problem with my code? Or is there another library that i can use instead?
I am new to automation, I just learned about Selenium for 3 days and built a simple C# console application with Selenium which trying to automate "sell" request on a trading website.
I noticed when I login the trading website with normal Chrome, the site is working as normal. But when I launch it with my C# console app, it seems like the trading website is not functioning as normal, seems dead.
Here I attached with both developer console picture as reference.
Normal Chrome browser:
enter image description here
Launched with C# console app:
enter image description here
Am I missing any part of my code, and cause the launched Chrome is being "locked".
Please help me
below is my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
using WebDriverManager;
using WebDriverManager.DriverConfigs.Impl;
namespace ii.tfxBot
{
class Program
{
static void Main(string[] args)
{
string ExecuteUrl = "https://tex.tfxi.com/#/exchange/tfx_usdt";
Console.WriteLine("test case started ");
//create the reference for the browser
//new DriverManager().SetUpDriver(new ChromeConfig());
var ccOptions = new ChromeOptions();
ccOptions.LeaveBrowserRunning = true;
//ccOptions.AttachToEdgeChrome = true;
//change the path accordingly
//ccOptions.EdgeExecutablePath = "C:/Program Files (x86)/Microsoft/Edge/Application/msedge.exe";
new DriverManager().SetUpDriver(new ChromeConfig());
var driver = new ChromeDriver(#"C:\WebDriver\bin", ccOptions);
// navigate to URL
driver.Navigate().GoToUrl("https://tex.tfxi.com/#/login");
Thread.Sleep(2000);
// identify the Google search text box
//IWebElement ele = driver.FindElement(By.Name("q"));
////enter the value in the google search text box
//ele.SendKeys("javatpoint tutorials");
//Thread.Sleep(2000);
////identify the google search button
//IWebElement ele1 = driver.FindElement(By.Name("btnK"));
//// click on the Google search button
//ele1.Click();
bool isUrl = false;
while (isUrl == false)
{
if (driver.Url == ExecuteUrl)
{
StartExecution(driver);
break;
}
Console.WriteLine("Execute Url not matched... try again in 1 second");
Thread.Sleep(5000);
}
//close the browser
//driver.Close();
Thread.Sleep(8000000);
Console.WriteLine("test case ended ");
}
private static void StartExecution(ChromeDriver driver)
{
var inputElements = driver.FindElements(By.CssSelector(".ivu-input.ivu-input-default"));
int i = 0;
foreach (var inputElement in inputElements)
{
Console.WriteLine("input count " + i.ToString() + " : " + inputElement.GetAttribute("placeholder").ToString());
string plText = inputElement.GetAttribute("placeholder").ToString();
if (plText == "出售數量")
{
Console.WriteLine("found the input number: " + i.ToString());
}
else
{
//inputElement.SendKeys("28000");
}
i++;
}
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromMilliseconds(300));
IWebElement divLimit;
bool found = false;
while (found == false)
{
//divLimit = driver.FindElement(By.ClassName("bd bd_limited"));
//divLimit = wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementIsVisible(By.CssSelector("bd bd_limited")));
divLimit = wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.CssSelector(".bd.bd_limited"))); ;
if (divLimit != null)
{
Console.WriteLine("item found, proceed to get selling price!");
GetSellingPrice(divLimit);
break;
}
Console.WriteLine("item NOT found!");
Thread.Sleep(300);
}
int tfxBal = GetTfxBalance(driver);
WaitforElement(driver, By.CssSelector(".mask2"), tfxBal);
}
public static int GetTfxBalance(ChromeDriver driver)
{
int TfxBal = 0;
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromMilliseconds(300));
IWebElement divHdLogin;
divHdLogin = wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.CssSelector(".hd.hd_login")));
//(IWebElement)driver.FindElements(By.CssSelector(".hd.hd_login"));
var targetKeys = divHdLogin.FindElements(By.TagName("span"));
Console.WriteLine("targetKeys 0 : " + targetKeys[0].Text);
Console.WriteLine("targetKeys 1 : " + targetKeys[1].Text);
Console.WriteLine("targetKeys 2 : " + targetKeys[2].Text);
decimal o = Convert.ToDecimal(targetKeys[1].Text);
if (targetKeys[1].Text.Contains("."))
{
var a = targetKeys[1].Text.Split('.');
TfxBal = Convert.ToInt32(a[0]);
}
else
{
TfxBal = Convert.ToInt32(targetKeys[1].Text);
}
return TfxBal;
}
public static void GetSellingPrice(IWebElement divLimit)
{
IWebElement divFormContent = divLimit.FindElement(By.CssSelector(".ivu-form-item-content"));
IWebElement ipSellPrice = divFormContent.FindElement(By.CssSelector(".ivu-input.ivu-input-default"));
Console.WriteLine(ipSellPrice.GetAttribute("value"));
}
public static bool Elexists(By by, WebDriver driver)
{
try
{
driver.FindElement(by);
IWebElement divPopup = driver.FindElement(by);
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromMilliseconds(300));
// textLeft countNumber
IWebElement divcountNumber;
divcountNumber = wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.CssSelector(".textLeft.countNumber")));
//Console.WriteLine("count number: " + divcountNumber.Text);
string popupStyle = divPopup.GetAttribute("style");
//Console.WriteLine("div Popup Style : " + popupStyle);
if (popupStyle == "display: none;")
{
//Console.WriteLine("No Pop up..");
return false;
}
else
{
Console.WriteLine("Pop up display has changed!");
return true;
}
}
catch (NoSuchElementException)
{
return false;
}
}
public static void WaitforElement(WebDriver driver, By by, int tfxBalance = 0)
{
// waitforMin = 2 hours
int waitforMin = 60 * 1000 * 2 * 2 * 2;
for (int i = 0; i < waitforMin; i++)
{
System.Threading.Thread.Sleep(250);
if (Elexists(by, driver))
{
Console.WriteLine("Pop up appears! Performing selling now");
var inputElements = driver.FindElements(By.CssSelector(".ivu-input.ivu-input-default"));
IWebElement SellBtn = driver.FindElement(By.CssSelector(".bg-red.ivu-btn.ivu-btn-default.ivu-btn-long"));
foreach (var inputElement in inputElements)
{
string plText = inputElement.GetAttribute("placeholder").ToString();
if (plText == "出售數量")
{
Console.WriteLine("found the input box");
inputElement.SendKeys("28000");
SellBtn.Click();
}
}
break;
}
Console.Write(".");
}
}
public static void SellTfx()
{
//
}
}
}
I am expecting some solution to fix my code
I have a C#-based Selenium test successfully running in a Github Actions container. It worked until recently, where presumably Github upgraded the ChromeDriver version of the ubuntu-latest image to 87.
After this(started failing on Dec. 2nd), I got the following:
Starting ChromeDriver 85.0.4183.87 (<uuid>-refs/branch-heads/4183#{#1689}) on port 35539
Only local connections are allowed.
Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe.
ChromeDriver was started successfully.
X SomeTestThatShouldpass [5s 387ms]
Error Message:
System.InvalidOperationException : session not created: This version of ChromeDriver only supports Chrome version 85 (SessionNotCreated)
Following this, I upgraded the ChromeDriver dependency in my *.csproj:
Before:
<PackageReference Include="Selenium.WebDriver.ChromeDriver" Version="85.0.4183.8700" />
After:
<PackageReference Include="Selenium.WebDriver.ChromeDriver" Version="87.0.4280.8800" />
However, after bumping the version I'm left with the very same error as above. It still starts ChromeDriver 85, and still brings forth an error in relation to version mismatches.
Apparently, bumping the dependency and building the .NET application again did not upgrade the ChromeDriver version.
How do I upgrade the ChromeDriver version from 85 to 87?
class Program
{
static void Main(string[] args)
{
string ChromeDriverPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
string ChromDriverVersion = GetChromDriverVersion(ChromeDriverPath);
string ChromeWebVersion = GetWebChromeVersion();
if (ChromDriverVersion != ChromeWebVersion)
{
var urlToDownload = GetURLToDownload(ChromeWebVersion);
KillAllChromeDriverProcesses();
DownloadNewVersionOfChrome(urlToDownload, ChromeDriverPath);
string extract = ExtructZip(ChromeDriverPath);
}
}
static string GetChromDriverVersion(string ChromeDriverePath)
{
string driverversion = "";
if (File.Exists(ChromeDriverePath + "\\chromedriver.exe"))
{
IWebDriver driver = new ChromeDriver(ChromeDriverePath);
ICapabilities capabilities = ((ChromeDriver)driver).Capabilities;
driverversion = ((capabilities.GetCapability("chrome") as Dictionary<string, object>)["chromedriverVersion"]).ToString().Split(' ').First();
driver.Dispose();
}
else
{
Console.WriteLine("ChromeDriver.exe missing !!");
}
return driverversion;
}
static string GetChromeWebPath()
{
//Path originates from here: https://chromedriver.chromium.org/downloads/version-selection
using (RegistryKey key = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\chrome.exe"))
{
if (key != null)
{
Object o = key.GetValue("");
if (!String.IsNullOrEmpty(o.ToString()))
{
return o.ToString();
}
else
{
throw new ArgumentException("Unable to get version because chrome registry value was null");
}
}
else
{
throw new ArgumentException("Unable to get version because chrome registry path was null");
}
}
}
static string GetWebChromeVersion()
{
string productVersionPath = GetChromeWebPath();
if (String.IsNullOrEmpty(productVersionPath))
{
throw new ArgumentException("Unable to get version because path is empty");
}
if (!File.Exists(productVersionPath))
{
throw new FileNotFoundException("Unable to get version because path specifies a file that does not exists");
}
var versionInfo = FileVersionInfo.GetVersionInfo(productVersionPath);
if (versionInfo != null && !String.IsNullOrEmpty(versionInfo.FileVersion))
{
return versionInfo.FileVersion;
}
else
{
throw new ArgumentException("Unable to get version from path because the version is either null or empty: " + productVersionPath);
}
}
static string GetURLToDownload(string version)
{
if (String.IsNullOrEmpty(version))
{
throw new ArgumentException("Unable to get url because version is empty");
}
//URL's originates from here: https://chromedriver.chromium.org/downloads/version-selection
string html = string.Empty;
string urlToPathLocation = #"https://chromedriver.storage.googleapis.com/LATEST_RELEASE_" + String.Join(".", version.Split('.').Take(3));
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(urlToPathLocation);
request.AutomaticDecompression = DecompressionMethods.GZip;
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
using (Stream stream = response.GetResponseStream())
using (StreamReader reader = new StreamReader(stream))
{
html = reader.ReadToEnd();
}
if (String.IsNullOrEmpty(html))
{
throw new WebException("Unable to get version path from website");
}
return "https://chromedriver.storage.googleapis.com/" + html + "/chromedriver_win32.zip";
}
static void KillAllChromeDriverProcesses()
{
var processes = Process.GetProcessesByName("chromedriver");
foreach (var process in processes)
{
try
{
process.Kill();
}
catch
{
}
}
}
static void DownloadNewVersionOfChrome(string urlToDownload,string ChromDriverPath)
{
if (String.IsNullOrEmpty(urlToDownload))
{
throw new ArgumentException("Unable to get url because urlToDownload is empty");
}
using (var client = new WebClient())
{
if (File.Exists(ChromDriverPath + "\\chromedriver.zip"))
{
File.Delete(ChromDriverPath + "\\chromedriver.zip");
}
client.DownloadFile(urlToDownload, "chromedriver.zip");
if (File.Exists(ChromDriverPath + "\\chromedriver.zip") && File.Exists(ChromDriverPath + "\\chromedriver.exe"))
{
File.Delete(ChromDriverPath + "\\chromedriver.exe");
}
}
}
static string ExtructZip(string ChromeDriverPath)
{
string errorMsg = "";
string zipFileName = "";
try
{
zipFileName= System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + "\\chromedriver.zip";
string orgFileName = "";
using (ZipFile zip = ZipFile.Read(zipFileName))
{
foreach (ZipEntry e in zip)
{
e.Extract(ChromeDriverPath, ExtractExistingFileAction.OverwriteSilently);
orgFileName = e.FileName;
}
}
File.Delete(zipFileName);
errorMsg = "Done";
}
catch (Exception ex)
{
errorMsg = "ExtructZip file " + zipFileName.Split('\\').Last() + " - " + ex.Message;
}
return errorMsg;
}
}
}
https://github.com/rosolko/WebDriverManager.Net
Use WebDriver manager to automatically install the version , you want
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using WebDriverManager;
using WebDriverManager.DriverConfigs.Impl;
namespace Test
{
[TestFixture]
public class Tests
{
private IWebDriver _webDriver;
[SetUp]
public void SetUp()
{
new DriverManager().SetUpDriver(new ChromeConfig(), "2.25");
_webDriver = new ChromeDriver();
}
[TearDown]
public void TearDown()
{
_webDriver.Quit();
}
[Test]
public void Test()
{
_webDriver.Navigate().GoToUrl("https://www.google.com");
Assert.True(_webDriver.Title.Contains("Google"));
}
}
}
public static IWebElement WaitGetElement(IWebDriver driver, By by, int timeoutInSeconds, bool checkIsVisible = false)
{
WebDriverWait webDriverWait = new WebDriverWait(driver, TimeSpan.FromSeconds((double)timeoutInSeconds));
IWebElement result;
try
{
if (checkIsVisible)
{
result = webDriverWait.Until<IWebElement>(ExpectedConditions.ElementIsVisible(by));
}
else
{
result = webDriverWait.Until<IWebElement>(ExpectedConditions.ElementExists(by));
}
}
catch (NoSuchElementException)
{
result = null;
}
catch (WebDriverTimeoutException)
{
result = null;
}
catch (TimeoutException)
{
result = null;
}
return result;
}
This is My Code . It Give Me Erro : The name 'ExpectedConditions' does not exist in the current context .
Can you Help Me .
I Think you are missing this particular Nuget package "SeleniumExtras.WaitHelpers.ExpectedConditions"
https://www.nuget.org/packages/DotNetSeleniumExtras.WaitHelpers/3.11.0
You can download it from nuget library or with the link provided. Later as some comments tell you must put an "using" in the code.
I hope this helps
public static IWebElement FindElement(ExpectedConditions expectedConditions, By by, int timeoutInSeconds)
{
DefaultWait<IWebDriver> wait = new DefaultWait<IWebDriver>(driver);
wait.Timeout = TimeSpan.FromSeconds(timeoutInSeconds);
wait.PollingInterval = TimeSpan.FromMilliseconds(10000);
wait.IgnoreExceptionTypes(typeof(NoSuchElementException));
IWebElement element =
wait.Until<IWebElement>(ExpectedConditions.ElementIsVisible(by));
}
My questions:
How to put this expectedConditions instead of what is currently in my method ?
I try to change:
IWebElement element =
wait.Until<IWebElement>(ExpectedConditions.ElementIsVisible(by));
with this:
IWebElement element =
wait.Until<IWebElement>(expectedConditions(by));
And received this error:
Method name expected.
The Until method requires a predicate as first argument.
A predicate is a function that is called at a regular interval until it returns something different from null or false.
So in your case you need to make it return a predicate and not a IWebElement:
public static Func<IWebDriver, IWebElement> MyCondition(By locator) {
return (driver) => {
try {
var ele = driver.FindElement(locator);
return ele.Displayed ? ele : null;
} catch (StaleElementReferenceException){
return null;
}
};
}
// usage
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
IWebElement element1 = wait.Until(MyCondition(By.Id("...")));
Which is equal to :
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
IWebElement element = wait.Until(ExpectedConditions.ElementIsVisible(By.Id("...")));
element.Click();
You could also use a lambda expression
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
IWebElement element = wait.Until((driver) => {
try {
var ele = driver.FindElement(By.Id("..."));
return ele.Displayed ? ele : null;
} catch (StaleElementReferenceException){
return null;
}
});
element.Click();
Or an extension method:
public static IWebElement WaitElementVisible(this IWebDriver driver, By by, int timeout = 10) {
return new WebDriverWait(driver, TimeSpan.FromSeconds(timeout)).Until((drv) => {
try {
var ele = drv.FindElement(by);
return ele.Displayed ? ele : null;
} catch (StaleElementReferenceException){
return null;
} catch (NotFoundException){
return null;
}
});
}
// usage
IWebElement element = driver.WaitElementVisible(By.Id("..."));
element.Click();
As you see, there is many ways to wait for an element is a specific state.