1 package io.guixer.tools; 2 3 import static com.google.common.base.Preconditions.checkNotNull; 4 import static org.apache.commons.lang3.StringUtils.substringAfter; 5 import static org.apache.commons.lang3.StringUtils.substringBefore; 6 7 import java.util.List; 8 9 import org.apache.commons.lang3.NotImplementedException; 10 import org.openqa.selenium.By; 11 import org.openqa.selenium.By.ByClassName; 12 import org.openqa.selenium.By.ByCssSelector; 13 import org.openqa.selenium.By.ById; 14 import org.openqa.selenium.By.ByLinkText; 15 import org.openqa.selenium.By.ByName; 16 import org.openqa.selenium.By.ByTagName; 17 import org.openqa.selenium.By.ByXPath; 18 import org.openqa.selenium.WebDriver; 19 import org.openqa.selenium.WebElement; 20 21 import io.guixer.tools.dom.DomFinder; 22 import io.guixer.tools.dom.WebDom; 23 import io.guixer.tools.dom.WebDomElement; 24 25 public abstract class Locators { 26 27 public static By by( 28 final String locator 29 ) { 30 31 checkNotNull(locator, "locator"); 32 33 if (locator.startsWith("#") && !locator.contains(" ") && !locator.contains(".")) { 34 35 return By.id(locator.substring(1)); 36 37 } else if (locator.startsWith("//")) { 38 39 return By.xpath(parseContains(locator)); 40 41 } else if (locator.startsWith("id:")) { 42 43 return By.id(substringAfter(locator, ":")); 44 45 } else if (locator.startsWith("tagName:") || locator.startsWith("tag:")) { 46 47 return By.tagName(substringAfter(locator, ":")); 48 49 } else if (locator.startsWith("cssSelector:") || locator.startsWith("css:")) { 50 51 return By.cssSelector(substringAfter(locator, ":")); 52 53 } else if (locator.startsWith("name:")) { 54 55 return By.name(substringAfter(locator, ":")); 56 57 } else if (locator.startsWith("linkText:") || locator.startsWith("link:")) { 58 59 return By.linkText(substringAfter(locator, ":")); 60 61 } else if (locator.startsWith("partialLinkText:") || locator.startsWith("partialLink:")) { 62 63 return By.partialLinkText(substringAfter(locator, ":")); 64 65 } else if (locator.startsWith("className:") || locator.startsWith("class:")) { 66 67 return By.className(substringAfter(locator, ":")); 68 69 } else if (locator.startsWith("xpath:")) { 70 71 return By.xpath(substringAfter(locator, ":")); 72 73 } else if (locator.contains("#") && !locator.contains("= '#")) { 74 75 final String tagName = substringBefore(locator, "#"); 76 final String id = substringAfter(locator, "#"); 77 78 return By.xpath("//" + tagName + "[@id = '" + id + "']"); 79 80 } else { 81 82 return By.xpath("//" + parseContains(locator)); 83 } 84 } 85 86 private static String parseContains( 87 final String locator 88 ) { 89 90 final StringBuilder sb = new StringBuilder(); 91 92 int offset = 0; 93 94 while (true) { 95 96 final int index = locator.indexOf("contains(", offset); 97 98 if (index == -1) { 99 break; 100 } 101 102 sb.append(locator.substring(offset, index)); 103 104 final int end = locator.indexOf(")", index); 105 106 if (locator.substring(index, end).contains(",")) { 107 108 sb.append(locator.substring(index, end)); 109 110 } else { 111 112 sb.append(locator.substring(index, index + 9) + "., "); 113 114 sb.append(locator.substring(index + 9, end)); 115 } 116 117 offset = end; 118 } 119 120 sb.append(locator.substring(offset)); 121 122 return sb.toString(); 123 } 124 125 public static String locator( 126 final By by 127 ) { 128 129 checkNotNull(by, "by"); 130 131 if (by instanceof ById) { 132 133 return "#" + substringAfter(by.toString(), " "); 134 135 } else if (by instanceof ByXPath) { 136 137 return "xpath:" + substringAfter(by.toString(), " "); 138 139 } else if (by instanceof ByClassName) { 140 141 return "class:" + substringAfter(by.toString(), " "); 142 143 } else if (by instanceof ByTagName) { 144 145 return "tag:" + substringAfter(by.toString(), " "); 146 147 } else if (by instanceof ByCssSelector) { 148 149 return "css:" + substringAfter(by.toString(), " "); 150 151 } else if (by instanceof ByLinkText) { 152 153 return "link:" + substringAfter(by.toString(), " "); 154 155 } else if (by instanceof ByName) { 156 157 return "name:" + substringAfter(by.toString(), " "); 158 159 } else { 160 161 throw new NotImplementedException("by: " + by); 162 } 163 } 164 165 public static String inferLocator( 166 final WebDriver driver, 167 final WebElement element 168 ) { 169 170 checkNotNull(driver, "driver"); 171 checkNotNull(element, "element"); 172 173 final By by = DomFinder.inferBy(new WebDom(driver), new WebDomElement(element)); 174 175 final List<WebElement> elements = driver.findElements(by); 176 177 if (elements.size() != 1) { 178 179 throw new IllegalStateException("No non-ambiguous locator was found for element: " + by); 180 } 181 182 return locator(by); 183 } 184 185 public static String addQuotesForXPath( 186 final String s 187 ) { 188 189 checkNotNull(s, "s"); 190 191 final StringBuilder sb = new StringBuilder(); 192 193 for (int offset = 0;;) { 194 195 final int indexOfSingleQuote = s.indexOf('\'', offset); 196 final int indexOfDoubleQuotes = s.indexOf('"', offset); 197 198 if (indexOfSingleQuote == -1) { 199 200 if (offset == 0) { 201 202 return '\'' + s + '\''; 203 204 } else { 205 206 return sb.append(", '" + s.substring(offset) + "')").toString(); 207 } 208 209 } else if (indexOfDoubleQuotes == -1) { 210 211 if (offset == 0) { 212 213 return '"' + s + '"'; 214 215 } else { 216 217 return sb.append(", \"" + s.substring(offset) + "\")").toString(); 218 } 219 220 } else if (indexOfSingleQuote < indexOfDoubleQuotes) { 221 222 final String fragment = s.substring(offset, indexOfDoubleQuotes); 223 224 sb.append(sb.isEmpty() ? "concat(" : ", "); 225 226 sb.append("\"" + fragment + "\"").toString(); 227 228 offset = indexOfDoubleQuotes; 229 230 } else { 231 232 final String fragment = s.substring(offset, indexOfSingleQuote); 233 234 sb.append(sb.isEmpty() ? "concat(" : ", "); 235 236 sb.append("'" + fragment + "'").toString(); 237 238 offset = indexOfSingleQuote; 239 } 240 } 241 } 242 }