You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular应用中Selenium无法调用sendKeys方法的问题排查

Angular应用中Selenium无法定位搜索输入框并调用sendKeys的问题

问题概况

搭建自动化测试框架时,在Angular应用内无法调用sendKeys()方法向搜索输入框输入内容,尝试多种元素定位方式均失败。

目标输入框HTML结构

<div class="mat-form-field-wrapper ng-tns-c183-3">
 <div class="mat-form-field-flex ng-tns-c183-3">
  <div class="mat-form-field-infix ng-tns-c183-3">

   <input _ngcontent-ibj-c243="" maxlength="800" matinput="" 
   formcontrolname="filterValue" class="mat-input-element mat-form-field- 
   autofill-control ng-tns-c183-3 ng-pristine ng-valid cdk-text-field- 
   autofill-monitored ng-touched" ng-reflect-name="filterValue" ng-reflect- 
   maxlength="800" id="mat-input-0" aria-invalid="false" aria- 
   required="false">

  <span class="mat-form-field-label-wrapper ng-tns-c183-3"><label 
  class="mat-form-field-label ng-tns-c183-3 mat-empty mat-form-field-empty 
  ng-star-inserted" ng-reflect-disabled="true" id="mat-form-field-label-3" 
  ng-reflect-ng-switch="true" for="mat-input-0" aria-owns="mat-input-0"> 
  <mat-label _ngcontent-ibj-c243="" class="ng-tns-c183-3 ng-star- 
  inserted">Search</mat-label><!--bindings={
  "ng-reflect-ng-switch-case": "true"
}--></label><!--bindings={
  "ng-reflect-ng-if": "true"
}--></span></div></div><div class="mat-form-field-underline ng-tns-c183-3 ng-star-inserted"><span class="mat-form-field-ripple ng-tns-c183-3"></span></div><!--bindings={
  "ng-reflect-ng-if": "true"
}--><div class="mat-form-field-subscript-wrapper ng-tns-c183-3" ng-reflect-ng-switch="hint"><!--bindings={
  "ng-reflect-ng-switch-case": "error"
}--><div class="mat-form-field-hint-wrapper ng-tns-c183-3 ng-trigger ng-trigger-transitionMessages ng-star-inserted" style="opacity: 1; transform: translateY(0%);"><!--bindings={
  "ng-reflect-ng-if": ""
}--><div class="mat-form-field-hint-spacer ng-tns-c183-3"></div></div><!--bindings={
  "ng-reflect-ng-switch-case": "hint"
}-->
</div>
</div>

尝试过的定位方式(均失败)

//driver.findElement(By.xpath("//*[@id=\"search-field\"]")).sendKeys("1000000");
//driver.findElement(By.id("mat-input-0")).sendKeys("1000000");
//driver.findElement(By.xpath("//input[@class='mat-input-element mat-form-field-autofill-control ng-tns-c183-3 ng-pristine ng-valid cdk-text-field-autofill-monitored ng-touched']")).sendKeys("1000045949");
//driver.findElement(By.class("mat-input-element")).sendKeys("1000000");

报错信息

WARNING: Unable to find an exact match for CDP version 111, so returning the closest version found: 110
Exception in thread "main" org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"css selector","selector":"#mat\-input\-0"}
  (Session info: chrome=111.0.5563.147)
Build info: version: '4.8.1', revision: '8ebccac989'
System info: os.name: 'Windows 10', os.arch: 'amd64', os.version: '10.0', java.version: '19.0.2'
Driver info: org.openqa.selenium.chrome.ChromeDriver
Command: [ac239ea7458d50777e81aa5e2d1214ba, findElement {using=id, value=mat-input-0}]
Capabilities {acceptInsecureCerts: false, browserName: chrome, browserVersion: 111.0.5563.147, chrome: {chromedriverVersion: 111.0.5563.64 (c710e93d5b63..., userDataDir: C:\Users\ne1723\AppData\Loc...}, goog:chromeOptions: {debuggerAddress: localhost:62610}, networkConnectionEnabled: false, pageLoadStrategy: normal, platformName: WINDOWS, proxy: Proxy(), se:cdp: ws://localhost:62610/devtoo..., se:cdpVersion: 111.0.5563.147, setWindowRect: true, strictFileInteractability: false, timeouts: {implicit: 0, pageLoad: 300000, script: 30000}, unhandledPromptBehavior: dismiss and notify, webauthn:extension:credBlob: true, webauthn:extension:largeBlob: true, webauthn:extension:minPinLength: true, webauthn:extension:prf: true, webauthn:virtualAuthenticators: true}
Session ID: ac239ea7458d50777e81aa5e2d1214ba
    at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:67)
    at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:500)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:484)
    at org.openqa.selenium.remote.codec.w3c.W3CHttpResponseCodec.createException(W3CHttpResponseCodec.java:200)
    at org.openqa.selenium.remote.codec.w3c.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:133)
    at org.openqa.selenium.remote.codec.w3c.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:53)
    at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:184)
    at org.openqa.selenium.remote.service.DriverCommandExecutor.invokeExecute(DriverCommandExecutor.java:167)
    at org.openqa.selenium.remote.service.DriverCommandExecutor.execute(DriverCommandExecutor.java:142)
    at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:543)
    at org.openqa.selenium.remote.ElementLocation$ElementFinder$2.findElement(ElementLocation.java:162)
    at org.openqa.selenium.remote.ElementLocation.findElement(ElementLocation.java:60)
    at org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:352)
    at org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:344)
    at fgi.fgiCreateCode.main(fgiCreateCode.java:35)

完整测试代码

package fgi;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;

public class fgiCreateCode {

    public static void main(String[] args) throws InterruptedException {

        System.setProperty("webdriver.chrome.driver", "xxx");

        ChromeOptions options=new ChromeOptions();
        options.addArguments("--remote-allow-origins=*");
        //Launching the browser
        WebDriver driver = new ChromeDriver(options);
        driver.get("xxx");


        driver.manage().window().maximize();

        Thread.sleep(3000);

        driver.switchTo().frame(0);

        driver.findElement(By.id("username")).sendKeys("xxx");
        driver.findElement(By.id("password")).sendKeys("xxx");
        driver.findElement(By.xpath("//button[@class='btn btn-primary']")).click();
        Thread.sleep(5000);

        //driver.findElement(By.xpath("//*[@id=\"search-field\"]")).sendKeys("xxx");
        //driver.findElement(By.id("mat-input-0")).sendKeys("xxx");
        //driver.findElement(By.xpath("//input[@class='mat-input-element mat-form-field-autofill-control ng-tns-c183-3 ng-pristine ng-valid cdk-text-field-autofill-monitored ng-touched']")).sendKeys("xxx");


        driver.close();
    }
}

解决办法

1. 处理iframe切换问题

登录操作在iframe中完成,登录后页面可能回到主文档,需先切换回默认上下文:

// 登录后切换回主文档
driver.switchTo().defaultContent();

2. 使用显式等待替代Thread.sleep

Thread.sleep()稳定性差,改用WebDriverWait等待元素可交互,确保元素加载完成:

import org.openqa.selenium.support.ui.WebDriverWait;
import org.openqa.selenium.support.ui.ExpectedConditions;
import java.time.Duration;

// 登录后添加
driver.switchTo().defaultContent();

WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
WebElement searchInput = wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//input[@formcontrolname='filterValue']")));
searchInput.sendKeys("1000000");

3. 使用更稳定的定位器

推荐以下几种定位方式,优先级从高到低:

  • 通过Angular formcontrolname定位:该属性为Angular表单控件名称,通常不会随意变更
    By searchLocator = By.xpath("//input[@formcontrolname='filterValue']");
    
  • 通过关联标签文本定位:利用搜索框的标签文本“Search”关联到输入框
    By searchLocator = By.xpath("//mat-label[text()='Search']/ancestor::div[@class='mat-form-field-infix']/input");
    
  • 通过matinput属性定位:Angular Material输入框的特有属性
    By searchLocator = By.cssSelector("input[matinput]");
    

4. 处理Shadow DOM(如果存在)

若输入框位于Shadow DOM内,需使用JavaScriptExecutor定位:

import org.openqa.selenium.JavascriptExecutor;

WebElement searchInput = (WebElement) ((JavascriptExecutor) driver).executeScript(
    "return document.querySelector('input[formcontrolname=\"filterValue\"]');"
);
searchInput.sendKeys("1000000");

5. 消除CDP版本警告

下载与Chrome版本(111.0.5563.147)匹配的ChromeDriver,替换现有驱动,消除版本不匹配警告。


内容的提问来源于stack exchange,提问作者jetswept

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 22:09:54