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

oknwwptz  于 2022-11-24  发布在  其他
关注(0)|答案(3)|浏览(159)

点击“登录”按钮后,会出现“请填写此字段”弹出消息。
我想用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">

当弹出消息出现时,浏览器DevTools检查器中的“事件”指示将显示在电子邮件字段HTML附近:

ekqde3dh

ekqde3dh1#

您所指的 popup 是Constraint API的element.setCustomValidity()方法的结果。

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

溶液

若要撷取element.setCustomValidity()方法产生的文字,您可以使用下列其中一种“定位器策略”:

  • 使用 PythonMozillaCssSelector
  • 代码块:
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.
  • 使用 JavaChromeXpath
  • 代码块:
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.
w8biq8rn

w8biq8rn2#

在没有看到html的情况下,我不能完全自信地告诉你。
不过,这应该是极其容易的(编辑:这是两件事中的一件:
1)输入字段的title属性。将光标悬停在某个对象上,或者(如果设计的话)将焦点放在具有title属性的元素上时,会在这样的框中显示标题文本。尽管该框肯定已经被风格化了。
2)这是一个自定义的div/other html,它连接到涉及该输入字段的“focus”事件的事件。
两者都需要不同的方式来获取文本。因为它们是不同的,我需要知道所涉及的html。请打开浏览器的开发者工具,并检查电子邮件字段。然后,复制此元素周围的html,包括上面显示的任何包含工具提示文本的内容。
一旦你粘贴了html,答案就很简单了。

**编辑:**我完全被难住了。我查看了html,搜索了事件列表和javascript文件。没有参考工具提示中显示的文本。

此外,它呈现为一个基于“title”属性的工具提示。它不是一个div。然而,title并不简单地存在于元素的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来做这件事,要么通过比我有更好答案的人,要么在编写这段代码的开发人员的帮助下。也就是说,如果你现在需要一些工作,这应该会给予你一些即时的满足感,直到找到一个更好的解决方案。

w7t8yxp5

w7t8yxp53#

我以前也遇到过这种类型的页面,当时我和UI开发人员进行了讨论。UI上显示的错误是本机浏览器支持的,如果该字段留空,每个浏览器都将默认显示此错误消息。
这是在HTML5中引入的,如果元素的html结构中有属性required="required",那么浏览器默认会显示错误信息。所以如果你也检查你的元素,required="required"也会出现在你的元素的html中。
一般来说,网站不会使用这个功能,因为他们在页面上使用自定义的错误消息,但在您的情况下,它正在使用。因此,使用selenium不可能检测到这个错误消息,因为错误消息不存在于UI或代码中的任何地方。因此,您要么要求您的开发人员更改实现,要么需要从您的测试套件中跳过这些验证。

相关问题