|
| 1 | +package util.validator; |
| 2 | + |
| 3 | +import org.apache.commons.io.FileUtils; |
| 4 | +import org.json.simple.JSONArray; |
| 5 | +import org.json.simple.JSONObject; |
| 6 | +import org.openqa.selenium.*; |
| 7 | +import util.driver.PageValidator; |
| 8 | + |
| 9 | +import javax.imageio.ImageIO; |
| 10 | +import java.awt.*; |
| 11 | +import java.awt.image.BufferedImage; |
| 12 | +import java.io.File; |
| 13 | +import java.io.IOException; |
| 14 | +import java.util.ArrayList; |
| 15 | +import java.util.List; |
| 16 | + |
| 17 | +public class ResponsiveValidator implements Validator { |
| 18 | + |
| 19 | + private static final int MIN_MARGIN = -10000; |
| 20 | + private WebDriver driver; |
| 21 | + private String rootElementReadableName; |
| 22 | + private WebElement rootElement; |
| 23 | + private WebElement leftElement; |
| 24 | + private WebElement rightElement; |
| 25 | + private WebElement aboveElement; |
| 26 | + private WebElement belowElement; |
| 27 | + private WebElement containerElement; |
| 28 | + private List<WebElement> overlapElements = new ArrayList<>(); |
| 29 | + private int minWidth, |
| 30 | + maxWidth, |
| 31 | + minHeight, |
| 32 | + maxHeight, |
| 33 | + minTopMargin, |
| 34 | + minRightMargin, |
| 35 | + minBottomMargin, |
| 36 | + minLeftMargin, |
| 37 | + maxTopMargin, |
| 38 | + maxRightMargin, |
| 39 | + maxBottomMargin, |
| 40 | + maxLeftMargin = MIN_MARGIN; |
| 41 | + private int xRoot; |
| 42 | + private int yRoot; |
| 43 | + private int widthRoot; |
| 44 | + private int heightRoot; |
| 45 | + private boolean drawMap = false; |
| 46 | + private int pageWidth; |
| 47 | + private int pageHeight; |
| 48 | + private int elementRightMargin; |
| 49 | + private int elementBottomMargin; |
| 50 | + |
| 51 | + public ResponsiveValidator(WebDriver driver) { |
| 52 | + this.driver = driver; |
| 53 | + } |
| 54 | + |
| 55 | + @Override |
| 56 | + public ResponsiveValidator rootElement(WebElement element, String readableNameOfElement) { |
| 57 | + rootElement = element; |
| 58 | + rootElementReadableName = readableNameOfElement; |
| 59 | + xRoot = rootElement.getLocation().getX(); |
| 60 | + yRoot = rootElement.getLocation().getY(); |
| 61 | + widthRoot = rootElement.getSize().getWidth(); |
| 62 | + heightRoot = rootElement.getSize().getHeight(); |
| 63 | + pageWidth = driver.manage().window().getSize().getWidth(); |
| 64 | + pageHeight = driver.manage().window().getSize().getHeight(); |
| 65 | + elementRightMargin = pageWidth - xRoot + widthRoot; |
| 66 | + elementBottomMargin = pageHeight - yRoot + heightRoot; |
| 67 | + return this; |
| 68 | + } |
| 69 | + |
| 70 | + @Override |
| 71 | + public ResponsiveValidator leftElement(WebElement element) { |
| 72 | + leftElement = element; |
| 73 | + return this; |
| 74 | + } |
| 75 | + |
| 76 | + @Override |
| 77 | + public ResponsiveValidator rightElement(WebElement element) { |
| 78 | + rightElement = element; |
| 79 | + return this; |
| 80 | + } |
| 81 | + |
| 82 | + @Override |
| 83 | + public ResponsiveValidator aboveElement(WebElement element) { |
| 84 | + aboveElement = element; |
| 85 | + return this; |
| 86 | + } |
| 87 | + |
| 88 | + @Override |
| 89 | + public ResponsiveValidator belowElement(WebElement element) { |
| 90 | + belowElement = element; |
| 91 | + return this; |
| 92 | + } |
| 93 | + |
| 94 | + @Override |
| 95 | + public ResponsiveValidator inside(WebElement element) { |
| 96 | + containerElement = element; |
| 97 | + return this; |
| 98 | + } |
| 99 | + |
| 100 | + @Override |
| 101 | + public ResponsiveValidator notOverlapWith(WebElement element) { |
| 102 | + overlapElements.add(element); |
| 103 | + throw new UnsupportedCommandException(); |
| 104 | + } |
| 105 | + |
| 106 | + @Override |
| 107 | + public ResponsiveValidator minWidth(int width) { |
| 108 | + minWidth = width; |
| 109 | + return this; |
| 110 | + } |
| 111 | + |
| 112 | + @Override |
| 113 | + public ResponsiveValidator maxWidth(int width) { |
| 114 | + maxWidth = width; |
| 115 | + return this; |
| 116 | + } |
| 117 | + |
| 118 | + @Override |
| 119 | + public ResponsiveValidator minHeight(int height) { |
| 120 | + minHeight = height; |
| 121 | + return this; |
| 122 | + } |
| 123 | + |
| 124 | + @Override |
| 125 | + public ResponsiveValidator maxHeight(int height) { |
| 126 | + maxHeight = height; |
| 127 | + return this; |
| 128 | + } |
| 129 | + |
| 130 | + @Override |
| 131 | + public ResponsiveValidator minMargin(int top, int right, int bottom, int left) { |
| 132 | + minTopMargin = top; |
| 133 | + minRightMargin = right; |
| 134 | + minBottomMargin = bottom; |
| 135 | + minLeftMargin = left; |
| 136 | + return this; |
| 137 | + } |
| 138 | + |
| 139 | + @Override |
| 140 | + public ResponsiveValidator maxMargin(int top, int right, int bottom, int left) { |
| 141 | + maxTopMargin = top; |
| 142 | + maxRightMargin = right; |
| 143 | + maxBottomMargin = bottom; |
| 144 | + maxLeftMargin = left; |
| 145 | + return this; |
| 146 | + } |
| 147 | + |
| 148 | + @Override |
| 149 | + public ResponsiveValidator drawMap() { |
| 150 | + drawMap = true; |
| 151 | + return this; |
| 152 | + } |
| 153 | + |
| 154 | + @Override |
| 155 | + public JSONObject validate() { |
| 156 | + JSONObject json = new JSONObject(); |
| 157 | + json.put("error", false); |
| 158 | + |
| 159 | + if (rootElement != null) { |
| 160 | + JSONArray errorMessage = new JSONArray(); |
| 161 | + |
| 162 | + BufferedImage img = null; |
| 163 | + File map = null; |
| 164 | + Graphics g = null; |
| 165 | + |
| 166 | + if (drawMap) { |
| 167 | + try { |
| 168 | + map = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE); |
| 169 | + img = ImageIO.read(map); |
| 170 | + } catch (Exception ignored) { |
| 171 | + } |
| 172 | + |
| 173 | + g = img.createGraphics(); |
| 174 | + } |
| 175 | + |
| 176 | + if (leftElement != null) { |
| 177 | + List<WebElement> elements = new ArrayList<>(); |
| 178 | + elements.add(leftElement); |
| 179 | + elements.add(rootElement); |
| 180 | + |
| 181 | + if (!PageValidator.elementsAreAlignedHorizontally(elements)) { |
| 182 | + errorMessage.add("Left element aligned not properly"); |
| 183 | + if (drawMap) { |
| 184 | + drawElementRect(g, Color.RED, leftElement); |
| 185 | + } |
| 186 | + } |
| 187 | + } |
| 188 | + if (rightElement != null) { |
| 189 | + List<WebElement> elements = new ArrayList<>(); |
| 190 | + elements.add(rootElement); |
| 191 | + elements.add(rightElement); |
| 192 | + |
| 193 | + if (!PageValidator.elementsAreAlignedHorizontally(elements)) { |
| 194 | + errorMessage.add("Right element aligned not properly"); |
| 195 | + if (drawMap) { |
| 196 | + drawElementRect(g, Color.RED, rightElement); |
| 197 | + } |
| 198 | + } |
| 199 | + } |
| 200 | + if (aboveElement != null) { |
| 201 | + List<WebElement> elements = new ArrayList<>(); |
| 202 | + elements.add(aboveElement); |
| 203 | + elements.add(rootElement); |
| 204 | + |
| 205 | + if (!PageValidator.elementsAreAlignedVertically(elements)) { |
| 206 | + errorMessage.add("Above element aligned not properly"); |
| 207 | + if (drawMap) { |
| 208 | + drawElementRect(g, Color.RED, aboveElement); |
| 209 | + } |
| 210 | + } |
| 211 | + } |
| 212 | + if (belowElement != null) { |
| 213 | + List<WebElement> elements = new ArrayList<>(); |
| 214 | + elements.add(rootElement); |
| 215 | + elements.add(belowElement); |
| 216 | + |
| 217 | + if (!PageValidator.elementsAreAlignedVertically(elements)) { |
| 218 | + errorMessage.add("Below element aligned not properly"); |
| 219 | + if (drawMap) { |
| 220 | + drawElementRect(g, Color.RED, belowElement); |
| 221 | + } |
| 222 | + } |
| 223 | + } |
| 224 | + if (containerElement != null) { |
| 225 | + float xContainer = containerElement.getLocation().getX(); |
| 226 | + float yContainer = containerElement.getLocation().getY(); |
| 227 | + float widthContainer = containerElement.getSize().getWidth(); |
| 228 | + float heightContainer = containerElement.getSize().getHeight(); |
| 229 | + |
| 230 | + if (xRoot < xContainer || yRoot < yContainer || (xRoot + widthRoot) > (xContainer + widthContainer) || (yRoot + heightRoot) > (yContainer + heightContainer)) { |
| 231 | + errorMessage.add("Element \"" + rootElementReadableName + "\" is not inside of container"); |
| 232 | + if (drawMap) { |
| 233 | + drawElementRect(g, Color.RED, containerElement); |
| 234 | + drawElementRect(g, Color.GREEN, rootElement); |
| 235 | + } |
| 236 | + } |
| 237 | + } |
| 238 | + if (minWidth > MIN_MARGIN) { |
| 239 | + if (widthRoot < minWidth) { |
| 240 | + errorMessage.add(String.format("Expected min width of element \"" + rootElementReadableName + "\" is: %spx. Actual width is: %spx", minWidth, widthRoot)); |
| 241 | + if (drawMap) { |
| 242 | + drawElementRect(g, Color.RED, rootElement); |
| 243 | + } |
| 244 | + } |
| 245 | + } |
| 246 | + if (maxWidth > MIN_MARGIN) { |
| 247 | + if (widthRoot > maxWidth) { |
| 248 | + errorMessage.add(String.format("Expected max width of element \"" + rootElementReadableName + "\" is: %spx. Actual width is: %spx", maxWidth, widthRoot)); |
| 249 | + if (drawMap) { |
| 250 | + drawElementRect(g, Color.RED, rootElement); |
| 251 | + } |
| 252 | + } |
| 253 | + } |
| 254 | + if (minHeight > MIN_MARGIN) { |
| 255 | + if (heightRoot < minHeight) { |
| 256 | + errorMessage.add(String.format("Expected min height of element \"" + rootElementReadableName + "\" is: %spx. Actual height is: %spx", minHeight, heightRoot)); |
| 257 | + if (drawMap) { |
| 258 | + drawElementRect(g, Color.RED, rootElement); |
| 259 | + } |
| 260 | + } |
| 261 | + } |
| 262 | + if (maxHeight > MIN_MARGIN) { |
| 263 | + if (heightRoot > maxHeight) { |
| 264 | + errorMessage.add(String.format("Expected max height of element \"" + rootElementReadableName + "\" is: %spx. Actual height is: %spx", maxHeight, heightRoot)); |
| 265 | + if (drawMap) { |
| 266 | + drawElementRect(g, Color.RED, rootElement); |
| 267 | + } |
| 268 | + } |
| 269 | + } |
| 270 | + if (minTopMargin > MIN_MARGIN && minRightMargin > MIN_MARGIN && minBottomMargin > MIN_MARGIN && minLeftMargin > MIN_MARGIN) { |
| 271 | + |
| 272 | + if (xRoot < minLeftMargin){ |
| 273 | + errorMessage.add(String.format("Expected min left margin of element \"" + rootElementReadableName + "\" is: %spx. Actual left margin is: %spx", minLeftMargin, xRoot)); |
| 274 | + } |
| 275 | + if (yRoot < minTopMargin){ |
| 276 | + errorMessage.add(String.format("Expected min top margin of element \"" + rootElementReadableName + "\" is: %spx. Actual top margin is: %spx", minTopMargin, yRoot)); |
| 277 | + } |
| 278 | + if (elementRightMargin < minRightMargin){ |
| 279 | + errorMessage.add(String.format("Expected min top margin of element \"" + rootElementReadableName + "\" is: %spx. Actual right margin is: %spx", minRightMargin, elementRightMargin)); |
| 280 | + } |
| 281 | + if (elementBottomMargin < minBottomMargin){ |
| 282 | + errorMessage.add(String.format("Expected min bottom margin of element \"" + rootElementReadableName + "\" is: %spx. Actual bottom margin is: %spx", minBottomMargin, elementBottomMargin)); |
| 283 | + } |
| 284 | + } |
| 285 | + if (maxTopMargin > MIN_MARGIN && maxRightMargin > MIN_MARGIN && maxBottomMargin > MIN_MARGIN && maxLeftMargin > MIN_MARGIN) { |
| 286 | + if (xRoot > maxLeftMargin){ |
| 287 | + errorMessage.add(String.format("Expected max left margin of element \"" + rootElementReadableName + "\" is: %spx. Actual left margin is: %spx", maxLeftMargin, xRoot)); |
| 288 | + } |
| 289 | + if (yRoot > maxTopMargin){ |
| 290 | + errorMessage.add(String.format("Expected max top margin of element \"" + rootElementReadableName + "\" is: %spx. Actual top margin is: %spx", maxTopMargin, yRoot)); |
| 291 | + } |
| 292 | + if (elementRightMargin > maxRightMargin){ |
| 293 | + errorMessage.add(String.format("Expected max right margin of element \"" + rootElementReadableName + "\" is: %spx. Actual right margin is: %spx", maxRightMargin, elementRightMargin)); |
| 294 | + } |
| 295 | + if (elementBottomMargin > maxBottomMargin){ |
| 296 | + errorMessage.add(String.format("Expected max bottom margin of element \"" + rootElementReadableName + "\" is: %spx. Actual bottom margin is: %spx", maxBottomMargin, elementBottomMargin)); |
| 297 | + } |
| 298 | + } |
| 299 | + |
| 300 | + if (!errorMessage.isEmpty()) { |
| 301 | + json.put("error", true); |
| 302 | + json.put("reason", errorMessage); |
| 303 | + } |
| 304 | + |
| 305 | + if (drawMap) { |
| 306 | + if (img != null) { |
| 307 | + try { |
| 308 | + g.setColor(Color.WHITE); |
| 309 | + ImageIO.write(img, "png", map); |
| 310 | + File file = new File("target/" + map.getName()); |
| 311 | + FileUtils.copyFile(map, file); |
| 312 | + } catch (IOException e) { |
| 313 | + e.printStackTrace(); |
| 314 | + } |
| 315 | + } |
| 316 | + } |
| 317 | + } else { |
| 318 | + json.put("error", true); |
| 319 | + json.put("reason", "Set root web element"); |
| 320 | + } |
| 321 | + |
| 322 | + return json; |
| 323 | + } |
| 324 | + |
| 325 | + private void drawElementRect(Graphics g, Color color, WebElement element) { |
| 326 | + g.setColor(color); |
| 327 | + g.drawRect(element.getLocation().x, element.getLocation().y, element.getSize().width, element.getSize().height); |
| 328 | + } |
| 329 | + |
| 330 | +} |
0 commit comments