Adding EventFiringWebDriver to Selenium Framework - c#

I need help with expanding my already build Selenium framework with WebDriver. I want to add eventHandlers that use EventFiringWebDriver on top of my code to add event for each action triggered by WebDriver for logging purposes.
To begin with, I will try to clearly present code flow.
Test starts...
Step 1. CspTestBase
public class CspTestBase : CommonElements
{
[BeforeScenario]
public void Init()
{
Initialize(); <- Code to init driver.
// more code here.
LoginPage.Goto();
LoginPage.LoginAs(TestConfig.Username).WithPassword(TestConfig.Password).Login();
}
[AfterScenario]
public void CleanUp()
{
Close();
}
When it jumps to Init method. This class holds all methods that directly require WebDriver instance.
public static class Driver
{
public static IWebDriver Instance { get; private set; }
public static void Initialize()
{
Instance = new TestDriverFactory().CreateDriver(); <- Next step
Instance.Manage().Timeouts().ImplicitlyWait(new TimeSpan(0, 0, 30));
Instance.Manage().Cookies.DeleteAllCookies();
//Instance.Manage().Window.Maximize();
}
Then when WebDriver Instance is created:
public class TestDriverFactory
{
public IWebDriver CreateDriver()
{
return new TestBase().Create(
new LocalDriverConfig(
TestConfig.Browser));
}
}
And when it finally comes to creating actual driver:
public class TestBase
{
private static IWebDriver _driver;
//string env;
private DesiredCapabilities _capabilities;
public IWebDriver Create(LocalDriverConfig config)
{
switch (config.Browser)
{
case "Chrome":
_driver = new ChromeDriver(#"C:\Utilities");
break;
case "Firefox":
SetFirefoxCapabilities();
//_driver = new FirefoxDriver(_capabilities);
break;
...
private void SetFirefoxCapabilities()
{
...
_capabilities = DesiredCapabilities.Firefox();
//FirefoxOptions options = new FirefoxOptions();
//options.SetLoggingPreference(LogType.Browser, LogLevel.Warning);
_capabilities.SetCapability(FirefoxDriver.ProfileCapabilityName, profile);
//capabilities.SetCapability(FirefoxDriver.ProfileCapabilityName, options);
EventFiringWebDriver firingDriver = new EventFiringWebDriver(new FirefoxDriver(binary, profile, TimeSpan.FromSeconds(60)));
// copy the profile for ommiting duplicate references
firingDriver.ExceptionThrown += firingDriver_TakeScreenshotOnException;
_driver = firingDriver;
}
private void firingDriver_TakeScreenshotOnException(object sender, WebDriverExceptionEventArgs e)
{
TakeScreenshot();
}
As you can see, I'm using EventFiringWebDriver already but I want to have it done properly to save me as much work as possible.
I did some reading and looked up solutions but these were simple or in Java. Any help will be much appreciated.

Related

Initialize webdriver inside BeforeFeature method

I have following problem. I need to register my webdriver instance inside of the specflow BeforeFeature method using context injection, but this method must be static. I have an error that my global container object have to be static. Is there any way to use this context injection in static method?
Here is my code:
[Binding]
public class SpecflowHooks
{
private readonly IObjectContainer container;
public SpecflowHooks(IObjectContainer container)
{
this.container = container;
}
[BeforeFeature]
public static void OneTime()
{
ChromeOptions options = new ChromeOptions();
options.AddArgument("--ignore-ssl-errors=yes");
options.AddArgument("--ignore-certificate-errors");
ChromeDriver driver = new ChromeDriver();
driver.Manage().Window.Maximize();
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(30);
container.RegisterInstanceAs<IWebDriver>(driver);
}
[BeforeScenario]
public void SetUp()
{
}
[AfterScenario]
public void TearDown()
{
}
[AfterFeature]
public static void FeatureTearDown()
{
IWebDriver driver = container.Resolve<IWebDriver>();
driver.Close();
driver.Dispose();
}
}
I presume you want to initialize the web driver only once per feature, and reuse an existing web driver object for each scenario in the feature.
As you noted, the BeforeFeature hook is static. You can still use this to initialize the web driver, but assign it to a static field on your hooks class. Then inside a BeforeScenario, register the static web driver object with the dependency injection container:
[Binding]
public class SpecflowHooks
{
private static IWebDriver driver;
private readonly IObjectContainer container;
public SpecflowHooks(IObjectContainer container)
{
this.container = container;
}
[BeforeFeature]
public static void OneTime()
{
ChromeOptions options = new ChromeOptions();
options.AddArgument("--ignore-ssl-errors=yes");
options.AddArgument("--ignore-certificate-errors");
driver = new ChromeDriver(options); // <-- don't forget to pass 'options' here
driver.Manage().Window.Maximize();
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(30);
}
[BeforeScenario]
public void SetUp()
{
container.RegisterInstanceAs<IWebDriver>(driver);
}
[AfterScenario]
public void TearDown()
{
}
[AfterFeature]
public static void FeatureTearDown()
{
if (driver == null)
return;
driver.Close();
driver.Dispose();
driver = null;
}
}

Invalid session id in specflow Selenium on closing [AfterScenarios]

I am opening a browser session at [BeginScenario] and Quit the session at the [AfterScenario].
At the beginning of second scenario, i am getting 'OpenQA.Selenium.WebDriverException: 'invalid session id'.
How do we start a new session at the beginning of each scenario.?
[Binding]
public class BasePage
{
public static IWebDriver driver;
public static void BrowserSetup()
{
driver = new ChromeDriver();
//driver.Manage().Cookies.DeleteAllCookies();
driver.Manage().Window.Maximize();
}
}
[Binding]
public class Hook : BasePage
{
[BeforeScenario]
public void Initialize(ScenarioContext scenarioContext)
{
BrowserSetup(); // Initialise the driver from BaseClass
scenario = featureName.CreateNode<Scenario>(scenarioContext.ScenarioInfo.Title);
//scenario = featureName.CreateNode<Scenario>(scenarioContext.ScenarioInfo.Title);
}
[AfterScenario]
public void CleanUp(ScenarioContext scenarioContext)
{
if (scenarioContext.TestError != null)
{
TakeScreenshot(driver);
}
//driver.Close();
driver.Quit();
}
}

Element was null when I user page object pattern

I'm new to mobile automation, and I'm facing a problem with page object pattern. When I try to find element with FindElementById everything works, here is my class with pop:
public class SamplePage
{
private AndroidDriver<AndroidElement> _driver;
[FindsByAndroidUIAutomator(ID = "com.miui.calculator:id/btn_1_s")]
private readonly AndroidElement _buttonOne;
[FindsByAndroidUIAutomator(ID = "android:id/button1")]
private readonly AndroidElement _confirmButton;
public SamplePage(AndroidDriver<AndroidElement> driver)
{
_driver = driver;
PageFactory.InitElements(_driver, this);
}
public void ClickOnConfirmButton()
{
//AndroidElement _confirmButton = _driver.FindElementById("android:id/button1");
_confirmButton.Click();
}
public void ClickOnButtonOne()
{
//AndroidElement _buttonOne = _driver.FindElementById("com.miui.calculator:id/btn_1_s");
_buttonOne.Click();
}
}
And here is main class
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Appium.Enums;
using OpenQA.Selenium.Appium.Android;
using OpenQA.Selenium.Remote;
using System;
using AppiumDotNetSamples.Helper;
namespace AppiumDotNetSamples
{
[TestFixture()]
public class AndroidBasicInteractionsTest
{
private AndroidDriver<AndroidElement> driver;
private SamplePage _samplePage;
[SetUp()]
public void BeforeAll()
{
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.SetCapability(MobileCapabilityType.PlatformName, "Android");
capabilities.SetCapability(MobileCapabilityType.PlatformVersion, "7.1.2");
capabilities.SetCapability(MobileCapabilityType.AutomationName, "UIAutomator2");
capabilities.SetCapability(MobileCapabilityType.DeviceName, "3e52f2ee7d34");
capabilities.SetCapability("appPackage", "com.miui.calculator");
capabilities.SetCapability("appActivity", "com.miui.calculator.cal.CalculatorActivity");
driver = new AndroidDriver<AndroidElement>(new Uri("http://localhost:4723/wd/hub"), capabilities, TimeSpan.FromSeconds(180));
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
_samplePage = new SamplePage(driver);
}
[Test()]
public void Click()
{
_samplePage.ClickOnConfirmButton();
_samplePage.ClickOnButtonOne();
}
[TearDown()]
public void AfterAll()
{
driver.Quit();
}
}
}
What am I doing wrong? I test on on Xiaomi Calculator app, but earlier I got the same issues on any other app like Google Calculator.
The ClickConfirmButton method is not returning the driver and hence it is null.
You may want to try something similar this and see if it is working
public AboutPage goToAboutPage()
{
about.Click();
return new AboutPage(driver);
}

Trying to implement a WebDriverActionListener Class

So I've created a WebDriverActionListener class. I register with my driver instance however the OnElementClicking does not fire.
I'm trying to register with my page constructer like so:
public Page(IWebDriver driver): base(driver)
{
this.driver = new WebDriverActionListener(driver);
PageFactory.InitElements(driver, this);
}
Here is my eventlistner class
public class WebDriverActionListener : EventFiringWebDriver
{
#region Object Declarations
private readonly IWebDriver driver;
#endregion
public WebDriverActionListener(IWebDriver parentDriver) : base(parentDriver)
{
driver = parentDriver;
}
protected override void OnElementClicking(WebElementEventArgs e)
{
base.OnElementClicking(e);
if (IsMobile()) //method in another class
{
e.Element.Move(driver); //method in another class
}
}
}
Could someone suggest why this is, I do not to do register my listener class like so driverExtensions = new WebDriverExtensions(this.driver); as it would require quite a lot of code change.
Thanks

testfixturesetup failed in the program

I was writing automation using C# Selenium. I wrote this code and the test keeps on failing. what do you think the problem is? chrome opens however it does not google
namespace ConsoleApplication4Sel
{
class Program
{
IWebDriver driver = new ChromeDriver();
static void Main(string[] args)
{
}
[SetUp]
public void initialization()
{
driver.Navigate().GoToUrl("http://www.google.com");
}
[Test]
public void ExcuteTest()
{
IWebElement element = driver.FindElement(By.Name("q"));
//perform ops
element.SendKeys("Execute authomation");
}
[TearDown]
public void CleanUp()
{
driver.Close();
}
}
}
Please post the error you're getting.
But in any case you forgot to link the path to the driver, meaning:
IWebDriver driver = new ChromeDriver(#"YOUR_PATH");
Put there your path, for example "D:\Download\chromedriver".

Categories