Làm thế nào để buộc Selenium WebDriver nhấp vào phần tử hiện không hiển thị?


99

Tôi đang sử dụng Selenium 2 Java API với FirefoxDriver. Khi tôi điền vào biểu mẫu, các hộp kiểm sẽ được thêm vào trang tùy thuộc vào đầu vào của biểu mẫu.

Tôi muốn mô phỏng một cú nhấp chuột vào các hộp kiểm đó bằng Selenium. Phần tử có thể nhìn thấy và sử dụng được trong trình duyệt thông thường nhưng selen khẳng định rằng phần tử không hiển thị.

"Element is not currently visible and so may not be interacted with"

Tôi có thể buộc selen bỏ qua trạng thái không nhìn thấy của các nguyên tố không? Làm cách nào để buộc Selenium tương tác với phần tử không hiển thị?


Bạn đang dùng trình duyệt nào? Bạn không thể tương tác với các phần tử bị tắt hoặc không hiển thị vì người dùng cuối sẽ không thể tương tác với chúng. Bạn sẽ cần cung cấp mã thử nghiệm và nguồn Trang của mình nếu bạn muốn tôi thử và chẩn đoán sự cố.
Ardesco

Câu trả lời:


102

Selenium xác định một phần tử có hiển thị hay không theo các tiêu chí sau (sử dụng trình kiểm tra DOM để xác định những gì css áp dụng cho phần tử của bạn, đảm bảo bạn xem xét kiểu được tính):

  • khả năng hiển thị! = ẩn
  • display! = none (cũng được kiểm tra với mọi phần tử mẹ)
  • opacity! = 0 (điều này không được kiểm tra khi nhấp vào một phần tử)
  • chiều cao và chiều rộng đều> 0
  • đối với đầu vào, loại thuộc tính! = hidden

Yếu tố của bạn phù hợp với một trong những tiêu chí đó. Nếu bạn không có khả năng thay đổi kiểu của phần tử, đây là cách bạn có thể thực hiện một cách cưỡng bức với javascript (giả sử là WebDriver kể từ khi bạn nói Selenium2 API):

((JavascriptExecutor)driver).executeScript("arguments[0].checked = true;", inputElement);

Nhưng điều đó sẽ không kích hoạt một sự kiện javascript, nếu bạn phụ thuộc vào sự kiện thay đổi cho đầu vào đó, bạn cũng sẽ phải kích hoạt nó (nhiều cách để làm điều đó, dễ nhất là sử dụng bất kỳ thư viện javascript nào được tải trên trang đó).

Nguồn để kiểm tra khả năng hiển thị -

https://github.com/SeleniumHQ/selenium/blob/master/javascript/atoms/dom.js#L577

Thông số kỹ thuật WebDriver xác định điều này -

https://dvcs.w3.org/hg/webdriver/raw-file/tip/webdriver-spec.html#widl-WebElement-isDisplayed-boolean


1
Bạn có nguồn (hoặc liên kết chuẩn) cho danh sách các điều kiện không?
mjs

2
Chừng nào bạn có thể đọc Javascript, phương pháp bot.dom.isShown là những gì xác định visibility: code.google.com/p/selenium/source/browse/trunk/javascript/atoms/...
lukeis

inputElement ở đây là gì. Tôi chạy đoạn mã dưới đây WebElement inputElement = driver.findElement (By.xpath (PASSWORD_PATH)); ((JavascriptExecutor) trình điều khiển) .executeScript ("đối số [0] .checked = true;", inputElement); Nhưng Không có Trợ giúp inputElement.sendKeys (mật khẩu);
Deepak Goel

2
@NIleshSharma python có phương pháp execute_script trực tiếp trên đối tượng điều khiển chính nó: driver.execute_script (...)
lukeis

1
Liên kết nguồn được đăng bởi @TunaBum đã thay đổi thành code.google.com/p/selenium/source/browse/javascript/atoms/…
Shepmaster

27

Đôi khi điều này có nghĩa là có nhiều phần tử trên một trang có cùng thuộc tính mà bạn đang cố gắng tìm kiếm và bạn đang "nói nhầm".

Nếu phần tử của bạn không thể được xác định duy nhất bằng: id hoặc: name (hoặc: class), thì có thể rất khó.

Đôi khi tìm kiếm phần tử bằng: xpath sẽ hữu ích và trong một số trường hợp, điều đó thậm chí không thực tế.

Trong những trường hợp đó, bạn có thể phải lấy tất cả các phần tử phù hợp với tiêu chí của mình và tham chiếu đến phần tử phù hợp theo chỉ mục. Nó bẩn, nhưng nó hoạt động.

Tôi đang sử dụng Selenium / Watir từ ứng dụng Ruby on Rails, vì vậy trong trường hợp của tôi, ví dụ sẽ là:

browser = Watir::Browser.new(:firefox, :profile => "default")       
browser.goto("http://www.google.com/analytics")
# login
browser.divs(:text, "+ New Property").last.click

Hi vọng điêu nay co ich.


thêm id vào phần tử dom đã sửa nó cho tôi
naoru

Tôi đã gặp vấn đề tương tự và điều chỉnh XPath để nó có thể phân biệt một phần tử duy nhất đã thực hiện thủ thuật.
JohnL

Tôi đã từng gặp vấn đề tương tự. Đã thay đổi lệnh gọi findElements () để đếm các kết quả phù hợp và có thêm một phần tử phù hợp. Cảm ơn!
Aries,

Rất nhiều điều này đối với tôi. LUÔN LUÔN đảm bảo tiêu chí lựa chọn của bạn đủ cụ thể cho yếu tố mà bạn nghĩ rằng bạn đang tương tác. Nhiều lần tôi đã có hai yếu tố khi chơi và một yếu tố bị ẩn và gây ra lỗi này cho tôi.
Chris

14

Tôi đã gặp sự cố tương tự, nhưng nó liên quan đến phần tử không hiển thị trong chế độ xem. Tôi đã chụp ảnh màn hình và nhận ra cửa sổ trình duyệt quá hẹp và không thể nhìn thấy phần tử. Tôi đã làm một trong những điều này và nó hoạt động:

driver.maximize_window()

Xem: WebDriver.maximize_window ()


7

Hoặc bạn có thể sử dụng Selenium Action Class để mô phỏng tương tác của người dùng - Ví dụ:

    WebDriver = new FirefoxDriver();

    WebElement menu = driver.findElement(By.xpath("")); // the triger event element

    Actions build = new Actions(driver); // heare you state ActionBuider
    build.moveToElement(menu).build().perform(); // Here you perform hover mouse over the needed elemnt to triger the visibility of the hidden
    WebElement m2m= driver.findElement(By.xpath(""));//the previous non visible element
    m2m.click();

7

Cũng có một trường hợp khác khi phần tử hiển thị sẽ được nhận dạng là không hiển thị:

  • Khi Phần tử được chuyển đổi CSS
  • Khi phần tử chính của phần tử được chuyển đổi CSS

Để kiểm tra xem phần tử bạn không thể tương tác có được chuyển đổi CSS hay không, trên CHROME, hãy làm như sau:

  1. thanh tra mở
  2. Tìm phần tử thú vị (hoặc nhiều khả năng là phần tử mẹ của nó, được cho là phần tử div)
  3. Chọn tab 'Đã tính'
  4. nếu có một tham số: webkit-biến đổi: ma trận (...), điều đó có nghĩa là phần tử được chuyển đổi CSS và có thể không được selen 2 công nhận là phần tử hiển thị


2

Tôi đã gặp vấn đề tương tự với selen 2 trong Internet explorer 9, nhưng cách khắc phục của tôi thực sự kỳ lạ. Tôi không thể nhấp vào các đầu vào bên trong biểu mẫu của mình -> các lần lặp lại selen, chúng không hiển thị.

Nó xảy ra khi biểu mẫu của tôi có bóng cong -> http://www.paulund.co.uk/creating-dierence-css3-box-shadows-effects : trong bê tông "Hiệu ứng số 2"

Tôi không biết, tại sao & làm thế nào giải pháp phần tử giả này dừng các thử nghiệm selen, nhưng nó hoạt động đối với tôi.


2

Bạn không thể buộc truy cập / thay đổi phần tử mà người dùng thường không có quyền truy cập, vì Selenium được thiết kế để bắt chước tương tác của người dùng.

Nếu lỗi này xảy ra, hãy kiểm tra xem:

  • phần tử hiển thị trong khung nhìn của bạn, hãy cố gắng tối đa hóa cửa sổ hiện tại mà webdriver đang sử dụng (ví dụ: maximize()trong node.js ,maximize_window() trong Python),
  • phần tử của bạn không xuất hiện hai lần (trong cùng một bộ chọn) và bạn đang chọn sai,
  • nếu phần tử của bạn bị ẩn, hãy xem xét hiển thị nó,
  • nếu bạn muốn truy cập / thay đổi giá trị của phần tử ẩn bất chấp giới hạn, thì hãy sử dụng Javascript cho điều đó (ví dụ: executeScript()trong node.js , execute_script()bằng Python).

1
Tôi không biết Selenium được thiết kế nghiêm ngặt như vậy. Có vẻ như nó không thực sự là một công cụ tự động hóa theo nghĩa chung, nhiều hơn là một công cụ tương tác người dùng tự động. Tôi đoán có một chút ý nghĩa. Cảm ơn đã làm rõ!
Daniel Lidström

1

Tôi chỉ giải quyết lỗi này khi sử dụng capybara trong dự án ror bằng cách thêm:

Capybara.ignore_elements = true

đến features/support/env.rb.


1

Tôi chỉ giải quyết lỗi này bằng thuộc tính hiển thị phần tử chờ

waitFor() { element.displayed }

Trong số tất cả các câu trả lời trên trang này, đây là cách đã khắc phục sự cố của tôi với hộp thoại Bootstrap Modal. Cảm ơn @Suat Keskin!
alastairs

1

Tôi gặp trường hợp ngoại lệ ElementNotVbrokenException bằng cách sử dụng selen để kiểm tra chức năng trên trang web django với glyphicons bootstrap dưới dạng liên kết trong các mẫu như:

<a href="{% url 'item-add' %}"><span class="glyphicon glyphicon-plus text-danger"></span></a>

Trong quá trình kiểm tra chức năng của tôi, kiểu bootstrap không được tải, sau đó việc cố gắng nhấp vào các liên kết như vậy sẽ làm tăng ElementNotVbrokenException. Tôi quản lý để làm cho họ có thể nhấp chỉ cần thêm một khoảng trống trong thẻ, như sau:

<a href="{% url 'item-add' %}"><span class="glyphicon glyphicon-plus text-danger">&nbsp;</span></a>

1

Có rất nhiều câu trả lời hay trên trang này.

  1. Tôi thường bắt đầu với Maximum.window (), thực sự tôi làm điều này trong Nhà máy trình điều khiển hoặc bất cứ nơi nào bạn khởi tạo trình điều khiển của mình. Đây là điều được thực hiện theo mặc định - luôn luôn.
  2. Nó thường là phần tử chờ đợi vì một số javascript chậm trễ.

Cả hai đều được thảo luận trong các chi tiết khác nhau ở trên. Câu trả lời tôi không thấy là ScrollToElement. Có vẻ như bạn đang xử lý một danh sách các phần tử, trong khi xử lý, bạn đang tạo thêm các phần tử, hộp kiểm. Điều này có thể khiến các phần tử trong danh sách của bạn di chuyển ra khỏi trang hiển thị. Đôi khi bạn có thể nhìn thấy phần tử bằng mắt thường nhưng bạn không thể nhấp vào phần tử đó. Khi xử lý danh sách, đôi khi bạn phải làm gián đoạn quá trình cuộn.

  • Đặt điểm ngắt và kiểm tra xem phần tử bạn đang sử dụng có nằm ở cạnh cửa sổ, trên cùng / dưới cùng bên phải / bên trái hay không. Đôi khi trong trường hợp này, bạn không thể truy cập qua selen nhưng bạn có thể nhấp chuột bằng tay theo cách thủ công.

Bởi vì tôi gặp phải vấn đề này, tôi đã tạo một PageScroll.java và đặt các tập lệnh cuộn của tôi ở đó. Dưới đây là một số phương thức từ lớp này:

public static void scrollToTop(WebDriver driver) {
      ((JavascriptExecutor) driver)
        .executeScript("window.scrollTo(0,0)");
    }

    public static void scrollToBottom(WebDriver driver) {
      ((JavascriptExecutor) driver)
        .executeScript("window.scrollTo(0, document.body.scrollHeight)");
    }

    public static void scrollToElementTop(WebDriver driver, WebElement element) {
      ((JavascriptExecutor) driver).executeScript(
        "arguments[0].scrollIntoView(true);", element);
    }

    public static void scrollToElementBottom(WebDriver driver, WebElement element) {
      ((JavascriptExecutor) driver).executeScript(
        "arguments[0].scrollIntoView(false);", element);
    }

xem Scroll Element into View with Selenium để biết thêm ví dụ


0

Câu trả lời được chấp nhận phù hợp với tôi. Dưới đây là một số mã để tìm phần tử mẹ khiến Selenium nghĩ rằng nó không hiển thị.

function getStyles(element){
	
	computedStyle = window.getComputedStyle(element);

	if(computedStyle.opacity === 0
	|| computedStyle.display === "none"
	|| computedStyle.visibility === "hidden"
	|| (computedStyle.height < 0 && computedStyle.height < 0)
	|| element.type === "hidden") {
		console.log("Found an element that Selenium will consider to not be visible")
		console.log(element);
		console.log("opacity: " + computedStyle.opacity);
		console.log("display: " + computedStyle.display);
		console.log("visibility: " + computedStyle.visibility);
		console.log("height: " + computedStyle.height);
		console.log("width: " + computedStyle.width);
	}

	if(element.parentElement){
		getStyles(element.parentElement);
	}
}

getStyles(document.getElementById('REPLACE WITH THE ID OF THE ELEMENT YOU THINK IS VISIBLE BUT SELENIUM CAN NOT FIND'));


0

Để thêm hạt cát của tôi ở đây: nếu một phần tử nằm sau một đường chia cố định, nó sẽ được coi là không hiển thị và bạn sẽ không thể nhấp vào nó; điều này đã xảy ra với tôi gần đây và tôi đã giải quyết nó bằng cách thực thi một tập lệnh như được đề xuất ở trên, điều này thực hiện:

document.evaluate("<xpath locator for element to be clicked>", document, null, XPathResult.ANY_TYPE, null).iterateNext().click()", locator);

Định vị ở đây là gì?
Anjana
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.