在使用 C# 的 Selenium 页面对象模型中,鼠标悬停是不可能的
Mouse hover not possible in Selenium Page Object Model with C#
我需要将鼠标悬停在网站的菜单选项上,以便出现上下文菜单。所以我尝试了两种方法:使用 Actions-Class 并在我的 Page-Object-Model-Selenium 项目中使用带有专用脚本的 JavaScriptExecutor 和 Pagefactory。但事实证明,它们都在 POM 中抛出异常,而在非 POM Selenium 项目中则不会。我提供了两个简单的例子,所以你可以自己比较行为。
下面是没有 POM 的版本,它可以工作:
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium.Support.Events;
using OpenQA.Selenium.Remote;
using OpenQA.Selenium;
using OpenQA.Selenium.Interactions;
namespace UnitTestProject1
{
[TestClass]
public class SimpleTest
{
public static EventFiringWebDriver Driver { get; set; }
[TestMethod]
public void TestMethod1()
{
var caps = new DesiredCapabilities();
caps.SetCapability("browserName", "internet explorer");
SimpleTest.Driver = new EventFiringWebDriver(new RemoteWebDriver(new Uri("http://127.0.0.1:4444/wd/hub"), caps, TimeSpan.FromSeconds(120)));
SimpleTest.Driver.Navigate().GoToUrl("https://www.whosebug.com");
var element = SimpleTest.Driver.FindElement(By.Id("nav-questions"));
// using Actions
// does not throw an exception
new Actions(SimpleTest.Driver).MoveToElement(element).Perform();
// using JavaScript
// does not throw an exception
var mouseOverScript = @"if(document.createEvent){var evObj = document.createEvent('MouseEvents');evObj.initEvent('mouseover', true, false); arguments[0].dispatchEvent(evObj); } else if(document.createEventObject) { arguments[0].fireEvent('onmouseover'); }";
((IJavaScriptExecutor)SimpleTest.Driver).ExecuteScript(mouseOverScript, element);
}
[TestCleanup]
public void Cleanup()
{
SimpleTest.Driver.Quit();
}
}
}
这里是带有 POM 的版本,它只抛出异常,即使其他一切都与另一个示例中的相同:
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium.Support.Events;
using OpenQA.Selenium.Remote;
using OpenQA.Selenium;
using OpenQA.Selenium.Interactions;
using OpenQA.Selenium.Support.PageObjects;
namespace UnitTestProject1
{
[TestClass]
public class PomTest
{
public PomTest()
{
var caps = new DesiredCapabilities();
caps.SetCapability("browserName", "chrome");
PomTest.Driver = new EventFiringWebDriver(new RemoteWebDriver(new Uri("http://127.0.0.1:4444/wd/hub"), caps, TimeSpan.FromSeconds(120)));
PomTest.Driver.Navigate().GoToUrl("https://www.whosebug.com");
}
public static EventFiringWebDriver Driver { get; set; }
[TestMethod]
public void TestMethod1()
{
var page = new SoPage();
page.HoverWithActions();
page.HoverWithJS();
}
[TestCleanup]
public void Cleanup()
{
PomTest.Driver.Quit();
}
}
public class SoPage
{
public SoPage()
{
PageFactory.InitElements(PomTest.Driver, this);
}
public void HoverWithActions()
{
// using Actions
// throws System.Reflection.TargetException;
new Actions(PomTest.Driver).MoveToElement(this.Element).Perform();
}
public void HoverWithJS()
{
// using JavaScript
// throws System.ArgumentException
var mouseOverScript = @"if(document.createEvent){var evObj = document.createEvent('MouseEvents');evObj.initEvent('mouseover', true, false); arguments[0].dispatchEvent(evObj); } else if(document.createEventObject) { arguments[0].fireEvent('onmouseover'); }";
((IJavaScriptExecutor)PomTest.Driver).ExecuteScript(mouseOverScript, this.Element);
}
[FindsBy(How = How.Id, Using = "nav-questions")]
public IWebElement Element { get; set; }
}
}
操作的例外情况是:
"System.Reflection.TargetException: Das Objekt stimmt mit dem Zieltyp nicht überein.
bei System.Reflection.RuntimeMethodInfo.CheckConsistency(Object target)
bei System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
bei System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
bei OpenQA.Selenium.Support.PageObjects.WebDriverObjectProxy.InvokeMethod(IMethodCallMessage msg, Object representedValue)
bei OpenQA.Selenium.Support.PageObjects.WebElementProxy.Invoke(IMessage msg)
bei System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
bei OpenQA.Selenium.ILocatable.get_Coordinates()
bei OpenQA.Selenium.Interactions.Internal.MouseAction.get_ActionLocation()
bei OpenQA.Selenium.Interactions.MoveMouseAction.Perform()
bei OpenQA.Selenium.Interactions.CompositeAction.Perform()
bei OpenQA.Selenium.Interactions.Actions.Perform()
bei UnitTestProject1.SoPage.HoverWithActions() in c:\users\lwa\documents\visual studio 2015\Projects\UnitTestProject1\UnitTestProject1\PomTest.cs:Zeile 50.
bei UnitTestProject1.PomTest.TestMethod1() in c:\users\lwa\documents\visual studio 2015\Projects\UnitTestProject1\UnitTestProject1\PomTest.cs:Zeile 28."
对于 JavaScriptExecutor:
System.ArgumentException: Argument is of an illegal typeOpenQA.Selenium.Support.Events.EventFiringWebDriver+EventFiringWebElement
Parametername: arg
bei OpenQA.Selenium.Remote.RemoteWebDriver.ConvertObjectToJavaScriptObject(Object arg)
bei OpenQA.Selenium.Remote.RemoteWebDriver.ConvertArgumentsToJavaScriptObjects(Object[] args)
bei OpenQA.Selenium.Remote.RemoteWebDriver.ExecuteScriptCommand(String script, String commandName, Object[] args)
bei OpenQA.Selenium.Remote.RemoteWebDriver.ExecuteScript(String script, Object[] args)
bei OpenQA.Selenium.Support.Events.EventFiringWebDriver.ExecuteScript(String script, Object[] args)
bei UnitTestProject1.SoPage.HoverWithJS() in c:\users\lwa\documents\visual studio 2015\Projects\UnitTestProject1\UnitTestProject1\PomTest.cs:Zeile 58.
bei UnitTestProject1.PomTest.TestMethod1() in c:\users\lwa\documents\visual studio 2015\Projects\UnitTestProject1\UnitTestProject1\PomTest.cs:Zeile 29."
我在 Visual Studio 2015 中使用 C#,软件包 Selenium.WebDriver 和 Selenium.Support 都在版本 3.3 中,有一个错误阻止我使用 3.4(参见 ).我的 Selenium Server Standalone 是 3.4.0。 Chrome、Firefox 和 Internet Explorer 的行为相同。
有没有人知道如何在 C# 的 POM 项目中实现悬停?
我找到了两个解决方法。您可以放弃 FindsByAttribute 并自己定义 属性 getter
public IWebElement Element => PomTest.Driver.FindElement(By.Id("nav-questions"));
或者您可以使用 IWebElements 的 IList 而不是 IWebElement,然后引用列表的第一个元素,此选项归功于 。
这将是我正在使用的变体,它看起来像这样:
public void HoverWithActions()
{
// using actions
// now it works :)
new Actions(PomTest.Driver).MoveToElement(this.Elements.First()).Perform();
}
public void HoverWithJS()
{
// using Javascript
// now it works :)
var mouseOverScript = @"if(document.createEvent){var evObj = document.createEvent('MouseEvents');evObj.initEvent('mouseover', true, false); arguments[0].dispatchEvent(evObj); } else if(document.createEventObject) { arguments[0].fireEvent('onmouseover'); }";
((IJavaScriptExecutor)PomTest.Driver).ExecuteScript(mouseOverScript, this.Elements.First());
}
[FindsBy(How = How.Id, Using = "nav-questions")]
public IList<IWebElement> Elements { get; set; }
我需要将鼠标悬停在网站的菜单选项上,以便出现上下文菜单。所以我尝试了两种方法:使用 Actions-Class 并在我的 Page-Object-Model-Selenium 项目中使用带有专用脚本的 JavaScriptExecutor 和 Pagefactory。但事实证明,它们都在 POM 中抛出异常,而在非 POM Selenium 项目中则不会。我提供了两个简单的例子,所以你可以自己比较行为。
下面是没有 POM 的版本,它可以工作:
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium.Support.Events;
using OpenQA.Selenium.Remote;
using OpenQA.Selenium;
using OpenQA.Selenium.Interactions;
namespace UnitTestProject1
{
[TestClass]
public class SimpleTest
{
public static EventFiringWebDriver Driver { get; set; }
[TestMethod]
public void TestMethod1()
{
var caps = new DesiredCapabilities();
caps.SetCapability("browserName", "internet explorer");
SimpleTest.Driver = new EventFiringWebDriver(new RemoteWebDriver(new Uri("http://127.0.0.1:4444/wd/hub"), caps, TimeSpan.FromSeconds(120)));
SimpleTest.Driver.Navigate().GoToUrl("https://www.whosebug.com");
var element = SimpleTest.Driver.FindElement(By.Id("nav-questions"));
// using Actions
// does not throw an exception
new Actions(SimpleTest.Driver).MoveToElement(element).Perform();
// using JavaScript
// does not throw an exception
var mouseOverScript = @"if(document.createEvent){var evObj = document.createEvent('MouseEvents');evObj.initEvent('mouseover', true, false); arguments[0].dispatchEvent(evObj); } else if(document.createEventObject) { arguments[0].fireEvent('onmouseover'); }";
((IJavaScriptExecutor)SimpleTest.Driver).ExecuteScript(mouseOverScript, element);
}
[TestCleanup]
public void Cleanup()
{
SimpleTest.Driver.Quit();
}
}
}
这里是带有 POM 的版本,它只抛出异常,即使其他一切都与另一个示例中的相同:
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium.Support.Events;
using OpenQA.Selenium.Remote;
using OpenQA.Selenium;
using OpenQA.Selenium.Interactions;
using OpenQA.Selenium.Support.PageObjects;
namespace UnitTestProject1
{
[TestClass]
public class PomTest
{
public PomTest()
{
var caps = new DesiredCapabilities();
caps.SetCapability("browserName", "chrome");
PomTest.Driver = new EventFiringWebDriver(new RemoteWebDriver(new Uri("http://127.0.0.1:4444/wd/hub"), caps, TimeSpan.FromSeconds(120)));
PomTest.Driver.Navigate().GoToUrl("https://www.whosebug.com");
}
public static EventFiringWebDriver Driver { get; set; }
[TestMethod]
public void TestMethod1()
{
var page = new SoPage();
page.HoverWithActions();
page.HoverWithJS();
}
[TestCleanup]
public void Cleanup()
{
PomTest.Driver.Quit();
}
}
public class SoPage
{
public SoPage()
{
PageFactory.InitElements(PomTest.Driver, this);
}
public void HoverWithActions()
{
// using Actions
// throws System.Reflection.TargetException;
new Actions(PomTest.Driver).MoveToElement(this.Element).Perform();
}
public void HoverWithJS()
{
// using JavaScript
// throws System.ArgumentException
var mouseOverScript = @"if(document.createEvent){var evObj = document.createEvent('MouseEvents');evObj.initEvent('mouseover', true, false); arguments[0].dispatchEvent(evObj); } else if(document.createEventObject) { arguments[0].fireEvent('onmouseover'); }";
((IJavaScriptExecutor)PomTest.Driver).ExecuteScript(mouseOverScript, this.Element);
}
[FindsBy(How = How.Id, Using = "nav-questions")]
public IWebElement Element { get; set; }
}
}
操作的例外情况是:
"System.Reflection.TargetException: Das Objekt stimmt mit dem Zieltyp nicht überein.
bei System.Reflection.RuntimeMethodInfo.CheckConsistency(Object target)
bei System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
bei System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
bei OpenQA.Selenium.Support.PageObjects.WebDriverObjectProxy.InvokeMethod(IMethodCallMessage msg, Object representedValue)
bei OpenQA.Selenium.Support.PageObjects.WebElementProxy.Invoke(IMessage msg)
bei System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
bei OpenQA.Selenium.ILocatable.get_Coordinates()
bei OpenQA.Selenium.Interactions.Internal.MouseAction.get_ActionLocation()
bei OpenQA.Selenium.Interactions.MoveMouseAction.Perform()
bei OpenQA.Selenium.Interactions.CompositeAction.Perform()
bei OpenQA.Selenium.Interactions.Actions.Perform()
bei UnitTestProject1.SoPage.HoverWithActions() in c:\users\lwa\documents\visual studio 2015\Projects\UnitTestProject1\UnitTestProject1\PomTest.cs:Zeile 50.
bei UnitTestProject1.PomTest.TestMethod1() in c:\users\lwa\documents\visual studio 2015\Projects\UnitTestProject1\UnitTestProject1\PomTest.cs:Zeile 28."
对于 JavaScriptExecutor:
System.ArgumentException: Argument is of an illegal typeOpenQA.Selenium.Support.Events.EventFiringWebDriver+EventFiringWebElement
Parametername: arg
bei OpenQA.Selenium.Remote.RemoteWebDriver.ConvertObjectToJavaScriptObject(Object arg)
bei OpenQA.Selenium.Remote.RemoteWebDriver.ConvertArgumentsToJavaScriptObjects(Object[] args)
bei OpenQA.Selenium.Remote.RemoteWebDriver.ExecuteScriptCommand(String script, String commandName, Object[] args)
bei OpenQA.Selenium.Remote.RemoteWebDriver.ExecuteScript(String script, Object[] args)
bei OpenQA.Selenium.Support.Events.EventFiringWebDriver.ExecuteScript(String script, Object[] args)
bei UnitTestProject1.SoPage.HoverWithJS() in c:\users\lwa\documents\visual studio 2015\Projects\UnitTestProject1\UnitTestProject1\PomTest.cs:Zeile 58.
bei UnitTestProject1.PomTest.TestMethod1() in c:\users\lwa\documents\visual studio 2015\Projects\UnitTestProject1\UnitTestProject1\PomTest.cs:Zeile 29."
我在 Visual Studio 2015 中使用 C#,软件包 Selenium.WebDriver 和 Selenium.Support 都在版本 3.3 中,有一个错误阻止我使用 3.4(参见
有没有人知道如何在 C# 的 POM 项目中实现悬停?
我找到了两个解决方法。您可以放弃 FindsByAttribute 并自己定义 属性 getter
public IWebElement Element => PomTest.Driver.FindElement(By.Id("nav-questions"));
或者您可以使用 IWebElements 的 IList 而不是 IWebElement,然后引用列表的第一个元素,此选项归功于
public void HoverWithActions()
{
// using actions
// now it works :)
new Actions(PomTest.Driver).MoveToElement(this.Elements.First()).Perform();
}
public void HoverWithJS()
{
// using Javascript
// now it works :)
var mouseOverScript = @"if(document.createEvent){var evObj = document.createEvent('MouseEvents');evObj.initEvent('mouseover', true, false); arguments[0].dispatchEvent(evObj); } else if(document.createEventObject) { arguments[0].fireEvent('onmouseover'); }";
((IJavaScriptExecutor)PomTest.Driver).ExecuteScript(mouseOverScript, this.Elements.First());
}
[FindsBy(How = How.Id, Using = "nav-questions")]
public IList<IWebElement> Elements { get; set; }