View Javadoc
1   /*
2    * Copyright (C) 2010-2014 Hamburg Sud and the contributors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.aludratest.service.gui.web.selenium.selenium2;
17  
18  import java.text.MessageFormat;
19  
20  import org.aludratest.service.locator.element.XPathLocator;
21  import org.openqa.selenium.By;
22  import org.openqa.selenium.InvalidSelectorException;
23  import org.openqa.selenium.JavascriptExecutor;
24  import org.openqa.selenium.WebDriver;
25  import org.openqa.selenium.WebElement;
26  import org.slf4j.Logger;
27  import org.slf4j.LoggerFactory;
28  
29  /**
30   * Performs z-index calculations with Selenium 2.
31   * author Marcel Malitz
32   * @author Volker Bergmann
33   */
34  public class ZIndexSupport {
35  
36      private static final Logger LOGGER = LoggerFactory.getLogger(ZIndexSupport.class);
37  
38      private static final int DEFAULT_Z_INDEX = 0;
39  
40      /*
41      	final static private String zIndexSearch = "this.browserbot.findElement('xpath=(//"
42      			+ "iframe[contains(@style, \"z-index\")])[arguments[0]]')"
43      			+ ".getAttribute('style')";
44       */
45      private static final String Z_INDEX_SEARCH_XPATH = "//iframe[contains(@style, ''z-index'')])[{0}]";
46  
47      private WebDriver driver;
48  
49      public ZIndexSupport(WebDriver driver) {
50          this.driver = driver;
51      }
52  
53      /** Checks if a element is blocked by a modal dialog. */
54      public boolean isInForeground(WebElement element) {
55          return (getCurrentZIndex(element) >= getMaxZIndex());
56      }
57  
58      /** To get the z-index (defined in the attribute "style") for the operated element. There are 3 possibilities for retrieving
59       * z-index: <br/>
60       * 1) If a z-index is defined for this element or its ancestor, then return this value <br/>
61       * 2) If no z-index is defined for this element and its ancestor, then use the base z-index for this page <br/>
62       * 3) For an element of the type "LabelLocator", the base z-index will be returned
63       * @param element The element to check.
64       * @return current z-Index */
65      public int getCurrentZIndex(WebElement element) {
66          String zIndex = null;
67          try {
68              do {
69                  zIndex = element.getCssValue("z-index");
70                  element = element.findElement(By.xpath(".."));
71              } while ("auto".equals(zIndex) && element != null);
72          } catch (InvalidSelectorException e) {
73              // this occurs when having reached the root element
74          }
75          int value = parseZIndex(zIndex);
76          LOGGER.debug("WebElement {} has z index {}", element, value);
77          return value;
78      }
79  
80      /** To get the biggest value of z-index for all of the elements on current page.
81       *  The element with the biggest value of z-index will be shown in foreground.
82       *  The elements with the lower value of z-index will be shown in background.
83       *  @return the biggest value of z-index on current page
84       */
85      public int getMaxZIndex() {
86          int zIndex = getBaseZIndex();
87          int zIndexCount = 0;
88          zIndexCount = getZIndexCount();
89          for (int i = 0; i < zIndexCount; i++) {
90              int tmpzIndex = getzIndex(i + 1);
91              zIndex = (tmpzIndex > zIndex) ? tmpzIndex : zIndex;
92          }
93          return zIndex;
94      }
95  
96      private int getBaseZIndex() {
97          // If it has a default z-Index defined in code, then get its value
98          if (getHistoryFrameCount() > 0) {
99              return getzIndex(0);
100             // If it has not defined a default z-Index in code, then set it to a default value
101         } else {
102             return DEFAULT_Z_INDEX;
103         }
104     }
105 
106     private int getZIndexCount() {
107         return getXPathCount("//iframe[contains(@style, \"z-index\")]");
108     }
109 
110     private int getHistoryFrameCount() {
111         int historyFrameCount = 0;
112         historyFrameCount = getXPathCount("//iframe[starts-with(@id, \"history-frame\")]");
113         return historyFrameCount;
114     }
115 
116     private int getzIndex(int index) {
117         int tmpzIndex = DEFAULT_Z_INDEX;
118         // If a base value is defined in code, it will overwrite the default value
119         try {
120             String zIndexSearchXPath = MessageFormat.format(Z_INDEX_SEARCH_XPATH, index);
121             WebElement element = LocatorUtil.findElement(new XPathLocator(zIndexSearchXPath), driver);
122             String tmpElement = (String) executeScript(element.getAttribute("style"), index);
123             tmpzIndex = getzIndexFromStyle(tmpElement);
124         } catch (InvalidSelectorException e) {
125             // This may happen for some elements and needs to be ignored
126         }
127         return tmpzIndex;
128     }
129 
130     private int getzIndexFromStyle(String style) {
131         if (style.endsWith("undefined")) {
132             // a normal element without z-Index defined
133             return getBaseZIndex();
134         } else {
135             // an element with z-Index
136             for (String tmp : style.split(";")) {
137                 if (tmp.trim().startsWith("z-index")) {
138                     return Integer.parseInt(tmp.replace("z-index:", "").trim());
139                 }
140             }
141         }
142         return getBaseZIndex();
143     }
144 
145     private int parseZIndex(String zIndexString) {
146         if ("auto".equals(zIndexString)) {
147             return getBaseZIndex();
148         } else {
149             return Integer.parseInt(zIndexString.trim());
150         }
151     }
152 
153     private int getXPathCount(String xpath) {
154         return driver.findElements(By.xpath(xpath)).size();
155     }
156 
157     private Object executeScript(String script, Object... arguments) {
158         return ((JavascriptExecutor) driver).executeScript(script, arguments);
159     }
160 
161 }