1 package com.atlassian.webdriver.visualcomparison;
2
3 import com.atlassian.selenium.visualcomparison.ScreenElement;
4 import com.atlassian.selenium.visualcomparison.VisualComparableClient;
5 import com.atlassian.selenium.visualcomparison.utils.ScreenResolution;
6 import com.atlassian.webdriver.AtlassianWebDriver;
7 import com.google.common.base.Function;
8 import org.openqa.selenium.By;
9 import org.openqa.selenium.Dimension;
10 import org.openqa.selenium.JavascriptExecutor;
11 import org.openqa.selenium.SearchContext;
12 import org.openqa.selenium.WebDriver;
13 import org.openqa.selenium.WebElement;
14
15 import java.io.File;
16 import java.util.ArrayList;
17 import java.util.List;
18
19
20
21
22 public class WebDriverVisualComparableClient implements VisualComparableClient
23 {
24 private final AtlassianWebDriver driver;
25 private Dimension documentSize;
26 private Dimension viewportSize;
27
28 public WebDriverVisualComparableClient(final AtlassianWebDriver driver)
29 {
30 this.driver = driver;
31 }
32
33 public void captureEntirePageScreenshot (String filePath)
34 {
35 driver.takeScreenshotTo(new File(filePath));
36 documentSize = getDimensionsFor("document");
37 viewportSize = getDimensionsFor("window");
38 }
39
40 private Dimension getDimensionsFor(String selector)
41 {
42 int x = Integer.parseInt(execute("return jQuery(" + selector + ").width();").toString());
43 int y = Integer.parseInt(execute("return jQuery(" + selector + ").height();").toString());
44 return new Dimension(x,y);
45 }
46
47 public ScreenElement getElementAtPoint(int x, int y)
48 {
49 int deltaY = documentSize.height - viewportSize.height;
50 int scrollY = Math.min(deltaY, y);
51 int relY = y - scrollY;
52
53 int deltaX = documentSize.width - viewportSize.width;
54 int scrollX = Math.min(deltaX, x);
55 int relX = x - scrollX;
56
57 execute(String.format("window.scrollTo(%d,%d)",scrollX,scrollY));
58 WebElement el = driver.findElement(atPointInDom(relX,relY));
59 return new WebDriverScreenElement(el);
60 }
61
62 private By atPointInDom(int relX, int relY)
63 {
64 final String domSel = String.format("return document.elementFromPoint(%d,%d);",relX,relY);
65 final Object o = driver.executeScript(domSel);
66
67 if (o instanceof WebElement) {
68 return new By() {
69 @Override
70 public List<WebElement> findElements(SearchContext searchContext) {
71 return new ArrayList<WebElement>() {
72 {
73 add((WebElement) o);
74 }
75 };
76 }
77 };
78 }
79
80 return null;
81 }
82
83 public void evaluate (String command)
84 {
85 execute(command);
86 }
87
88 public Object execute (String command, Object... arguments)
89 {
90 return driver.executeScript(command, arguments);
91 }
92
93 public boolean resizeScreen(ScreenResolution resolution, boolean refresh)
94 {
95 driver.getDriver().manage().window().setSize(new Dimension(resolution.width, resolution.height));
96 viewportSize = getDimensionsFor("window");
97 if (refresh)
98 {
99 refreshAndWait();
100 }
101 return true;
102 }
103
104 public void refreshAndWait ()
105 {
106
107 driver.navigate().refresh();
108 }
109
110 public boolean waitForJQuery (long waitTimeMillis)
111 {
112 try
113 {
114 driver.waitUntil(new Function<WebDriver, Boolean>() {
115 public Boolean apply(WebDriver webDriver) {
116 String jQueryActive = ((JavascriptExecutor)webDriver).executeScript("return (window.jQuery.active)").toString();
117 return (jQueryActive).equals ("0");
118 }
119 }, (int)waitTimeMillis);
120 Thread.sleep(400);
121 }
122 catch (InterruptedException e)
123 {
124 return false;
125 }
126 return true;
127 }
128
129 private class WebDriverScreenElement implements ScreenElement
130 {
131 private final WebElement element;
132
133 WebDriverScreenElement(WebElement el)
134 {
135 this.element = el;
136 }
137
138 @Override
139 public String getHtml()
140 {
141 return (String)execute("var d = document.createElement('div'); d.appendChild(arguments[0].cloneNode(true)); return d.innerHTML;", element);
142 }
143 }
144
145 }