วิธีบังคับให้ Selenium WebDriver คลิกองค์ประกอบที่มองไม่เห็นในปัจจุบัน


99

ฉันใช้ Selenium 2 Java API กับ FirefoxDriver เมื่อฉันกรอกแบบฟอร์มช่องทำเครื่องหมายจะถูกเพิ่มลงในเพจโดยขึ้นอยู่กับอินพุตของฟอร์ม

ฉันต้องการจำลองการคลิกที่ช่องทำเครื่องหมายโดยใช้ซีลีเนียม องค์ประกอบสามารถมองเห็นได้และใช้งานได้ในเบราว์เซอร์ทั่วไป แต่ซีลีเนียมยืนยันว่ามองไม่เห็นองค์ประกอบ

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

ฉันสามารถบังคับให้ซีลีเนียมเพิกเฉยต่อสถานะที่มองไม่เห็นขององค์ประกอบได้หรือไม่? ฉันจะบังคับให้ซีลีเนียมโต้ตอบกับองค์ประกอบที่มองไม่เห็นได้อย่างไร


สิ่งที่เบราว์เซอร์ที่คุณใช้? คุณไม่สามารถโต้ตอบกับองค์ประกอบที่ปิดใช้งานหรือมองไม่เห็นเนื่องจากผู้ใช้ปลายทางจะไม่สามารถโต้ตอบกับองค์ประกอบเหล่านี้ได้ คุณจะต้องให้รหัสทดสอบและแหล่งที่มาของหน้าหากคุณต้องการให้ฉันลองวิเคราะห์ปัญหา
Ardesco

คำตอบ:


102

ซีลีเนียมกำหนดว่าองค์ประกอบสามารถมองเห็นได้หรือไม่ตามเกณฑ์ต่อไปนี้ (ใช้ตัวตรวจสอบ DOM เพื่อพิจารณาว่า css ใช้กับองค์ประกอบของคุณอย่างไรตรวจสอบให้แน่ใจว่าคุณดูรูปแบบการคำนวณ):

  • visibility! = hidden
  • display! = none (ยังตรวจสอบกับทุกองค์ประกอบหลัก)
  • ความทึบ! = 0 (ไม่ได้ตรวจสอบการคลิกองค์ประกอบ)
  • ความสูงและความกว้างเป็นทั้ง> 0
  • สำหรับอินพุตประเภทแอตทริบิวต์! = hidden

องค์ประกอบของคุณตรงกับหนึ่งในเกณฑ์เหล่านั้น หากคุณไม่มีความสามารถในการเปลี่ยนรูปแบบขององค์ประกอบนี่คือวิธีที่คุณสามารถทำได้อย่างมีประสิทธิภาพด้วยจาวาสคริปต์ (จะถือว่า WebDriver เนื่องจากคุณพูดว่า Selenium2 API):

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

แต่จะไม่เริ่มเหตุการณ์จาวาสคริปต์หากคุณขึ้นอยู่กับเหตุการณ์การเปลี่ยนแปลงสำหรับอินพุตนั้นคุณจะต้องเริ่มการทำงานด้วย (หลายวิธีในการทำเช่นนั้นง่ายที่สุดในการใช้ไลบรารีจาวาสคริปต์ที่โหลดในหน้านั้น)

ที่มาของการตรวจสอบการมองเห็น -

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

ข้อกำหนดของ WebDriver ที่กำหนดสิ่งนี้ -

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


1
คุณมีแหล่งที่มา (หรือลิงก์บัญญัติ) สำหรับรายการเงื่อนไขหรือไม่?
mjs

2
ตราบใดที่คุณสามารถอ่าน Javascript ได้วิธีการ bot.dom.isShown คือสิ่งที่กำหนดการเปิดเผย: code.google.com/p/selenium/source/browse/trunk/javascript/atoms/…
lukeis

inputElement คืออะไรที่นี่ ฉันรันโค้ดด้านล่าง WebElement inputElement = driver.findElement (By.xpath (PASSWORD_PATH)); ((ไดรเวอร์ JavascriptExecutor)) .executeScript ("อาร์กิวเมนต์ [0] .checked = true;", inputElement); แต่ No Help inputElement.sendKeys (รหัสผ่าน);
Deepak Goel

2
@NIleshSharma python มีเมธอด execute_script บนวัตถุไดรเวอร์โดยตรง: driver.execute_script (... )
lukeis

1
ลิงก์ต้นทางที่โพสต์โดย @TunaBum ได้เปลี่ยนเป็นcode.google.com/p/selenium/source/browse/javascript/atoms/…
Shepmaster

27

บางครั้งหมายความว่ามีองค์ประกอบหลายรายการในหน้าเว็บที่มีพร็อพเพอร์ตี้เดียวกับที่คุณกำลังพยายามค้นหาและคุณกำลัง "พูดผิด"

หากองค์ประกอบของคุณไม่สามารถระบุโดยเฉพาะโดย: id หรือ: name (หรือ: class) อาจเป็นเรื่องยุ่งยาก

บางครั้งการค้นหาองค์ประกอบโดย: xpath จะช่วยได้และในบางกรณีก็ไม่สามารถใช้งานได้จริง

ในกรณีดังกล่าวคุณอาจต้องได้รับองค์ประกอบทั้งหมดที่ตรงกับเกณฑ์ของคุณและอ้างอิงองค์ประกอบที่ถูกต้องโดยดัชนี มันสกปรก แต่ก็ใช้ได้

ฉันใช้ Selenium / Watir จากแอป Ruby on Rails ดังนั้นในกรณีของฉันตัวอย่างจะเป็น:

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

หวังว่านี่จะช่วยได้


การเพิ่ม id ไปยังองค์ประกอบ dom แก้ไขให้ฉัน
naoru

ฉันมีปัญหาเดียวกันและการปรับ XPath เพื่อให้สามารถแยกแยะองค์ประกอบที่ไม่ซ้ำกันได้เป็นเคล็ดลับ
JohnL

ผมมีปัญหาเหมือนกัน. เปลี่ยนการเรียกไปที่ findElements () เพื่อนับการแข่งขันและมีอีกหนึ่งองค์ประกอบที่ตรงกัน ขอบคุณ!
ราศีเมษ

มากสำหรับฉัน ตรวจสอบให้แน่ใจเสมอว่าเกณฑ์การคัดเลือกของคุณมีความเฉพาะเจาะจงเพียงพอกับองค์ประกอบที่คุณคิดว่าคุณกำลังโต้ตอบด้วย หลายครั้งฉันมีองค์ประกอบสองอย่างในการเล่นและอีกหนึ่งถูกซ่อนไว้และทำให้ฉันเกิดข้อผิดพลาดนี้
คริส

14

ฉันมีปัญหาที่คล้ายกัน แต่เกี่ยวข้องกับองค์ประกอบที่มองไม่เห็นในวิวพอร์ต ฉันถ่ายภาพหน้าจอและพบว่าหน้าต่างเบราว์เซอร์แคบเกินไปและมองไม่เห็นองค์ประกอบ ฉันทำอย่างใดอย่างหนึ่งและได้ผล:

driver.maximize_window()

ดู: WebDriver.maximize_window ()


7

หรือคุณอาจใช้ Selenium Action Class เพื่อจำลองการโต้ตอบของผู้ใช้ - ตัวอย่างเช่น

    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

นอกจากนี้ยังมีอีกกรณีหนึ่งที่องค์ประกอบที่มองเห็นได้จะถูกรับรู้ว่ามองไม่เห็น:

  • เมื่อองค์ประกอบถูกเปลี่ยน CSS
  • เมื่อองค์ประกอบหลักขององค์ประกอบถูกเปลี่ยน CSS

ในการตรวจสอบว่าองค์ประกอบที่คุณไม่ต้องการโต้ตอบนั้นมีการแปลง CSS หรือไม่บน CHROME ให้ทำสิ่งนี้:

  1. เปิดสารวัตร
  2. ค้นหาองค์ประกอบที่น่าสนใจ (หรือมีแนวโน้มมากกว่าองค์ประกอบหลักองค์ประกอบ div ที่คาดคะเน)
  3. เลือกแท็บ 'คำนวณแล้ว'
  4. หากมีพารามิเตอร์: webkit-transform: matrix (... ) หมายความว่าองค์ประกอบนั้นถูกแปลงเป็น CSS และซีลีเนียม 2 อาจไม่ได้รับการยอมรับว่าเป็นองค์ประกอบที่มองเห็นได้

5

การล่องหนอาจเกิดจากเวลาที่องค์ประกอบควรจะปรากฏขึ้นอย่างช้าๆ การบังคับให้เบราว์เซอร์รอสักครู่อาจช่วยได้ในกรณีนั้น

ดูเช่นคำถามเกี่ยวกับการให้WebDriver รอจนกว่าองค์ประกอบจะปรากฏขึ้น


2

ฉันมีปัญหาเดียวกันกับซีลีเนียม 2 ใน internet explorer 9 แต่การแก้ไขของฉันแปลกจริงๆ ฉันไม่สามารถคลิกเข้าสู่อินพุตภายในแบบฟอร์มของฉัน -> ซีลีเนียมซ้ำไม่สามารถมองเห็นได้

มันเกิดขึ้นเมื่อแบบฟอร์มของฉันมีเงาโค้ง -> http://www.paulund.co.uk/creating-different-css3-box-shadows-effects : ในคอนกรีต "Effect no. 2"

ฉันไม่รู้ว่าทำไมและวิธีแก้ปัญหาองค์ประกอบหลอกนี้หยุดการทดสอบซีลีเนียม แต่มันใช้ได้กับฉัน


2

คุณไม่สามารถบังคับให้เข้าถึง / เปลี่ยนแปลงองค์ประกอบที่โดยปกติผู้ใช้ไม่มีสิทธิ์เข้าถึงเนื่องจาก Selenium ออกแบบมาเพื่อเลียนแบบการโต้ตอบของผู้ใช้

หากเกิดข้อผิดพลาดนี้ให้ตรวจสอบว่า:

  • องค์ประกอบที่ปรากฏอยู่ใน viewport คุณพยายามที่จะเพิ่มหน้าต่างปัจจุบันที่ webdriver ใช้ (เช่นmaximize()ในNode.js , maximize_window()ในหลาม)
  • องค์ประกอบของคุณไม่ปรากฏขึ้นสองครั้ง (ภายใต้ตัวเลือกเดียวกัน) และคุณกำลังเลือกผิด
  • หากองค์ประกอบของคุณซ่อนอยู่ให้พิจารณาทำให้มองเห็นได้
  • ถ้าคุณต้องการที่จะคุ้มค่าการเข้าถึง / การเปลี่ยนแปลงขององค์ประกอบที่ซ่อนอยู่แม้จะมีข้อ จำกัด จากนั้นใช้จาวาสคริปต์ที่ (เช่นexecuteScript()ในNode.js , execute_script()ในหลาม)

1
ฉันไม่รู้ว่าซีลีเนียมถูกออกแบบมาให้เข้มงวดขนาดนี้ ดูเหมือนว่ามันจะไม่ใช่เครื่องมืออัตโนมัติในความหมายทั่วไป แต่เป็นเครื่องมือโต้ตอบกับผู้ใช้อัตโนมัติมากกว่า ฉันเดาว่ามันสมเหตุสมผลแล้ว ขอบคุณที่ชี้แจง!
Daniel Lidström

1

ฉันเพิ่งแก้ไขข้อผิดพลาดนี้ในขณะที่ใช้ capybara ใน ror project โดยเพิ่ม:

Capybara.ignore_elements = true

ถึงfeatures/support/env.rb.


1

ฉันเพิ่งแก้ไขข้อผิดพลาดนี้โดยรอคุณสมบัติการแสดงองค์ประกอบ

waitFor() { element.displayed }

จากคำตอบทั้งหมดในหน้านี้นี่คือสิ่งที่แก้ไขปัญหาของฉันด้วยกล่องโต้ตอบ Bootstrap Modal ขอบคุณ @Suat Keskin!
alastairs

1

ฉันเข้าสู่ข้อยกเว้น ElementNotVisibleException โดยใช้ซีลีเนียมสำหรับการทดสอบการทำงานบนไซต์ django ที่มี bootstrap glyphicons เป็นลิงก์ในเทมเพลตเป็น:

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

ในระหว่างการทดสอบการทำงานของฉันสไตล์ bootstrap จะไม่ถูกโหลดจากนั้นการพยายามคลิกที่ลิงก์ดังกล่าวจะเพิ่ม ElementNotVisibleException ฉันจัดการเพื่อให้คลิกได้เพียงแค่เพิ่มช่องว่างในแท็กเช่นนั้น:

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

1

มีคำตอบดีๆมากมายในเพจนี้

  1. ฉันมักจะเริ่มต้นด้วย maximize.window () ซึ่งจริงๆแล้วฉันทำสิ่งนี้ในไดรเวอร์ Factory หรือที่ใดก็ตามที่คุณเริ่มต้นไดรเวอร์ของคุณ นี่คือสิ่งที่ทำโดยค่าเริ่มต้น - เสมอ
  2. โดยปกติจะรอองค์ประกอบเนื่องจากความล่าช้าของจาวาสคริปต์

ทั้งสองจะกล่าวถึงในรายละเอียดต่างๆข้างต้น คำตอบที่ฉันไม่เห็นคือ ScrollToElement ดูเหมือนว่าคุณกำลังประมวลผลรายการองค์ประกอบในขณะที่กำลังประมวลผลคุณกำลังสร้างองค์ประกอบเพิ่มเติมช่องทำเครื่องหมาย ซึ่งอาจทำให้องค์ประกอบในรายการของคุณย้ายออกจากหน้าที่มองเห็นได้ บางครั้งคุณสามารถมองเห็นองค์ประกอบได้ด้วยตาเปล่า แต่คุณไม่สามารถคลิกได้ เมื่อประมวลผลรายการบางครั้งคุณต้องแทรกการเลื่อน

  • กำหนดจุดพักและตรวจสอบว่าองค์ประกอบที่คุณใช้อยู่ที่ขอบหน้าต่างด้านบน / ล่างขวา / ซ้ายหรือไม่ บางครั้งเมื่อเป็นกรณีนี้คุณไม่สามารถเข้าถึงซีลีเนียมได้ แต่คุณสามารถคลิกเมาส์ด้วยตนเองได้

เนื่องจากฉันทำงานข้ามสิ่งนี้ฉันจึงสร้าง PageScroll.java และวางสคริปต์การเลื่อนไว้ที่นั่น วิธีการบางอย่างจากคลาสนี้มีดังต่อไปนี้:

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);
    }

ดูScroll Element ใน View with Selenium สำหรับตัวอย่างเพิ่มเติม


0

คำตอบที่ยอมรับได้ผลสำหรับฉัน ด้านล่างนี้คือโค้ดบางส่วนเพื่อค้นหาองค์ประกอบหลักที่ทำให้ Selenium คิดว่ามองไม่เห็น

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

หากต้องการเพิ่มเม็ดทรายของฉันที่นี่: หากองค์ประกอบอยู่หลัง div คงที่จะถือว่ามองไม่เห็นและคุณจะไม่สามารถคลิกได้ สิ่งนี้เกิดขึ้นกับฉันเมื่อไม่นานมานี้และฉันได้แก้ไขโดยเรียกใช้สคริปต์ตามที่แนะนำข้างต้นซึ่งทำ:

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

ตัวระบุตำแหน่งที่นี่คืออะไร?
Anjana
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.