如何使用Selenium处理html5约束验证弹出窗口?

时间:2019-03-18 14:42:24

标签: html5 selenium selenium-webdriver webdriverwait constraint-validation

enter image description here

图片说明了一切。 单击“登录”按钮后,“请填写此字段”。出现弹出消息。它看起来像一些JavaScript的东西。 我想使用Selenium获取此弹出消息的文本。 可能吗?这是电子邮件输入字段的html:

<input autocorrect="none" autocapitalize="none" spellcheck="false" autofocus="autofocus" class="cell small-21 form-text required" data-drupal-selector="edit-name" aria-describedby="edit-name--description" type="text" id="edit-name" name="name" value="" size="60" maxlength="60" required="required" aria-required="true" placeholder="Email or Username">

P.S。当出现弹出消息时,浏览器开发工具中的“事件”指示将显示在电子邮件字段html附近。 enter image description here

3 个答案:

答案 0 :(得分:2)

您指的弹出窗口Constraint API's element.setCustomValidity()方法的结果。

  

注意:HTML5约束验证不会消除服务器端验证的需要。即使可以预期的无效表单请求的数量要少得多,无效请求仍然可以由不兼容的浏览器(例如,没有HTML5和JavaScript的浏览器)或试图欺骗您的Web应用程序的坏人发送。因此,与HTML4一样,您还需要在服务器端验证输入约束,方法与在客户端进行的验证一致。

解决方案

要检索通过element.setCustomValidity()方法得到的文本,可以使用以下Locator Strategies中的任何一个:

  • 使用 Python Mozilla CssSelector

    • 代码块:

      from selenium import webdriver
      from selenium.webdriver.support.ui import WebDriverWait
      from selenium.webdriver.support import expected_conditions as EC
      from selenium.webdriver.common.by import By
      
      driver = webdriver.Firefox(executable_path=r'C:\Utility\BrowserDrivers\geckodriver.exe')
      driver.get("https://accounts.us1.advisor.ws/user/login")
      email_username = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input.cell.small-21.form-text.required#edit-name[name='name']")))
      print(email_username.get_attribute("validationMessage"))
      
    • 控制台输出:

      Please fill out this field.
      
  • 使用 Java Chrome Xpath

    • 代码块:

      import org.openqa.selenium.By;
      import org.openqa.selenium.WebDriver;
      import org.openqa.selenium.WebElement;
      import org.openqa.selenium.chrome.ChromeDriver;
      import org.openqa.selenium.chrome.ChromeOptions;
      import org.openqa.selenium.support.ui.ExpectedConditions;
      import org.openqa.selenium.support.ui.WebDriverWait;
      
      public class validationmessage {
      
          public static void main(String[] args) {
      
              System.setProperty("webdriver.chrome.driver", "C:\\Utility\\BrowserDrivers\\chromedriver.exe");
              ChromeOptions options = new ChromeOptions();
              options.addArguments("start-maximized");
              options.addArguments("disable-infobars");
              options.addArguments("--disable-extensions"); 
              WebDriver driver =  new ChromeDriver(options);
              driver.get("https://accounts.us1.advisor.ws/user/login");
              WebElement email_username = new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.xpath("//input[@class='cell small-21 form-text required' and @id='edit-name'][@name='name']")));
              System.out.println(email_username.getAttribute("validationMessage"));
          }
      }
      
    • 控制台输出:

      Please fill out this field.
      

答案 1 :(得分:1)

没有看到html,我无法完全自信地告诉您。

但是,这应该非常容易(编辑:著名的遗言)。那是两件事之一:

1)输入字段的标题属性。将鼠标悬停在某物上,或者(如果设计为)将焦点放在具有title属性的元素上,则会在这样的框中显示标题文本。尽管盒子肯定是风格化的。

2)这是一个自定义div / other html,已链接到涉及该输入字段的“ focus”事件的事件。

两者都需要不同的方式来获取文本。由于它们不同,因此我需要了解所涉及的html。请打开浏览器的开发人员工具,然后检查电子邮件字段。然后,将该元素周围的html复制,包括保存上面显示的工具提示文本的所有内容。

一旦粘贴该html,答案就会很简单。

编辑:我绝对很沮丧。我查看了html,搜索了事件列表和javascript文件。没有对该工具提示中显示的文本的引用。

此外,它还呈现为基于“标题”属性的工具提示。它不是div。然而标题并不仅仅存在于元素的DOM中。我不知道开发人员为使该页面实现所有功能而做了什么魔术。我既是Web开发人员,还是自动化工程师,这超出了我的范围。可能只是我以前从未遇到过,或者可能只是错过了一些东西,一旦我看到它也会让我感到愚蠢。

因此,我强烈建议您直接询问该页面的开发人员他们做了什么,以使该标题按原样显示(html中不存在,并且javascript中没有引用)。

编辑#2:这是我提到的最后一种图像识别。它使用AForge,它很容易作为dll插入。如果使用Visual Studio,则可以将其作为nuget包获取。

using AForge.Imaging;
using System.Drawing;
using System.IO;
using OpenQA.Selenium;

public static class AssertImages
{

    //97.5% match expected. 100% is too strict, and practicly impossible. The lower the value you provide, the more possibly it is for a false match.
    //Never go below 75%. False matches above 75% are generally only possible if the baseline image is very generic, such as a basic shape or colored item.
    public const float BASE_EXPECTED_MATCH_PERCENT = 0.975f; 

    /// <summary>
    /// Determines if a provided baseline image exists within a screenshot of the current browser window .
    /// </summary>
    /// <param name="relativePathToBaseline"> Pass the relative url to the baseline image we are searching for.</param>
    /// <param name="matchExpected">Optional parameter that modifies the expected percent match. Use this when a baseline image may be stretched, different colored, or otherwise slightly modified from provided baseline.</param>
    /// <returns></returns>
    public static bool DoesScreenshotContain(string relativePathToBaseline, float matchExpected = BASE_EXPECTED_MATCH_PERCENT)
    {

        //Save screenhot as source image in jpeg format. Then, read jpeg as bitmap.
        Screenshot ss = ((ITakesScreenshot)BaseTest.Driver).GetScreenshot();
        string tempFile = Path.Combine(Path.GetTempPath(), "temp_screenshot.jpg");
        ss.SaveAsFile(tempFile, ScreenshotImageFormat.Jpeg);
        Bitmap sourceImage = new Bitmap(new MemoryStream(File.ReadAllBytes(tempFile)));
        Bitmap template = new Bitmap(Path.Combine(Reporting.BaseDirectory, "Suite", "ImageRecognition", "Baselines", relativePathToBaseline));
        //Find baseline in template image.
        ExhaustiveTemplateMatching tm = new ExhaustiveTemplateMatching(BASE_EXPECTED_MATCH_PERCENT);
        return tm.ProcessImage(sourceImage, template).Length > 0;

    }

}

然后,在工具提示中拍摄文本图片,以用作基准。如下所述,我非常不愿意将其用作最终解决方案。更好的选择是找到一种使用Selenium或直接javascript的方法,或者通过比我更好的答案的人,或者在编写此代码的开发人员的帮助下进行。话虽如此,如果您需要立即可用的功能,这将使您立即感到满意,直到找到更好的解决方案为止。

答案 2 :(得分:1)

我之前也曾遇到过这种类型的页面,当时我与UI开发人员进行了讨论。 UI上显示的错误是本机浏览器支持,并且如果将该字段保留为空白,则每个浏览器默认情况下都会显示此错误消息。

这是HTML5中引入的,如果元素的html结构中有属性required="required",则浏览器默认情况下将显示您得到的错误消息。因此,如果您还检查元素,则required="required"也会出现在元素的html中。

通常,网站不使用此功能,因为它们在页面上使用其自定义的错误消息,但在您使用的情况下会使用该错误消息。因此,无法使用硒检测到此错误消息,因为错误消息不存在于UI或代码中的任何位置。因此,您要么要求开发人员更改实现,要么需要从测试套件中跳过这些验证。