Skip to content

Commit 607c032

Browse files
authored
Make scaling obligatory for full screenshot, rework getScreenshot method, remove from constructor parameters. Add more test actions (#124)
1 parent ade1afe commit 607c032

File tree

3 files changed

+25
-40
lines changed

3 files changed

+25
-40
lines changed

src/main/java/aquality/selenium/elements/interfaces/ByImage.java

Lines changed: 17 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@
1818
/**
1919
* Locator to search elements by image.
2020
* Takes screenshot and finds match using openCV.
21+
* Performs screenshot scaling if devicePixelRatio != 1.
2122
* Then finds elements by coordinates using javascript.
2223
*/
2324
public class ByImage extends By {
2425
private static boolean wasLibraryLoaded = false;
2526
private final Mat template;
26-
private final boolean doScaling;
2727

2828
private static void loadLibrary() {
2929
if (!wasLibraryLoaded) {
@@ -39,19 +39,8 @@ private static void loadLibrary() {
3939
* @param file image file to locate element by.
4040
*/
4141
public ByImage(File file) {
42-
this(file, false);
43-
}
44-
45-
/**
46-
* Constructor accepting image file.
47-
*
48-
* @param file image file to locate element by.
49-
* @param doScaling perform screenshot scaling if devicePixelRatio != 1
50-
*/
51-
public ByImage(File file, boolean doScaling) {
5242
loadLibrary();
5343
this.template = Imgcodecs.imread(file.getAbsolutePath(), Imgcodecs.IMREAD_UNCHANGED);
54-
this.doScaling = doScaling;
5544
}
5645

5746
/**
@@ -60,19 +49,8 @@ public ByImage(File file, boolean doScaling) {
6049
* @param bytes image bytes to locate element by.
6150
*/
6251
public ByImage(byte[] bytes) {
63-
this(bytes, false);
64-
}
65-
66-
/**
67-
* Constructor accepting image file.
68-
*
69-
* @param bytes image bytes to locate element by.
70-
* @param doScaling perform screenshot scaling if devicePixelRatio != 1
71-
*/
72-
public ByImage(byte[] bytes, boolean doScaling) {
7352
loadLibrary();
7453
this.template = Imgcodecs.imdecode(new MatOfByte(bytes), Imgcodecs.IMREAD_UNCHANGED);
75-
this.doScaling = doScaling;
7654
}
7755

7856
@Override
@@ -82,21 +60,14 @@ public String toString() {
8260

8361
@Override
8462
public List<WebElement> findElements(SearchContext context) {
85-
byte[] screenshotBytes = getScreenshot(context);
86-
Mat source = Imgcodecs.imdecode(new MatOfByte(screenshotBytes), Imgcodecs.IMREAD_UNCHANGED);
87-
long devicePixelRatio = (long) AqualityServices.getBrowser().executeScript(JavaScript.GET_DEVICE_PIXEL_RATIO);
88-
if (devicePixelRatio != 1 && doScaling) {
89-
int scaledWidth = (int) (source.width() / devicePixelRatio);
90-
int scaledHeight = (int) (source.height() / devicePixelRatio);
91-
Imgproc.resize(source, source, new Size(scaledWidth, scaledHeight), 0, 0, Imgproc.INTER_AREA);
92-
}
63+
Mat source = getScreenshot(context);
9364
Mat result = new Mat();
9465
Imgproc.matchTemplate(source, template, result, Imgproc.TM_CCOEFF_NORMED);
9566

9667
float threshold = 1 - AqualityServices.getConfiguration().getVisualizationConfiguration().getDefaultThreshold();
9768
Core.MinMaxLocResult minMaxLoc = Core.minMaxLoc(result);
9869

99-
int matchCounter = (result.width() - template.width() + 1) * (result.height() - template.height() + 1);
70+
int matchCounter = Math.abs((result.width() - template.width() + 1) * (result.height() - template.height() + 1));
10071
List<Point> matchLocations = new ArrayList<>();
10172
while (matchCounter > 0 && minMaxLoc.maxVal >= threshold) {
10273
matchCounter--;
@@ -149,11 +120,20 @@ protected static double distanceToPoint(Point matchLocation, WebElement element)
149120
* Takes screenshot from searchContext if supported, or from browser.
150121
*
151122
* @param context search context for element location.
152-
* @return captured screenshot as byte array.
123+
* @return captured screenshot as Mat object.
153124
*/
154-
protected byte[] getScreenshot(SearchContext context) {
155-
return !(context instanceof TakesScreenshot)
156-
? AqualityServices.getBrowser().getScreenshot()
157-
: ((TakesScreenshot) context).getScreenshotAs(OutputType.BYTES);
125+
protected Mat getScreenshot(SearchContext context) {
126+
byte[] screenshotBytes = context instanceof TakesScreenshot
127+
? ((TakesScreenshot) context).getScreenshotAs(OutputType.BYTES)
128+
: AqualityServices.getBrowser().getScreenshot();
129+
boolean isBrowserScreenshot = context instanceof WebDriver || !(context instanceof TakesScreenshot);
130+
Mat source = Imgcodecs.imdecode(new MatOfByte(screenshotBytes), Imgcodecs.IMREAD_UNCHANGED);
131+
long devicePixelRatio = (long) AqualityServices.getBrowser().executeScript(JavaScript.GET_DEVICE_PIXEL_RATIO);
132+
if (devicePixelRatio != 1 && isBrowserScreenshot) {
133+
int scaledWidth = (int) (source.width() / devicePixelRatio);
134+
int scaledHeight = (int) (source.height() / devicePixelRatio);
135+
Imgproc.resize(source, source, new Size(scaledWidth, scaledHeight), 0, 0, Imgproc.INTER_AREA);
136+
}
137+
return source;
158138
}
159139
}

src/test/java/tests/integration/LocatorTests.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import aquality.selenium.elements.interfaces.ILabel;
66
import automationpractice.forms.ChallengingDomForm;
77
import org.openqa.selenium.By;
8+
import org.openqa.selenium.OutputType;
89
import org.openqa.selenium.WebElement;
910
import org.openqa.selenium.support.locators.RelativeLocator;
1011
import org.testng.Assert;
@@ -38,14 +39,18 @@ public void testByImageLocator() {
3839
Assert.assertFalse(form.getLabelByImage().state().isDisplayed(), "Should be impossible to find element on page by image when it is absent");
3940
getBrowser().goTo(form.getUrl());
4041
Assert.assertTrue(form.getLabelByImage().state().isDisplayed(), "Should be possible to find element on page by image");
42+
Assert.assertEquals(form.getLabelByImage().getElement().getTagName(), "img", "Correct element must be found");
4143

4244
List<ILabel> childLabels = form.getChildLabelsByImage();
4345
List<ILabel> docLabels = form.getLabelsByImage();
4446
Assert.assertTrue(docLabels.size() > 1, "List of elements should be possible to find by image");
4547
Assert.assertEquals(docLabels.size(), childLabels.size(), "Should be possible to find child elements by image with the same count");
4648

47-
ILabel screen = AqualityServices.getElementFactory().getLabel(new ByImage(AqualityServices.getBrowser().getScreenshot()), "full screen");
48-
Assert.assertTrue(screen.state().waitForDisplayed(), "Should be possible to find element by full page screenshot");
49+
ILabel documentByTag = AqualityServices.getElementFactory().getLabel(By.tagName("body"), "document by tag");
50+
ILabel documentByImage = AqualityServices.getElementFactory().getLabel(new ByImage(documentByTag.getElement().getScreenshotAs(OutputType.BYTES)),
51+
"full screen");
52+
Assert.assertTrue(documentByImage.state().isDisplayed(), "Should be possible to find element by document screenshot");
53+
Assert.assertEquals(documentByImage.getElement().getTagName(), "body", "Correct element must be found");
4954
}
5055

5156
@Test

src/test/java/theinternet/forms/BrokenImagesForm.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import java.util.List;
99

1010
public class BrokenImagesForm extends TheInternetForm {
11-
private final By imageLocator = new ByImage(FileUtil.getResourceFileByName("brokenImage.png"), true);
11+
private final By imageLocator = new ByImage(FileUtil.getResourceFileByName("brokenImage.png"));
1212

1313
public BrokenImagesForm(){
1414
super(By.id("content"), "Broken Images form");

0 commit comments

Comments
 (0)