簡體   English   中英

如何修復 'IHasInputDevices 已過時。 使用 Actions 或 ActionsBuilder class 來模擬鼠標和鍵盤輸入的警告 Selenium

[英]How to fix 'IHasInputDevices is obsolete. Use the Actions or ActionsBuilder class to simulate mouse and keyboard input' warning with Selenium

After upgrading the Selenium NuGet packages in our solution to version 3.141.0 (both Selenium.WebDriver and Selenium.Support), the IHasInputDevices interface now has a warning:

'IHasInputDevices' 已過時。 '使用 Actions 或 ActionsBuilder class 來模擬鼠標和鍵盤輸入。

Visual Studio 中棄用警告的屏幕截圖

我創建了一個名為LazyWebDriver ,它實現了IWebDriverIHasInputDevicesIActionExecutor接口。 LazyWebDriver class 延遲IWebDriver的實例化,直到訪問ChromeDriver的成員。 這允許我們通過 IWebDriver object 並延遲瀏覽器 window 的出現,以防在設置階段測試失敗。

LazyWebDriver class 的代碼:

public class LazyWebDriver : IWebDriver/*, IHasInputDevices*/, IActionExecutor
{
    private System.Func<IWebDriver> createDriver;
    private IWebDriver driver;

    private IWebDriver Driver
    {
        get
        {
            if (driver == null)
                driver = createDriver();

            return driver;
        }
    }

    public string Url
    {
        get => Driver.Url;
        set => Driver.Url = value;
    }

    public string Title => Driver.Title;

    public string PageSource => Driver.PageSource;

    public string CurrentWindowHandle => Driver.CurrentWindowHandle;

    public ReadOnlyCollection<string> WindowHandles => Driver.WindowHandles;

    public IKeyboard Keyboard => ((IHasInputDevices)Driver).Keyboard;

    public IMouse Mouse => ((IHasInputDevices)Driver).Mouse;

    public bool IsActionExecutor => ((IActionExecutor)Driver).IsActionExecutor;

    public LazyWebDriver(System.Func<IWebDriver> createDriver)
    {
        this.createDriver = createDriver;
    }

    public void Close()
    {
        Driver.Close();
    }

    public void Dispose()
    {
        Driver.Dispose();
    }

    public IWebElement FindElement(By by)
    {
        return Driver.FindElement(by);
    }

    public ReadOnlyCollection<IWebElement> FindElements(By by)
    {
        return Driver.FindElements(by);
    }

    public IOptions Manage()
    {
        return Driver.Manage();
    }

    public INavigation Navigate()
    {
        return Driver.Navigate();
    }

    public void Quit()
    {
        Driver.Quit();
    }

    public ITargetLocator SwitchTo()
    {
        return Driver.SwitchTo();
    }

    public void PerformActions(IList<ActionSequence> actionSequenceList)
    {
        ((IActionExecutor)Driver).PerformActions(actionSequenceList);
    }

    public void ResetInputState()
    {
        ((IActionExecutor)Driver).ResetInputState();
    }
}

警告指示使用 Actions 或 ActionBuilder class,因此我從 LazyWebDriver class 中刪除了 IHasInputDevices 接口,並嘗試使用 Actions class:

[TestClass]
public class DeprecatedInterfaceTest
{
    [TestMethod]
    public void Test()
    {
        using (var driver = new LazyWebDriver(() => new ChromeDriver()))
        {
            driver.Navigate().GoToUrl("https://www.stackoverflow.com");

            var link = driver.FindElement(By.CssSelector("a[href='/teams/customers']"));
            var actions = new Actions(driver);

            actions = actions.MoveToElement(link);
            actions = actions.Click(link);
            actions.Perform();
        }
    }
}

測試失敗並顯示以下錯誤消息:

測試方法 DeprecatedInterfaceTest.Test 拋出異常:
System.ArgumentException:IWebDriver object 必須實現或包裝實現 IHasInputDevices 的驅動程序。
參數名稱:驅動

測試在這一行失敗:

var actions = new Actions(driver);

我在網上做了一些搜索,但沒有找到消除 IHasInputDevices 接口並使用過時警告中指示的 Actions class 的方法。 ActionBuilder class 似乎也用於排隊一堆 Actions 對象。

如何消除 IHasInputDevices 接口並仍然使用 Actions class?

至少在 3.14 中你不能消除 IHasInputDevices 接口

請參閱此selenium-3.141.59/dotnet/src/webdriver/Interactions/Actions.cs#L68它檢查 IHasInputDevices。 甚至 3.14 中的 RemoteWebdriver 也實現了IHasInputDevices ,因此您的 LazyWebDriver 必須實現它。

IHasInputDevices inputDevicesDriver = GetDriverAs<IHasInputDevices>(driver);

這將檢查並拋出異常

public Actions(IWebDriver driver)
        {
            //this.driver = driver;
            IHasInputDevices inputDevicesDriver = GetDriverAs<IHasInputDevices>(driver);
            if (inputDevicesDriver == null)
            {
                throw new ArgumentException("The IWebDriver object must implement or wrap a driver that implements IHasInputDevices.", "driver");
            }

            IActionExecutor actionExecutor = GetDriverAs<IActionExecutor>(driver);
            if (actionExecutor == null)
            {
                throw new ArgumentException("The IWebDriver object must implement or wrap a driver that implements IActionExecutor.", "driver");
            }

            this.keyboard = inputDevicesDriver.Keyboard;
            this.mouse = inputDevicesDriver.Mouse;
            this.actionExecutor = actionExecutor;
        }

如 Selenium 4. IHasInputDevices 被刪除。 變更日志

 Removed IHasInputDevices and IHasTouchScreen and implementations. The Mouse,
   Keyboard, and TouchScreen implementations in the .NET bindings were never
   intended to be used by user code. Instead, users are expected to use the
   Actions and TouchActions classes or the ActionBuilder class to create
   complex interactions with pages being automated. This change reinforces that
   behavior, making it explicit.

如果您在 Selenium 4 中實現 LazyWebdriver,那么您將不會遇到此問題,因為刪除了 IHasInputDevices 並且 Actions class 僅檢查 IActionExecutor。 請參閱Actions.cs selenium-4.0.0-alpha-6

public Actions(IWebDriver driver)
{
    IActionExecutor actionExecutor = GetDriverAs<IActionExecutor>(driver);
    if (actionExecutor == null)
    {
        throw new ArgumentException("The IWebDriver object must implement or wrap a driver that implements IActionExecutor.", "driver");
    }

    this.actionExecutor = actionExecutor;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM