【问题标题】:How to find a JavaScript alert that is already open with WatiN如何查找已使用 WatiN 打开的 JavaScript 警报
【发布时间】:2014-12-16 15:10:17
【问题描述】:

我结合使用 SpecFlow、MSTests 进行单元测试,并使用 WatiN 驱动浏览器来测试我们的 Web 应用程序。

  • Visual Studio 2010
  • 类库风格项目
  • 规范流
  • 质谱测试
  • 等待

如果用户在未填写所有必填字段的情况下提交我们的表单,则会弹出 JavaScript alert。我正在尝试使用 WatiN 检测此弹出窗口。触发警报的 SpecFlow 步骤与断言弹出窗口存在的 SpecFlow 步骤不同,因此等待 WatiN 对话处理程序不起作用,因为警报已经打开。

示例 SpecFlow 场景:

Scenario: Form Fields are required
    # This step spawns the alert dialog
    When I click the "Save and Continue" button
    # Test fails here because the alert is already open
    Then I should see the validation error alert

When I click the "Save and Continue" button 的步骤定义

[When(@"I click the ""(.*)"" button")]
public void WhenIClickTheButton(string buttonText)
{
    Button button = BitWeb.Browser.Button(Find.ByValue(buttonText).Or(Find.ByText(buttonText)));
    Assert.IsTrue(button.Exists, "No button with text '{0}' was found", buttonText);
    button.Click();
    browser.WaitForComplete();
}

Then I should see the ... alert 的步骤定义:

[Then(@"I should see the validation error alert")]
public void ThenIShouldSeeTheValidationErrorAlert()
{
    var alert = new WatiN.Core.DialogHandlers.AlertDialogHandler();

    alert.WaitUntilExists();

    StringAssert.Contains(alert.Message, "An error has occurred. Check entire", "The validation error alert was not visible.");
}

alert.WaitUntilExists(); 的调用会引发异常:

WatiN.Core.Exceptions.WatiNException:对话框在 30 秒内不可用。

当我断言警报对话框可见时,DialogHandler 找不到警报,因为它已经打开。

如何找到已使用 WatiN 打开的警报对话框?

更新 #1: 我倾向于使用 ScenarioContext.Current 对象的解决方案,我只是不确定如何将它们连接在一起,这样浏览器就不会等待 30 秒每次点击按钮只是为了查看是否弹出警告框。

更新#2:经过一番调查,一步点击按钮会导致整个测试框架暂停,直到alert 对话框被关闭。单击“确定”按钮关闭对话框,这允许测试运行程序前进到下一步,在此我断言对话框是可见的——先有鸡还是先有蛋的场景。致电button.ClickNoWait() 解决了这个问题。

【问题讨论】:

  • 对话框是html对话框(jquery类型)还是实际弹出对话框(win32)?
  • 这是一个alert("message") 对话框。

标签: javascript c# internet-explorer-8 watin specflow


【解决方案1】:

让我为你写一个更完整的例子:

public partial class Form1 : Form
{
    //
    // Your class properites/variables
    //
    AlertDialogHandler dialogHandler;


    [DllImport("User32.dll")]
    public static extern Int32 FindWindow(String lpClassName, String lpWindowName);

    //
    // Some methods/functions declarations
    //

    public void SomeInitMethod()
    {
          dialogHandler = new AlertDialogHandler()
          browse.AddDialogHandler(dialogHandler);
    }

    public void SampleMethod()
    {
       IntPtr hwndTmp = (IntPtr)FindWindow("#32770", "Dialog Title");
       WatiN.Core.Native.Windows.Window popUpDialog = new Window(hwndTmp);
       dialogHandler.HandleDialog(popUpDialog);
       //
       // The line above will find the OK button for you and click on it, 
       // from here you continue with the rest of your code.

    }

}

希望这更清楚一点。

【讨论】:

  • 好的。这更有意义。我做了更多的谷歌搜索并想出了这个。我仍在尝试处理警报框。这主要是因为我正在用 WatiN 和 SpecFlow 的组合撞我的头。
  • 感谢@ProgrammerV5 的帮助。 +1并将其标记为答案。我将添加我自己的答案(未标记为答案),给出我在 SpecFlow 方面使用的实际 C# 代码以供将来参考。
【解决方案2】:

由于它是一个 Win32 对话框,您可以获得弹出窗口的句柄(您知道样式并且您知道窗口的标题,如果您不知道样式可以使用 WinSpy++ 找到,只需打开工具并将靶心指向警报,它将为您提供该窗口的所有详细信息)

// #32770 is the window style, just to make the search more confined.
IntPtr hwndTmp = (IntPtr)FindWindow("#32770", "This should be the title of the alert");
Window alertDialog = new Window(hwndTmp);

从这里开始,您将能够在 WatiN 中将其视为常规 Dialog(您应该使用 HandleDialog 传递 alertDialog 作为参数等。如果不清楚,请告诉我,我会加强响应)。

【讨论】:

  • 什么是FindWindow?该方法在哪里声明?
  • 另外,Window 类存在于哪个命名空间/程序集中?
  • [DllImport("User32.dll")] public static extern Int32 FindWindow(String lpClassName, String lpWindowName);
  • Window 是 WatiN.Core.Native.Windows 的一部分
  • 我没有可以使用FindWindow 方法的类。这是类上的静态方法还是实例方法,如果是,它是哪个类的成员?
【解决方案3】:

我将@ProgrammerV5 的答案标记为真正的答案,因为它引导我找到了这段代码。我只发布这个答案是因为它直接与 SpecFlow 和 WatiN 相关。

我有三个不同的 SpecFlow 步骤,单击一个按钮,生成 alert,断言警报框有我期望的文本,最后一步单击“确定”。

SpecFlow 场景示例

Scenario: Doing something really important
    When I click the "Save and Continue" button
    Then I should see the validation error alert
    When I click OK in the validation error alert
    Then I continue on with the rest of this Scenario...

首先,我创建了一个快速帮助方法来查找alert 对话框:

TestProject/Helpers/StepHelper.cs

public static class StepHelper
{
    [DllImport("User32.dll")]
    public static extern Int32 FindWindow(String lpClassName, String lpWindowName);

    public static WatiN.Core.Native.Windows.Window GetAlertBox()
    {
        IntPtr hwndTmp = (IntPtr)FindWindow("#32770", "Message from webpage");
        return new WatiN.Core.Native.Windows.Window(hwndTmp);
    }
}

这使您可以在 Internet Explorer 8 中抓住alert

When I click the "Save and Continue" button 的步骤定义:

[When(@"I click the ""(.*)"" button")]
public void WhenIClickTheButton(string buttonText)
{
    Button button = browser.Button(Find.ByValue(buttonText).Or(Find.ByText(buttonText)));
    Assert.IsTrue(button.Exists, "No button with text '{0}' was found", buttonText);
    button.ClickNoWait();
}

button.Click()button.ClickNoWait() 的调用会生成警报框。只需调用Click() 方法,WatiN 就会等待该事件完全处理,然后再从方法调用返回。由于警告框打开并阻塞了页面,因此单击事件没有完成,从而导致对Click() 的调用完全停止。我通过调用ClickNoWait() 解决了这个问题,这是一种单击页面上元素的“即发即弃”方式。现在会弹出警告框,但测试运行程序可以前进到下一个 SpecFlow 步骤。

Then I should see the validation error alert 的步骤定义:

[Then(@"I should see the validation error alert")]
public void ThenIShouldSeeTheValidationErrorAlert()
{
    var alert = StepHelper.GetAlertBox();

    Assert.IsTrue(alert.Message.Contains("An error has occurred"),
        "An alert was found, but contained the wrong message ('{0}')", alert.Message);
}

在这里,我使用之前创建的StepHelper.GetAlertBox() 方法来获取代表警报框的WatiN.Core.Native.Windows.Window 对象的句柄。然后是一个简单的Assert.IsTrue 确保警报中显示的消息实际上是我们的“验证失败”消息(我们在此页面上还有其他警报)。

最后,我们需要关闭警告框。

When I click OK in the validation error alert 的步骤定义:

[When(@"I click OK in the validation error alert")]
public void WhenIClickOKInTheValidationErrorAlert()
{
    var alert = StepHelper.GetAlertBox();

    Assert.IsTrue(alert.Message.Contains("An error has occurred"),
        "An alert was found, but contained the wrong message ('{0}')", alert.Message);

    alert.ForceClose();
}

这里我们只是从帮助程序中获取警报框对象,然后调用ForceClose 来关闭警报框,因为单击右上角的“确定”或“X”按钮本质上是相同的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-15
    • 1970-01-01
    • 2013-10-10
    • 2017-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多