2013-02-01 23 views
12

का उपयोग करके मैं java.awt.Robot साथ संयोजन के रूप में सेलेनियम WebDriver उपयोग कर रहा हूँ बेहतर हमारी वेब आवेदन के साथ उपयोगकर्ता बातचीत अनुकरण करने के लिए। हां, मुझे पता है कि यह शायद अनावश्यक है, लेकिन जिन ग्राहकों की मैं सेवा करता हूं, वे इसकी मांग करते हैं।सेलेनियम WebDriver और HTML विंडो स्थान जावा

वर्तमान में बातें बहुत अच्छी तरह से काम कर रहे हैं, फिर भी मुझे लगता है कि में एक छोटी सी रोड़ा है मैं स्क्रीन स्थिति पर वेब तत्व 'प्राप्त करने के लिए एक अच्छा तरीका खोजने के लिए प्रतीत नहीं कर सकते हैं। टाइटल बार, मेन्यू बार, नेविगेशन बार इत्यादि जैसी चीजें सभी सामग्री को भौतिक स्क्रीन पर दबाती हैं (जो रोबोट से इसके निर्देशांक प्राप्त करती है), लेकिन इस पर कोई प्रभाव नहीं पड़ता कि सेलेनियम तत्व की रिपोर्ट करता है।

जब मैं कॉल करता हूं: element.getLocation(); सेलेनियम वेबलेमेंट पर, यह हमेशा मुझे एचटीएमएल सामग्री रेंडर फलक के सापेक्ष अपना स्थान देता है, ब्राउज़र विंडो नहीं।

एक बेहतर उदाहरण है: driver.findElement(By.tagName("body")).getLocation(); हमेशा 0,0 देता है, खिड़की के वास्तविक परदे पर स्थान की परवाह किए बिना।

अभी मैं खिड़की को अधिकतम करने के बाद एक लंबवत और क्षैतिज ऑफसेट जोड़ कर हैकिंग कर रहा हूं, लेकिन ये विभिन्न ब्राउज़रों के बीच समान नहीं हैं (आईई की शीर्ष सजावट फ़ायरफ़ॉक्स के उदाहरण के लिए अधिक कमरे लेती हैं), और हो सकता है प्रत्येक उपयोगकर्ता के लिए अलग अगर वे उपकरण सलाखों, खोज बार, आदि में।

जोड़ा हाँ, मैं जानता हूँ कि मैं पूर्ण स्क्रीन मोड में चला सकते हैं, लेकिन मैं नहीं बल्कि नहीं था, अगर सब पर संभव बुकमार्क है।

वहाँ WebDriver उपयोग करने के लिए एक विश्वसनीय ढंग से तत्वों के भौतिक परदे पर स्थान पाने के लिए एक तरीका है?

+2

सेलेनियम टीम में रुचि व्यक्त करने के लिए आपको इस मुद्दे को तारांकित करने में रुचि हो सकती है: https://code.google.com/p/selenium/issues/detail?id=5267 – kem

उत्तर

6

मेरा मानना ​​है कि वहाँ पृष्ठ पर कुछ तत्व असली परदे पर स्थान पाने के लिए कोई रास्ता नहीं है।

मुझे यह भी लगता है कि पूर्णस्क्रीन मोड आपकी सबसे अच्छी शर्त है।

उस ने कहा, मैंने RobotCalibration कक्षा लिखा है जो आपके वर्तमान ब्राउज़र के असली ऑफ़सेट का पता लगा सकता है। यह एक विशेष रूप से तैयार किए गए पृष्ठ को खोलता है और उस पर क्लिक करने के लिए Robot कक्षा का उपयोग करता है। एल्गोरिदम ब्राउज़र के केंद्र में शुरू होता है और फिर ब्राउज़र व्यूपोर्ट के ऊपरी बाएं कोने को खोजने के लिए बिसेक्टिंग का उपयोग करता है।

आईई 8 और एफएफ 18 पर परीक्षण किया गया। अधिकतम और खिड़की वाले ब्राउज़र दोनों के लिए काम करता है। ज्ञात समस्या: यदि आपके पास शीर्ष बुकमार्क टूलबार सक्षम है, तो यह कुछ बुकमार्क पर क्लिक कर सकता है और इसलिए रीडायरेक्ट कर सकता है। इसे बहुत आसानी से संभाला जा सकता है, लेकिन अगर आपको इसकी ज़रूरत है तो मैंने इसे आपके ऊपर छोड़ दिया :)।

परीक्षण पेज:

<!DOCTYPE html> 
<html lang="en" onclick="document.getElementById('counter').value++"> 
<head> 
    <meta charset="utf-8" /> 
    <title>Calibration Test</title> 
</head> 
<body> 
    <img height="1" width="1" style="position: absolute; left: 0; top: 0;" 
     onclick="document.getElementById('done').value = 'yep'" /> 
    <input type="text" id="counter" value="0" /> 
    <input type="text" id="done" value="nope" /> 
</body> 
</html> 

RobotCalibration वर्ग। यह एक छोटा सा लंबा है, तो मैं आप अपने पसंदीदा आईडीई में copypaste और वहाँ यह पता लगाने के लिए सुझाव देते हैं:

import java.awt.AWTException; 
import java.awt.Dimension; 
import java.awt.Point; 
import java.awt.Robot; 
import java.awt.Toolkit; 
import java.awt.event.InputEvent; 
import java.nio.file.Paths; 

import org.openqa.selenium.By; 
import org.openqa.selenium.WebDriver; 
import org.openqa.selenium.ie.InternetExplorerDriver; 

public class RobotCalibration { 

    public static Point calibrate(WebDriver driver) { 
     return new RobotCalibration(driver).calibrate(); 
    } 

    /** Time for which to wait for the page response. */ 
    private static final long TIMEOUT = 1000; 

    private final WebDriver driver; 
    private final Robot r; 

    private final Point browserCenter; 
    private int leftX; 
    private int rightX; 
    private int midX; 
    private int topY; 
    private int bottomY; 
    private int midY; 

    private RobotCalibration(WebDriver driver) { 
     this.driver = driver; 
     try { 
      driver.manage().window().getSize(); 
     } catch (UnsupportedOperationException headlessBrowserException) { 
      throw new IllegalArgumentException("Calibrating a headless browser makes no sense.", headlessBrowserException); 
     } 

     try { 
      this.r = new Robot(); 
     } catch (AWTException headlessEnvironmentException) { 
      throw new IllegalStateException("Robot won't work on headless environments.", headlessEnvironmentException); 
     } 

     Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 
     org.openqa.selenium.Dimension browserSize = driver.manage().window().getSize(); 
     org.openqa.selenium.Point browserPos = driver.manage().window().getPosition(); 

     // a maximized browser returns negative position 
     // a maximized browser returns size larger than actual screen size 
     // you can't click outside the screen 
     leftX = Math.max(0, browserPos.x); 
     rightX = Math.min(leftX + browserSize.width, screenSize.width - 1); 
     midX = (leftX + rightX) /2; 

     topY = Math.max(0, browserPos.y); 
     bottomY = Math.min(topY + browserSize.height, screenSize.height - 1); 
     midY = (topY + bottomY) /2; 

     browserCenter = new Point(midX, midY); 
    } 

    private Point calibrate() { 
     driver.get(Paths.get("files/RobotCalibration.html").toUri().toString()); 

     // find left border 
     while (leftX < rightX) { 
      click(midX, midY); 
      if (clickWasSuccessful()) { 
       rightX = midX; 
      } else { 
       leftX = midX + 1; 
       // close any menu we could have opened 
       click(browserCenter.x, browserCenter.y); 
      } 
      midX = (leftX + rightX) /2; 
     } 

     // find top border 
     while (topY < bottomY) { 
      click(midX, midY); 
      if (clickWasSuccessful()) { 
       bottomY = midY; 
      } else { 
       topY = midY + 1; 
       // close any menu we could have opened 
       click(browserCenter.x, browserCenter.y); 
      } 
      midY = (topY + bottomY) /2; 
     } 

     if (!isCalibrated()) { 
      throw new IllegalStateException("Couldn't calibrate the Robot."); 
     } 
     return new Point(midX, midY); 
    } 

    /** clicks on the specified location */ 
    private void click(int x, int y) { 
     r.mouseMove(x, y); 
     r.mousePress(InputEvent.BUTTON1_DOWN_MASK); 
     r.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); 

     // for some reason, my IE8 can't properly register clicks that are close 
     // to each other faster than click every half a second 
     if (driver instanceof InternetExplorerDriver) { 
      sleep(500); 
     } 
    } 

    private static void sleep(int millis) { 
     try { 
      Thread.sleep(millis); 
     } catch (InterruptedException ignored) { 
      // nothing to do 
     } 
    } 

    private int counter = 0; 
    /** @return whether the click on a page was successful */ 
    private boolean clickWasSuccessful() { 
     counter++; 

     long targetTime = System.currentTimeMillis() + TIMEOUT; 
     while (System.currentTimeMillis() < targetTime) { 
      int pageCounter = Integer.parseInt(driver.findElement(By.id("counter")).getAttribute("value")); 
      if (counter == pageCounter) { 
       return true; 
      } 
     } 
     return false; 
    } 

    /** @return whether the top left corner has already been clicked at */ 
    private boolean isCalibrated() { 
     long targetTime = System.currentTimeMillis() + TIMEOUT; 
     while (System.currentTimeMillis() < targetTime) { 
      if (driver.findElement(By.id("done")).getAttribute("value").equals("yep")) { 
       return true; 
      } 
     } 
     return false; 
    } 

} 

नमूना उपयोग:

WebDriver driver = new InternetExplorerDriver(); 
Point p = RobotCalibration.calibrate(driver); 
System.out.println("Left offset: " + p.x + ", top offset: " + p.y); 
driver.quit(); 

किसी भी सवाल पूछने के लिए अगर कुछ स्पष्ट नहीं है स्वतंत्र महसूस।

+0

मैं वास्तव में वही करने जा रहा था चीज, बस एक और अधिक सुरुचिपूर्ण समाधान की उम्मीद है। धन्यवाद! – Merkidemis

+0

@Merkidemis हाँ, मैंने समाधान खोजने के लिए कुछ समय की कोशिश की, क्योंकि मुझे इसकी भी आवश्यकता थी। पूर्णस्क्रीन मोड के साथ समाप्त हुआ जो मुझे [इस बग] के कारण परेशान करता है (http://code.google.com/p/selenium/issues/detail?आईडी = 4067) जो पूर्णस्क्रीन पर स्क्रीनशॉट को अनुपयोगी बनाता है। –

+1

मुझे इन विभिन्न ऑफ़सेट को सहेजने जा रहे हैं, क्योंकि जिस वेब ऐप का मैं परीक्षण कर रहा हूं, उदाहरण के लिए पता बार के बिना नई विंडो खुल जाएगी। सत्र (शुरुआत और मेनू बार के साथ) की शुरुआत में किए गए अंशांकन बेकार होंगे। – Merkidemis

4

पूर्ण ऑफसेट के सापेक्ष होने के लिए Slanec answer से एक आसान तरीका है।

window.coordinates = []; 
window.attachEvent('click', function() { 
    window.coordinates = [event.pageX, event.pageY]; 
}); 

तो फिर तुम JavascriptExecutor के माध्यम से क्लिक करें और रिश्तेदार क्लिक स्थान प्राप्त:

// browser center 
Dimension size = driver.manage().window().getSize(); 
Point point = driver.manage().window().getPosition() 
    .translate(size.width/2, size.height/2); 

// Click through robot 
click(point.x, point.y); 
Thread.sleep(500); 

// read coordinates 
List<Object> coordinates = (List<Object>) ((JavascriptExecutor) driver) 
    .executeScript("return window.coordinates;"); 
if (coordinates.size() != 2) 
    throw new IllegalStateException("Javascript did not receive the click"); 

// point contains screen coordinates of upper left page point 
point.translate(-((Integer)coordinates.get(0)), 
       -((Integer)coordinates.get(1))); 

सबसे पहले आप निर्देशांक और उन्हें एक वैश्विक चर में बचाने के लिए खिड़की पर जावास्क्रिप्ट attached click listener साथ एक रिक्त पृष्ठ की जरूरत है

+1

यह बहुत अच्छा है और मैं बहुत शर्मिंदा हूं मैं अपने साथ नहीं आया! अच्छा लगा। –

0

वर्तमान सेलेनियम वेब तत्व का पूर्ण स्थान प्राप्त करने के लिए एपीआई को लागू नहीं करता है। लेकिन SAFS ने वेब तत्व का पूर्ण स्थान प्राप्त करने के लिए एक संस्करण लागू किया है।

सोच नीचे है:

  1. फ्रेम करने के लिए तत्व के स्थान रिश्तेदार प्राप्त करें। क्योंकि एक ब्राउज़र वेब पेज में बहुत सारे फ्रेम हो सकते हैं। इसके अलावा, फ्रेम किसी अन्य फ्रेम में लगाया जा सकता है। इसलिए, बाहरी फ्रेम के साथ एक वर्ग का उपयोग करना बेहतर है ताकि बाहरी रूप से बाहरी फ्रेम स्थान पर खोज किया जा सके।

`

class FrameElement { 
    FrameElement parent; 
    Point location; 

    FrameElement(FrameElement parent, WebElement frame) throws ... { 
     if(parent != null) { 
      this.parent = parent; 
      location = frame.getLocation().moveBy(parent.getLocation().x, parent.getLocation().y); 
     } else { 
      location = frame.getLocation(); 
     } 
    } 

    public Point getLocation() {return location;} 
} 

Point p = webelement.getLocation(); 
  1. फ्रेम के स्थान, ब्राउज़र क्लाइंट क्षेत्र (भाग को बाहर उपकरण पट्टी, मेनू, आदि) के सापेक्ष जोड़ें।

  2. ब्राउज़र विंडो के सापेक्ष ब्राउज़र क्लाइंट क्षेत्र जोड़ें।

  3. स्क्रीन के सापेक्ष ब्राउज़र विंडो का स्थान जोड़ें।

5

ऐसा लगता है कि सेलेनियम के पास अब आपकी ब्राउज़र विंडो से संबंधित तत्व स्थिति प्राप्त करने का एक तरीका है। मेरे परीक्षणों में से एक में मैं यह सत्यापित करने की कोशिश कर रहा था कि एक पृष्ठ एक निश्चित स्थिति के लिए लगाया गया था और यह पता लगाने का सबसे अच्छा तरीका खिड़की से संबंधित तत्व स्थिति प्राप्त करना था। यह getCoordinates() .ViewPort() विधियों का उपयोग करके किया जा सकता है।

यहाँ एक WebElement के सापेक्ष स्थान प्राप्त करने के लिए कुछ नमूना कोड:

import org.openqa.selenium.By; 
import org.openqa.selenium.Point; 
import org.openqa.selenium.WebDriver; 
import org.openqa.selenium.WebElement; 
import org.openqa.selenium.firefox.FirefoxDriver; 
import org.openqa.selenium.internal.Locatable; 

public class RelativeElementLocation { 

private static Point locationPoint; 
private static Locatable elementLocation; 
WebDriver driver = new FirefoxDriver(); 
WebElement element; 

public Point location() throws Throwable { 
    driver.get("Insert your URL here"); 
    element = driver.findElement(By.id("Insert id/css/xpath/ here")); 
    elementLocation = (Locatable) element; 
    locationPoint = elementLocation.getCoordinates().inViewPort(); 
    System.out.println(locationPoint); 

    return locationPoint; 
    } 
} 

inViewPort() विधि को केवल चेतावनी है कि आप एक तत्व वर्तमान में है कि के रिश्तेदार तत्व स्थान प्राप्त करने की कोशिश करता है, तो पृष्ठ दृश्य में नहीं, विधि पृष्ठ को स्क्रॉल करेगी ताकि तत्व दृश्य में है और फिर आपको सापेक्ष स्थिति दे। मतलब, अगर आप किसी तत्व की सापेक्ष स्थिति प्राप्त करने का प्रयास करते हैं जो आपके ब्राउज़र पृष्ठ दृश्य से ऊपर है, तो यह आपको नकारात्मक y समन्वय देने वाला नहीं है, बल्कि उस तत्व तक स्क्रॉल करें और y समन्वय शून्य बनाएं।

उम्मीद है कि यह मदद करता है, मैं सेलेनियम और जावा के लिए नया हूं इसलिए यदि मेरे कोड में कोई गलती है तो कृपया मुझे क्षमा करें।

संबंधित मुद्दे