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