PageRenderTime 36ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/atlassian-visual-comparison/src/main/java/com/atlassian/selenium/visualcomparison/v2/DefaultComparer.java

https://bitbucket.org/atlassian/atlassian-selenium
Java | 226 lines | 188 code | 19 blank | 19 comment | 14 complexity | a74576824c91900035e93c570965e822 MD5 | raw file
  1. package com.atlassian.selenium.visualcomparison.v2;
  2. import com.atlassian.annotations.ExperimentalApi;
  3. import com.atlassian.selenium.visualcomparison.ScreenElement;
  4. import com.atlassian.selenium.visualcomparison.VisualComparableClient;
  5. import com.atlassian.selenium.visualcomparison.VisualComparer;
  6. import com.atlassian.selenium.visualcomparison.utils.BoundingBox;
  7. import com.atlassian.selenium.visualcomparison.utils.ScreenResolution;
  8. import com.atlassian.selenium.visualcomparison.v2.settings.PagePart;
  9. import com.atlassian.selenium.visualcomparison.v2.settings.Replacement;
  10. import com.atlassian.selenium.visualcomparison.v2.settings.Resolution;
  11. import com.google.common.base.Function;
  12. import com.google.common.collect.ImmutableList;
  13. import com.google.common.collect.ImmutableMap;
  14. import javax.annotation.Nonnull;
  15. import javax.annotation.Nullable;
  16. import javax.annotation.concurrent.Immutable;
  17. import java.io.File;
  18. import java.util.List;
  19. import java.util.Map;
  20. import static com.atlassian.selenium.visualcomparison.v2.ComparisonSettings.emptySettings;
  21. import static com.google.common.base.Preconditions.checkState;
  22. import static com.google.common.collect.Iterables.toArray;
  23. import static com.google.common.collect.Iterables.transform;
  24. import static java.util.Objects.requireNonNull;
  25. /**
  26. * Current default implementation of {@link Comparer}. This implementation delegates the visual comparison requests to
  27. * the {@link com.atlassian.selenium.visualcomparison.VisualComparer old visual comparison library}, transforming the
  28. * request, the settings and the results in the process.
  29. *
  30. * <p>
  31. * {@link BrowserEngine} is used as the underlying SPI for the browser automation framework and
  32. * {@link ComparisonSettings} as the vehicle for configuring the visual comparison, both at the
  33. * {@link #DefaultComparer(BrowserEngine, ComparisonSettings) instance} and at the
  34. * {@link #compare(String, ComparisonSettings) single comparison} level.
  35. * </p>
  36. *
  37. * <p>
  38. * NOTE: this implementation is likely to change in the future to migrate away from the old library. Depending on
  39. * implementation details of this class is highly discouraged.
  40. * </p>
  41. *
  42. * @since 2.3
  43. */
  44. @ExperimentalApi
  45. @Immutable
  46. public final class DefaultComparer implements Comparer
  47. {
  48. private final BrowserEngine engine;
  49. private final ComparisonSettings settings;
  50. public DefaultComparer(@Nonnull BrowserEngine engine, ComparisonSettings settings) {
  51. this.engine = requireNonNull(engine, "engine");
  52. this.settings = requireNonNull(settings, "settings");
  53. }
  54. @Override
  55. public void compare(@Nonnull String id)
  56. {
  57. compare(id, emptySettings());
  58. }
  59. @Override
  60. public void compare(@Nonnull String id, @Nonnull ComparisonSettings extraSettings)
  61. {
  62. requireNonNull(id, "id");
  63. requireNonNull(extraSettings, "settings");
  64. final ComparisonSettings effectiveSettings = settings.merge(extraSettings);
  65. validateSettings(effectiveSettings);
  66. VisualComparer comparer = getComparer(effectiveSettings);
  67. try
  68. {
  69. if (!comparer.uiMatches(id, effectiveSettings.getBaselineDirectory().getAbsolutePath()))
  70. {
  71. String message = "Screenshots did not match the baseline in "
  72. + effectiveSettings.getBaselineDirectory().getAbsolutePath() + ".";
  73. if (effectiveSettings.isReportingEnabled())
  74. {
  75. message += " Check reports in " + effectiveSettings.getReportingDirectory().getAbsolutePath()
  76. + " for more details.";
  77. }
  78. throw new VisualComparisonFailedException(id, message);
  79. }
  80. }
  81. catch (Exception e)
  82. {
  83. if (e instanceof VisualComparisonFailedException)
  84. {
  85. throw (VisualComparisonFailedException) e;
  86. }
  87. else
  88. {
  89. throw new VisualComparisonFailedException(id, "Error when performing comparison", e);
  90. }
  91. }
  92. }
  93. @SuppressWarnings("ConstantConditions")
  94. private void validateSettings(ComparisonSettings effectiveSettings)
  95. {
  96. checkState(effectiveSettings.getBaselineDirectory() != null, "Baseline directory must be provided");
  97. if (!effectiveSettings.getBaselineDirectory().isDirectory())
  98. {
  99. checkState(effectiveSettings.getBaselineDirectory().mkdirs(), "Unable to create baseline directory "
  100. + effectiveSettings.getBaselineDirectory().getAbsolutePath());
  101. }
  102. if (effectiveSettings.isReportingEnabled() && !effectiveSettings.getReportingDirectory().isDirectory())
  103. {
  104. checkState(effectiveSettings.getReportingDirectory().mkdirs(), "Unable to create reporting directory "
  105. + effectiveSettings.getReportingDirectory().getAbsolutePath());
  106. }
  107. }
  108. private VisualComparer getComparer(ComparisonSettings effectiveSettings)
  109. {
  110. VisualComparer comparer = new VisualComparer(new BrowserEngineComparableClient());
  111. comparer.setScreenResolutions(getResolutions(effectiveSettings));
  112. if (effectiveSettings.isReportingEnabled())
  113. {
  114. comparer.enableReportGeneration(effectiveSettings.getReportingDirectory().getAbsolutePath());
  115. }
  116. comparer.setIgnoreSingleLineDiffs(effectiveSettings.isIgnoreSingleLineDifferences());
  117. comparer.setRefreshAfterResize(effectiveSettings.isRefreshAfterResize());
  118. comparer.setIgnoreAreas(getIgnoreAreas(effectiveSettings));
  119. comparer.setUIStringReplacements(getReplacements(effectiveSettings));
  120. comparer.setWaitforJQueryTimeout(5000);
  121. return comparer;
  122. }
  123. private ScreenResolution[] getResolutions(ComparisonSettings effectiveSettings)
  124. {
  125. return toArray(transform(effectiveSettings.getResolutions(), new Function<Resolution, ScreenResolution>()
  126. {
  127. @Nullable
  128. @Override
  129. public ScreenResolution apply(Resolution input)
  130. {
  131. return new ScreenResolution(input.getWidth(), input.getHeight());
  132. }
  133. }), ScreenResolution.class);
  134. }
  135. private List<BoundingBox> getIgnoreAreas(ComparisonSettings effectiveSettings)
  136. {
  137. return ImmutableList.copyOf(transform(effectiveSettings.getIgnoredParts(), new Function<PagePart, BoundingBox>()
  138. {
  139. @Nullable
  140. @Override
  141. public BoundingBox apply(PagePart input)
  142. {
  143. return new BoundingBox(input.getLeft(), input.getTop(), input.getRight(), input.getBottom());
  144. }
  145. }));
  146. }
  147. private Map<String, String> getReplacements(ComparisonSettings effectiveSettings)
  148. {
  149. ImmutableMap.Builder<String,String> builder = ImmutableMap.builder();
  150. for (Replacement replacement : effectiveSettings.getReplacements())
  151. {
  152. builder.put(replacement.getElementId(), replacement.getHtml());
  153. }
  154. return builder.build();
  155. }
  156. private final class BrowserEngineComparableClient implements VisualComparableClient
  157. {
  158. @Override
  159. public void captureEntirePageScreenshot(String filePath)
  160. {
  161. engine.captureScreenshotTo(new File(filePath));
  162. }
  163. @Override
  164. public ScreenElement getElementAtPoint(int x, int y)
  165. {
  166. return engine.getElementAt(x, y);
  167. }
  168. @Override
  169. public Object execute(String command, Object... arguments)
  170. {
  171. return engine.executeScript(Object.class, command, arguments);
  172. }
  173. @Override
  174. public boolean resizeScreen(ScreenResolution resolution, boolean refreshAfterResize)
  175. {
  176. engine.resizeTo(new Resolution((int) resolution.getWidth(), (int) resolution.getHeight()));
  177. if (refreshAfterResize)
  178. {
  179. refreshAndWait();
  180. }
  181. return true;
  182. }
  183. @Override
  184. public void refreshAndWait()
  185. {
  186. engine.reloadPage();
  187. }
  188. @Override
  189. public boolean waitForJQuery(long waitTimeMillis)
  190. {
  191. Long jQueryActive = null;
  192. try
  193. {
  194. while (jQueryActive == null || jQueryActive != 0)
  195. {
  196. jQueryActive = engine.executeScript(Long.class, "return window.jQuery.active");
  197. Thread.sleep(100);
  198. }
  199. }
  200. catch (InterruptedException e)
  201. {
  202. return false;
  203. }
  204. return true;
  205. }
  206. }
  207. }