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);
}
}
}