diff --git a/bellatrix.android/src/main/java/solutions/bellatrix/android/components/AndroidComponent.java b/bellatrix.android/src/main/java/solutions/bellatrix/android/components/AndroidComponent.java index 9a34321d..c1580d81 100644 --- a/bellatrix.android/src/main/java/solutions/bellatrix/android/components/AndroidComponent.java +++ b/bellatrix.android/src/main/java/solutions/bellatrix/android/components/AndroidComponent.java @@ -22,10 +22,7 @@ import org.openqa.selenium.interactions.Actions; import solutions.bellatrix.android.components.contracts.Component; import solutions.bellatrix.android.configuration.AndroidSettings; -import solutions.bellatrix.android.findstrategies.FindStrategy; -import solutions.bellatrix.android.findstrategies.NameFindStrategy; -import solutions.bellatrix.android.findstrategies.TagFindStrategy; -import solutions.bellatrix.android.findstrategies.XPathFindStrategy; +import solutions.bellatrix.android.findstrategies.*; import solutions.bellatrix.android.infrastructure.DriverService; import solutions.bellatrix.android.services.AppService; import solutions.bellatrix.android.services.ComponentCreateService; @@ -36,6 +33,7 @@ import solutions.bellatrix.core.utilities.DebugInformation; import solutions.bellatrix.core.utilities.InstanceFactory; import solutions.bellatrix.core.utilities.Log; +import solutions.bellatrix.plugins.opencv.Base64Encodable; import java.awt.Dimension; import java.util.ArrayList; @@ -221,6 +219,10 @@ public return createAll(componentClass, findStrategy); } + public TComponent createByImage(Class componentClass, Base64Encodable encodedImage) { + return create(componentClass, new ImageBase64FindStrategy(encodedImage)); + } + public TComponent createByXPath(Class componentClass, String xpath) { return create(componentClass, new XPathFindStrategy(xpath)); } @@ -237,6 +239,11 @@ public List createAllByName(Cl return createAll(componentClass, new NameFindStrategy(name)); } + public List createAllByImage(Class componentClass, Base64Encodable encodedImage) { + return createAll(componentClass, new ImageBase64FindStrategy(encodedImage)); + } + + public List createAllByXPath(Class componentClass, String xpath) { return createAll(componentClass, new XPathFindStrategy(xpath)); } diff --git a/bellatrix.android/src/main/java/solutions/bellatrix/android/configuration/AndroidSettings.java b/bellatrix.android/src/main/java/solutions/bellatrix/android/configuration/AndroidSettings.java index de101408..c2f1f156 100644 --- a/bellatrix.android/src/main/java/solutions/bellatrix/android/configuration/AndroidSettings.java +++ b/bellatrix.android/src/main/java/solutions/bellatrix/android/configuration/AndroidSettings.java @@ -41,4 +41,6 @@ public class AndroidSettings { @Getter @Setter private Boolean videosOnFailEnabled; @Getter @Setter private String videosSaveLocation; + + @Getter @Setter private Boolean allowImageFindStrategies; } diff --git a/bellatrix.android/src/main/java/solutions/bellatrix/android/findstrategies/ImageBase64FindStrategy.java b/bellatrix.android/src/main/java/solutions/bellatrix/android/findstrategies/ImageBase64FindStrategy.java new file mode 100644 index 00000000..fd1a21a4 --- /dev/null +++ b/bellatrix.android/src/main/java/solutions/bellatrix/android/findstrategies/ImageBase64FindStrategy.java @@ -0,0 +1,54 @@ +/* + * Copyright 2025 Automate The Planet Ltd. + * Author: Miriyam Kyoseva + * Licensed under the Apache License, Version 2.0 (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package solutions.bellatrix.android.findstrategies; + +import io.appium.java_client.AppiumBy; +import io.appium.java_client.android.AndroidDriver; +import org.openqa.selenium.WebElement; +import solutions.bellatrix.plugins.opencv.Base64Encodable; + +import java.util.List; + +public class ImageBase64FindStrategy extends FindStrategy { + private final Base64Encodable encodedImage; + public ImageBase64FindStrategy(Base64Encodable encodedImage) { + super(encodedImage.getImageName()); + this.encodedImage = encodedImage; + } + + @Override + public WebElement findElement(AndroidDriver driver) { + return driver.findElement(AppiumBy.image(encodedImage.getBase64Image())); + } + + @Override + public List findAllElements(AndroidDriver driver) { + return driver.findElements(AppiumBy.image(encodedImage.getBase64Image())); + } + + @Override + public WebElement findElement(WebElement element) { + return element.findElement(AppiumBy.image(encodedImage.getBase64Image())); + } + + @Override + public List findAllElements(WebElement element) { + return element.findElements(AppiumBy.image(encodedImage.getBase64Image())); + } + + @Override + public String toString() { + return String.format("image = %s", getValue()); + } +} diff --git a/bellatrix.android/src/main/java/solutions/bellatrix/android/infrastructure/DriverService.java b/bellatrix.android/src/main/java/solutions/bellatrix/android/infrastructure/DriverService.java index 3bbfb124..fcec337b 100644 --- a/bellatrix.android/src/main/java/solutions/bellatrix/android/infrastructure/DriverService.java +++ b/bellatrix.android/src/main/java/solutions/bellatrix/android/infrastructure/DriverService.java @@ -107,6 +107,9 @@ private static AndroidDriver initializeDriverGridMode(GridSettings gridSettings, options.put("name", testName); caps.setCapability(gridSettings.getOptionsName(), options); + if (ConfigurationService.get(AndroidSettings.class).getAllowImageFindStrategies()) + caps.setCapability("use-plugins", "images"); + AndroidDriver driver = null; try { driver = new AndroidDriver(new URL(gridSettings.getUrl()), caps); @@ -134,6 +137,9 @@ private static AndroidDriver initializeDriverRegularMode(String serviceUrl) { caps.setAppActivity(getAppConfiguration().getAppActivity()); } + if (ConfigurationService.get(AndroidSettings.class).getAllowImageFindStrategies()) + caps.setCapability("use-plugins", "images"); + addDriverConfigOptions(caps); addCustomDriverOptions(caps); var driver = new AndroidDriver(new URL(serviceUrl), caps); diff --git a/bellatrix.android/src/main/java/solutions/bellatrix/android/infrastructure/MobileScreenshotPlugin.java b/bellatrix.android/src/main/java/solutions/bellatrix/android/infrastructure/MobileScreenshotPlugin.java index 61250771..f4b6bfa0 100644 --- a/bellatrix.android/src/main/java/solutions/bellatrix/android/infrastructure/MobileScreenshotPlugin.java +++ b/bellatrix.android/src/main/java/solutions/bellatrix/android/infrastructure/MobileScreenshotPlugin.java @@ -13,8 +13,6 @@ package solutions.bellatrix.android.infrastructure; -import lombok.SneakyThrows; -import org.apache.commons.io.FileUtils; import org.openqa.selenium.OutputType; import org.openqa.selenium.TakesScreenshot; import plugins.screenshots.ScreenshotPlugin; @@ -35,7 +33,11 @@ public MobileScreenshotPlugin() { } @Override - @SneakyThrows + public byte[] takeScreenshot() { + return ((TakesScreenshot)DriverService.getWrappedAndroidDriver()).getScreenshotAs(OutputType.BYTES); + } + + @Override public String takeScreenshot(String name) { var screenshotSaveDir = getOutputFolder(); var filename = getUniqueFileName(name); @@ -57,7 +59,6 @@ public String takeScreenshot(String name) { } @Override - @SneakyThrows public String takeScreenshot(String screenshotSaveDir, String filename) { var screenshot = ((TakesScreenshot)DriverService.getWrappedAndroidDriver()).getScreenshotAs(OutputType.BASE64); diff --git a/bellatrix.android/src/main/java/solutions/bellatrix/android/services/ComponentCreateService.java b/bellatrix.android/src/main/java/solutions/bellatrix/android/services/ComponentCreateService.java index e8ebb4f6..c1c49508 100644 --- a/bellatrix.android/src/main/java/solutions/bellatrix/android/services/ComponentCreateService.java +++ b/bellatrix.android/src/main/java/solutions/bellatrix/android/services/ComponentCreateService.java @@ -17,6 +17,7 @@ import solutions.bellatrix.android.findstrategies.*; import solutions.bellatrix.android.infrastructure.DriverService; import solutions.bellatrix.core.utilities.InstanceFactory; +import solutions.bellatrix.plugins.opencv.Base64Encodable; import java.util.ArrayList; import java.util.List; @@ -32,6 +33,10 @@ public return allBy(componentClass, findStrategy); } + public TComponent byImage(Class componentClass, Base64Encodable encodedImage) { + return by(componentClass, new ImageBase64FindStrategy(encodedImage)); + } + public TComponent byId(Class componentClass, String id) { return by(componentClass, new IdFindStrategy(id)); } @@ -76,6 +81,10 @@ public TComponent byIdContaining(Class List allByImage(Class componentClass, Base64Encodable encodedImage) { + return allBy(componentClass, new ImageBase64FindStrategy(encodedImage)); + } + public List allById(Class componentClass, String automationId) { return allBy(componentClass, new IdFindStrategy(automationId)); } diff --git a/bellatrix.desktop/pom.xml b/bellatrix.desktop/pom.xml index 759eff0a..198883f7 100644 --- a/bellatrix.desktop/pom.xml +++ b/bellatrix.desktop/pom.xml @@ -48,5 +48,11 @@ 1.0 compile + + solutions.bellatrix + bellatrix.plugins.opencv + 1.0 + compile + \ No newline at end of file diff --git a/bellatrix.desktop/src/main/java/solutions/bellatrix/desktop/components/DesktopComponent.java b/bellatrix.desktop/src/main/java/solutions/bellatrix/desktop/components/DesktopComponent.java index 928aeb88..7a07911a 100644 --- a/bellatrix.desktop/src/main/java/solutions/bellatrix/desktop/components/DesktopComponent.java +++ b/bellatrix.desktop/src/main/java/solutions/bellatrix/desktop/components/DesktopComponent.java @@ -34,6 +34,7 @@ import solutions.bellatrix.desktop.services.ComponentCreateService; import solutions.bellatrix.desktop.services.ComponentWaitService; import solutions.bellatrix.desktop.waitstrategies.*; +import solutions.bellatrix.plugins.opencv.Base64Encodable; import java.awt.Dimension; import java.util.ArrayList; @@ -247,6 +248,11 @@ public TComponent createByAutomationId(Cla return create(componentClass, new AutomationIdFindStrategy(automationId)); } + public TComponent createByImage(Class componentClass, Base64Encodable encodedImage) { + return create(componentClass, new ImageBase64FindStrategy(encodedImage)); + } + + public List createAllByAccessibilityId(Class componentClass, String accessibilityId) { return createAll(componentClass, new AccessibilityIdFindStrategy(accessibilityId)); } @@ -275,6 +281,10 @@ public List createAllByIdConta return createAll(componentClass, new IdContainingFindStrategy(idContaining)); } + public List createAllByImage(Class componentClass, Base64Encodable encodedImage) { + return createAll(componentClass, new ImageBase64FindStrategy(encodedImage)); + } + protected TComponent create(Class componentClass, TFindStrategy findStrategy) { CREATING_ELEMENT.broadcast(new ComponentActionEventArgs(this)); findElement(); diff --git a/bellatrix.desktop/src/main/java/solutions/bellatrix/desktop/configuration/DesktopSettings.java b/bellatrix.desktop/src/main/java/solutions/bellatrix/desktop/configuration/DesktopSettings.java index 3575b6dd..458cffc8 100644 --- a/bellatrix.desktop/src/main/java/solutions/bellatrix/desktop/configuration/DesktopSettings.java +++ b/bellatrix.desktop/src/main/java/solutions/bellatrix/desktop/configuration/DesktopSettings.java @@ -47,4 +47,6 @@ public class DesktopSettings { @Getter @Setter private Boolean videosOnFailEnabled; @Getter @Setter private String videosSaveLocation; + + @Getter @Setter private Boolean allowImageFindStrategies; } diff --git a/bellatrix.desktop/src/main/java/solutions/bellatrix/desktop/findstrategies/ImageBase64FindStrategy.java b/bellatrix.desktop/src/main/java/solutions/bellatrix/desktop/findstrategies/ImageBase64FindStrategy.java new file mode 100644 index 00000000..b0637dec --- /dev/null +++ b/bellatrix.desktop/src/main/java/solutions/bellatrix/desktop/findstrategies/ImageBase64FindStrategy.java @@ -0,0 +1,54 @@ +/* + * Copyright 2025 Automate The Planet Ltd. + * Author: Miriyam Kyoseva + * Licensed under the Apache License, Version 2.0 (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package solutions.bellatrix.desktop.findstrategies; + +import io.appium.java_client.AppiumBy; +import io.appium.java_client.windows.WindowsDriver; +import org.openqa.selenium.WebElement; +import solutions.bellatrix.plugins.opencv.Base64Encodable; + +import java.util.List; + +public class ImageBase64FindStrategy extends FindStrategy { + private final Base64Encodable encodedImage; + public ImageBase64FindStrategy(Base64Encodable encodedImage) { + super(encodedImage.getImageName()); + this.encodedImage = encodedImage; + } + + @Override + public WebElement findElement(WindowsDriver driver) { + return driver.findElement(AppiumBy.image(encodedImage.getBase64Image())); + } + + @Override + public List findAllElements(WindowsDriver driver) { + return driver.findElements(AppiumBy.image(encodedImage.getBase64Image())); + } + + @Override + public WebElement findElement(WebElement element) { + return element.findElement(AppiumBy.image(encodedImage.getBase64Image())); + } + + @Override + public List findAllElements(WebElement element) { + return element.findElements(AppiumBy.image(encodedImage.getBase64Image())); + } + + @Override + public String toString() { + return String.format("image = %s", getValue()); + } +} diff --git a/bellatrix.desktop/src/main/java/solutions/bellatrix/desktop/infrastructure/DesktopScreenshotPlugin.java b/bellatrix.desktop/src/main/java/solutions/bellatrix/desktop/infrastructure/DesktopScreenshotPlugin.java index b8c95926..d75b8929 100644 --- a/bellatrix.desktop/src/main/java/solutions/bellatrix/desktop/infrastructure/DesktopScreenshotPlugin.java +++ b/bellatrix.desktop/src/main/java/solutions/bellatrix/desktop/infrastructure/DesktopScreenshotPlugin.java @@ -13,8 +13,6 @@ package solutions.bellatrix.desktop.infrastructure; -import lombok.SneakyThrows; -import org.apache.commons.io.FileUtils; import org.openqa.selenium.OutputType; import org.openqa.selenium.TakesScreenshot; import plugins.screenshots.ScreenshotPlugin; @@ -35,7 +33,11 @@ public DesktopScreenshotPlugin() { } @Override - @SneakyThrows + public byte[] takeScreenshot() { + return ((TakesScreenshot)DriverService.getWrappedDriver()).getScreenshotAs(OutputType.BYTES); + } + + @Override public String takeScreenshot(String name) { var screenshotSaveDir = getOutputFolder(); var filename = getUniqueFileName(name); @@ -56,7 +58,6 @@ public String takeScreenshot(String name) { } @Override - @SneakyThrows public String takeScreenshot(String screenshotSaveDir, String filename) { var screenshot = ((TakesScreenshot)DriverService.getWrappedDriver()).getScreenshotAs(OutputType.BASE64); Path path = Paths.get(screenshotSaveDir, filename); diff --git a/bellatrix.desktop/src/main/java/solutions/bellatrix/desktop/infrastructure/DriverService.java b/bellatrix.desktop/src/main/java/solutions/bellatrix/desktop/infrastructure/DriverService.java index f0945606..68faf44c 100644 --- a/bellatrix.desktop/src/main/java/solutions/bellatrix/desktop/infrastructure/DriverService.java +++ b/bellatrix.desktop/src/main/java/solutions/bellatrix/desktop/infrastructure/DriverService.java @@ -88,6 +88,9 @@ private static WindowsDriver initializeDriverGridMode(GridSettings gridSettings) caps.setApp(getAppConfiguration().getAppPath().replace("\\", "/")); caps.setAppWorkingDir(new File(getAppConfiguration().getAppPath()).getParent()); + if (ConfigurationService.get(DesktopSettings.class).getAllowImageFindStrategies()) + caps.setCapability("use-plugins", "images"); + WindowsDriver driver = null; try { driver = new WindowsDriver(new URL(gridSettings.getUrl()), caps); diff --git a/bellatrix.desktop/src/main/java/solutions/bellatrix/desktop/services/ComponentCreateService.java b/bellatrix.desktop/src/main/java/solutions/bellatrix/desktop/services/ComponentCreateService.java index 56a32a2a..6892051f 100644 --- a/bellatrix.desktop/src/main/java/solutions/bellatrix/desktop/services/ComponentCreateService.java +++ b/bellatrix.desktop/src/main/java/solutions/bellatrix/desktop/services/ComponentCreateService.java @@ -17,6 +17,7 @@ import solutions.bellatrix.desktop.components.DesktopComponent; import solutions.bellatrix.desktop.findstrategies.*; import solutions.bellatrix.desktop.infrastructure.DriverService; +import solutions.bellatrix.plugins.opencv.Base64Encodable; import java.util.ArrayList; import java.util.List; @@ -60,6 +61,10 @@ public TComponent byIdContaining(Class TComponent byImage(Class componentClass, Base64Encodable encodedImage) { + return by(componentClass, new ImageBase64FindStrategy(encodedImage)); + } + public List allByAutomationId(Class componentClass, String automationId) { return allBy(componentClass, new AutomationIdFindStrategy(automationId)); } @@ -88,6 +93,10 @@ public List allByIdContaining( return allBy(componentClass, new IdContainingFindStrategy(idContaining)); } + public List allByImage(Class componentClass, Base64Encodable encodedImage) { + return allBy(componentClass, new ImageBase64FindStrategy(encodedImage)); + } + public TComponent by(Class componentClass, TFindStrategy findStrategy) { var component = InstanceFactory.create(componentClass); component.setFindStrategy(findStrategy); diff --git a/bellatrix.ios/src/main/java/solutions/bellatrix/ios/components/IOSComponent.java b/bellatrix.ios/src/main/java/solutions/bellatrix/ios/components/IOSComponent.java index f4c3bb71..77cf666a 100644 --- a/bellatrix.ios/src/main/java/solutions/bellatrix/ios/components/IOSComponent.java +++ b/bellatrix.ios/src/main/java/solutions/bellatrix/ios/components/IOSComponent.java @@ -33,6 +33,7 @@ import solutions.bellatrix.ios.services.ComponentCreateService; import solutions.bellatrix.ios.services.ComponentWaitService; import solutions.bellatrix.ios.waitstrategies.*; +import solutions.bellatrix.plugins.opencv.Base64Encodable; import java.awt.Dimension; import java.util.ArrayList; @@ -249,6 +250,10 @@ public TComponent createByIOSClassChain(Class< return create(componentClass, new IOSClassChainFindStrategy(iosClassChain)); } + public TComponent createByImage(Class componentClass, Base64Encodable encodedImage) { + return create(componentClass, new ImageBase64FindStrategy(encodedImage)); + } + public List createAllByName(Class componentClass, String name) { return createAll(componentClass, new NameFindStrategy(name)); } @@ -281,6 +286,10 @@ public List createAllByIOSClassCha return createAll(componentClass, new IOSClassChainFindStrategy(iosClassChain)); } + public List createAllByImage(Class componentClass, Base64Encodable encodedImage) { + return createAll(componentClass, new ImageBase64FindStrategy(encodedImage)); + } + protected TComponent create(Class componentClass, TFindStrategy findStrategy) { CREATING_ELEMENT.broadcast(new ComponentActionEventArgs(this)); findElement(); diff --git a/bellatrix.ios/src/main/java/solutions/bellatrix/ios/configuration/IOSSettings.java b/bellatrix.ios/src/main/java/solutions/bellatrix/ios/configuration/IOSSettings.java index 4f9097d3..d2366657 100644 --- a/bellatrix.ios/src/main/java/solutions/bellatrix/ios/configuration/IOSSettings.java +++ b/bellatrix.ios/src/main/java/solutions/bellatrix/ios/configuration/IOSSettings.java @@ -50,4 +50,6 @@ public class IOSSettings { @Getter @Setter private Boolean videosOnFailEnabled; @Getter @Setter private String videosSaveLocation; + + @Getter @Setter private Boolean allowImageFindStrategies; } diff --git a/bellatrix.ios/src/main/java/solutions/bellatrix/ios/findstrategies/ImageBase64FindStrategy.java b/bellatrix.ios/src/main/java/solutions/bellatrix/ios/findstrategies/ImageBase64FindStrategy.java new file mode 100644 index 00000000..6e5b6bc2 --- /dev/null +++ b/bellatrix.ios/src/main/java/solutions/bellatrix/ios/findstrategies/ImageBase64FindStrategy.java @@ -0,0 +1,54 @@ +/* + * Copyright 2025 Automate The Planet Ltd. + * Author: Miriyam Kyoseva + * Licensed under the Apache License, Version 2.0 (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package solutions.bellatrix.ios.findstrategies; + +import io.appium.java_client.AppiumBy; +import io.appium.java_client.ios.IOSDriver; +import org.openqa.selenium.WebElement; +import solutions.bellatrix.plugins.opencv.Base64Encodable; + +import java.util.List; + +public class ImageBase64FindStrategy extends FindStrategy { + private final Base64Encodable encodedImage; + public ImageBase64FindStrategy(Base64Encodable encodedImage) { + super(encodedImage.getImageName()); + this.encodedImage = encodedImage; + } + + @Override + public WebElement findElement(IOSDriver driver) { + return driver.findElement(AppiumBy.image(encodedImage.getBase64Image())); + } + + @Override + public List findAllElements(IOSDriver driver) { + return driver.findElements(AppiumBy.image(encodedImage.getBase64Image())); + } + + @Override + public WebElement findElement(WebElement element) { + return element.findElement(AppiumBy.image(encodedImage.getBase64Image())); + } + + @Override + public List findAllElements(WebElement element) { + return element.findElements(AppiumBy.image(encodedImage.getBase64Image())); + } + + @Override + public String toString() { + return String.format("image = %s", getValue()); + } +} diff --git a/bellatrix.ios/src/main/java/solutions/bellatrix/ios/infrastructure/DriverService.java b/bellatrix.ios/src/main/java/solutions/bellatrix/ios/infrastructure/DriverService.java index 52e71713..6c77402b 100644 --- a/bellatrix.ios/src/main/java/solutions/bellatrix/ios/infrastructure/DriverService.java +++ b/bellatrix.ios/src/main/java/solutions/bellatrix/ios/infrastructure/DriverService.java @@ -113,6 +113,9 @@ private static IOSDriver initializeDriverRegularMode(String serviceUrl) { caps.setApp(getAppConfiguration().getAppPath().replace("\\", "/")); } + if (ConfigurationService.get(IOSSettings.class).getAllowImageFindStrategies()) + caps.setCapability("use-plugins", "images"); + addDriverOptions(caps); var driver = new IOSDriver(new URL(serviceUrl), caps); solutions.bellatrix.web.infrastructure.DriverService.setWrappedDriver(driver); diff --git a/bellatrix.ios/src/main/java/solutions/bellatrix/ios/infrastructure/MobileScreenshotPlugin.java b/bellatrix.ios/src/main/java/solutions/bellatrix/ios/infrastructure/MobileScreenshotPlugin.java index 6e932d0b..018c3ce4 100644 --- a/bellatrix.ios/src/main/java/solutions/bellatrix/ios/infrastructure/MobileScreenshotPlugin.java +++ b/bellatrix.ios/src/main/java/solutions/bellatrix/ios/infrastructure/MobileScreenshotPlugin.java @@ -13,8 +13,6 @@ package solutions.bellatrix.ios.infrastructure; -import lombok.SneakyThrows; -import org.apache.commons.io.FileUtils; import org.openqa.selenium.OutputType; import org.openqa.selenium.TakesScreenshot; import plugins.screenshots.ScreenshotPlugin; @@ -35,7 +33,11 @@ public MobileScreenshotPlugin() { } @Override - @SneakyThrows + public byte[] takeScreenshot() { + return ((TakesScreenshot)DriverService.getWrappedIOSDriver()).getScreenshotAs(OutputType.BYTES); + } + + @Override public String takeScreenshot(String name) { var screenshotSaveDir = getOutputFolder(); var filename = getUniqueFileName(name); @@ -55,7 +57,6 @@ public String takeScreenshot(String name) { } @Override - @SneakyThrows public String takeScreenshot(String screenshotSaveDir, String filename) { var screenshot = ((TakesScreenshot)DriverService.getWrappedIOSDriver()).getScreenshotAs(OutputType.BASE64); var path = Paths.get(screenshotSaveDir, filename) + ".png"; diff --git a/bellatrix.ios/src/main/java/solutions/bellatrix/ios/services/ComponentCreateService.java b/bellatrix.ios/src/main/java/solutions/bellatrix/ios/services/ComponentCreateService.java index e01e0645..db9ec690 100644 --- a/bellatrix.ios/src/main/java/solutions/bellatrix/ios/services/ComponentCreateService.java +++ b/bellatrix.ios/src/main/java/solutions/bellatrix/ios/services/ComponentCreateService.java @@ -17,6 +17,7 @@ import solutions.bellatrix.ios.components.IOSComponent; import solutions.bellatrix.ios.findstrategies.*; import solutions.bellatrix.ios.infrastructure.DriverService; +import solutions.bellatrix.plugins.opencv.Base64Encodable; import java.util.ArrayList; import java.util.List; @@ -68,6 +69,10 @@ public TComponent byAccessibilityIdContaining( return by(componentClass, new AccessibilityIdFindStrategy(accessibilityId)); } + public TComponent byImage(Class componentClass, Base64Encodable encodedImage) { + return by(componentClass, new ImageBase64FindStrategy(encodedImage)); + } + public List allById(Class componentClass, String id) { return allBy(componentClass, new IdFindStrategy(id)); } @@ -104,6 +109,10 @@ public List allByAccessibilityId(C return allBy(componentClass, new AccessibilityIdFindStrategy(accessibilityId)); } + public List allByImage(Class componentClass, Base64Encodable encodedImage) { + return allBy(componentClass, new ImageBase64FindStrategy(encodedImage)); + } + public TComponent by(Class componentClass, TFindStrategy findStrategy) { var component = InstanceFactory.create(componentClass); component.setFindStrategy(findStrategy); diff --git a/bellatrix.playwright/pom.xml b/bellatrix.playwright/pom.xml index ef684b0d..a8099293 100644 --- a/bellatrix.playwright/pom.xml +++ b/bellatrix.playwright/pom.xml @@ -47,15 +47,30 @@ compile - net.lightbody.bmp - browsermob-core - 2.1.5 + solutions.bellatrix + bellatrix.plugins.opencv + 1.0 compile - solutions.bellatrix - bellatrix.layout - 1.0 + org.projectlombok + lombok + 1.18.30 + + + com.microsoft.playwright + playwright + 1.44.0 + + + org.junit.jupiter + junit-jupiter + 5.10.0 + + + net.lightbody.bmp + browsermob-core + 2.1.5 compile @@ -70,6 +85,12 @@ 5.4.0 compile + + solutions.bellatrix + bellatrix.layout + 1.0 + compile + \ No newline at end of file diff --git a/bellatrix.playwright/src/main/java/solutions/bellatrix/playwright/components/ActionImage.java b/bellatrix.playwright/src/main/java/solutions/bellatrix/playwright/components/ActionImage.java new file mode 100644 index 00000000..7beb8c1b --- /dev/null +++ b/bellatrix.playwright/src/main/java/solutions/bellatrix/playwright/components/ActionImage.java @@ -0,0 +1,63 @@ +package solutions.bellatrix.playwright.components; + +import com.microsoft.playwright.Mouse; +import com.microsoft.playwright.options.MouseButton; +import lombok.Getter; +import lombok.Setter; +import org.openqa.selenium.InvalidArgumentException; +import solutions.bellatrix.core.plugins.EventListener; +import solutions.bellatrix.playwright.components.common.ComponentActionEventArgs; +import solutions.bellatrix.playwright.findstrategies.ImageBase64FindStrategy; +import solutions.bellatrix.playwright.infrastructure.PlaywrightService; +import solutions.bellatrix.plugins.opencv.OpenCvService; + +import java.awt.*; + +@Getter +@Setter +public class ActionImage extends WebComponent { + public final static EventListener CLICKING = new EventListener<>(); + public final static EventListener HOVERING = new EventListener<>(); + + private final Mouse mouse = PlaywrightService.wrappedBrowser().getCurrentPage().mouse(); + + @Override + public Point getLocation() { + ImageBase64FindStrategy findStrategy; + try { + findStrategy = (ImageBase64FindStrategy)getFindStrategy(); + } catch (ClassCastException e) { + throw new InvalidArgumentException("Invalid image base 64 format"); + } + + var encodedImage = findStrategy.getEncodedImage(); + + var location = OpenCvService.getLocation(encodedImage, true); + return new Point((int)location.x + encodedImage.getXOffset(), (int)location.y + encodedImage.getYOffset()); + } + + public void click() { + CLICKING.broadcast(new ComponentActionEventArgs(this, null, "Coordinates: %d, %d".formatted(getLocation().x, getLocation().y))); + + mouse.click(getLocation().x, getLocation().y); + } + + public void rightClick() { + CLICKING.broadcast(new ComponentActionEventArgs(this, null, "Coordinates: %d, %d".formatted(getLocation().x, getLocation().y))); + + mouse.click(getLocation().x, getLocation().y, new Mouse.ClickOptions().setButton(MouseButton.RIGHT)); + } + + public void hover() { + HOVERING.broadcast(new ComponentActionEventArgs(this, null, "Coordinates: %d, %d".formatted(getLocation().x, getLocation().y))); + + mouse.move(getLocation().x, getLocation().y); + } + + public void dragAndDrop(ActionImage image) { + mouse.move(getLocation().x, getLocation().y); + mouse.down(); + mouse.move(image.getLocation().x, image.getLocation().y); + mouse.up(); + } +} \ No newline at end of file diff --git a/bellatrix.playwright/src/main/java/solutions/bellatrix/playwright/components/TextArea.java b/bellatrix.playwright/src/main/java/solutions/bellatrix/playwright/components/TextArea.java index f2523871..e49ebd26 100644 --- a/bellatrix.playwright/src/main/java/solutions/bellatrix/playwright/components/TextArea.java +++ b/bellatrix.playwright/src/main/java/solutions/bellatrix/playwright/components/TextArea.java @@ -26,7 +26,7 @@ public String getText() { String text = defaultGetText(); if (text.isEmpty()) { - return defaultGetValue(); + return getWrappedElement().inputValue(); } return text; diff --git a/bellatrix.playwright/src/main/java/solutions/bellatrix/playwright/components/TextInput.java b/bellatrix.playwright/src/main/java/solutions/bellatrix/playwright/components/TextInput.java index 43568f67..af477f64 100644 --- a/bellatrix.playwright/src/main/java/solutions/bellatrix/playwright/components/TextInput.java +++ b/bellatrix.playwright/src/main/java/solutions/bellatrix/playwright/components/TextInput.java @@ -26,7 +26,7 @@ public String getText() { String text = defaultGetText(); if (text.isEmpty()) { - return defaultGetValue(); + return getWrappedElement().inputValue(); } return text; diff --git a/bellatrix.playwright/src/main/java/solutions/bellatrix/playwright/components/WebComponent.java b/bellatrix.playwright/src/main/java/solutions/bellatrix/playwright/components/WebComponent.java index cc9e7418..163003ae 100644 --- a/bellatrix.playwright/src/main/java/solutions/bellatrix/playwright/components/WebComponent.java +++ b/bellatrix.playwright/src/main/java/solutions/bellatrix/playwright/components/WebComponent.java @@ -32,7 +32,6 @@ import solutions.bellatrix.playwright.components.common.ComponentActionEventArgs; import solutions.bellatrix.playwright.components.common.create.RelativeCreateService; import solutions.bellatrix.playwright.components.common.validate.Validator; -import solutions.bellatrix.playwright.components.common.webelement.FrameElement; import solutions.bellatrix.playwright.components.common.webelement.WebElement; import solutions.bellatrix.playwright.components.contracts.Component; import solutions.bellatrix.playwright.components.contracts.ComponentStyle; diff --git a/bellatrix.playwright/src/main/java/solutions/bellatrix/playwright/components/common/webelement/WebElement.java b/bellatrix.playwright/src/main/java/solutions/bellatrix/playwright/components/common/webelement/WebElement.java index 34109d6d..ac195208 100644 --- a/bellatrix.playwright/src/main/java/solutions/bellatrix/playwright/components/common/webelement/WebElement.java +++ b/bellatrix.playwright/src/main/java/solutions/bellatrix/playwright/components/common/webelement/WebElement.java @@ -31,11 +31,18 @@ */ @Getter public class WebElement { + public WebElement(List locators) { + wrappedLocators = locators; + wrappedLocator = wrappedLocators.get(0); + } + public WebElement(Locator locator) { wrappedLocator = locator; + wrappedLocators = wrappedLocator.all(); } private final Locator wrappedLocator; + private final List wrappedLocators; public WebElement getByAltText(String text, GetByAltTextOptions options) { return new WebElement(wrappedLocator.getByAltText(text, options.convertTo(Locator.GetByAltTextOptions.class))); @@ -143,8 +150,7 @@ public FrameElement locateFrame() { public List all() { List elements = new ArrayList<>(); - List locators = wrappedLocator.all(); - for (Locator locator : locators) { + for (Locator locator : wrappedLocators) { elements.add(new WebElement(locator)); } @@ -294,7 +300,7 @@ public WebElement filter() { } public WebElement first() { - return new WebElement(wrappedLocator.first()); + return new WebElement(wrappedLocators.get(0)); } public void focus(Locator.FocusOptions options) { @@ -399,11 +405,11 @@ public boolean isVisible() { } public WebElement last() { - return new WebElement(wrappedLocator.last()); + return new WebElement(wrappedLocators.get(wrappedLocator.count() - 1)); } public WebElement nth(int index) { - return new WebElement(wrappedLocator.nth(index)); + return new WebElement(wrappedLocators.get(index)); } public WebElement or(WebElement webElement) { diff --git a/bellatrix.playwright/src/main/java/solutions/bellatrix/playwright/findstrategies/ImageBase64FindStrategy.java b/bellatrix.playwright/src/main/java/solutions/bellatrix/playwright/findstrategies/ImageBase64FindStrategy.java new file mode 100644 index 00000000..58d03431 --- /dev/null +++ b/bellatrix.playwright/src/main/java/solutions/bellatrix/playwright/findstrategies/ImageBase64FindStrategy.java @@ -0,0 +1,115 @@ +/* + * Copyright 2025 Automate The Planet Ltd. + * Author: Miriam Kyoseva + * Licensed under the Apache License, Version 2.0 (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package solutions.bellatrix.playwright.findstrategies; + +import com.microsoft.playwright.Locator; +import com.microsoft.playwright.Page; +import lombok.Getter; +import solutions.bellatrix.core.utilities.SingletonFactory; +import solutions.bellatrix.core.utilities.parsing.TypeParser; +import solutions.bellatrix.playwright.components.common.webelement.WebElement; +import solutions.bellatrix.playwright.services.JavaScriptService; +import solutions.bellatrix.plugins.opencv.Base64Encodable; +import solutions.bellatrix.plugins.opencv.OpenCvService; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +@Getter +public class ImageBase64FindStrategy extends FindStrategy { + private final Base64Encodable encodedImage; + + public ImageBase64FindStrategy(Base64Encodable encodedImage) { + this.encodedImage = encodedImage; + } + + @Override + public WebElement convert(Page page) { + var location = OpenCvService.getLocation(encodedImage, false); + + var foundLocators = findElementsOn(location, page); + + this.webElement = new WebElement(foundLocators); + + return webElement; + } + + @Override + public WebElement convert(WebElement webElement) { + var location = OpenCvService.getLocation(encodedImage, false); + + var foundLocators = findElementsOn(location, webElement.page()); + + this.webElement = new WebElement(foundLocators); + + return webElement; + } + + private static List findElementsOn(org.opencv.core.Point coordinates, Page page) { + var elementsXpaths = (List)page.evaluate("(%s)(%s, %s);".formatted(js, TypeParser.parse(coordinates.x, Integer.class), TypeParser.parse(coordinates.y, Integer.class))); + + var locators = new ArrayList(); + + for (var i = 0; i < elementsXpaths.size(); i++) { + if (!elementsXpaths.get(i).isBlank()) + locators.add(page.locator("/" + elementsXpaths.get(i))); + } + + return locators; + } + + private static String js = """ + function getElementsOn(x, y) { + function getAbsoluteXpath(element) { + function indexElement(el) { + let index = 1; + + let previousSibling = el.previousElementSibling; + while (previousSibling) { + if (previousSibling.nodeName.toLowerCase() === el.nodeName.toLowerCase()) { + index++; + } + previousSibling = previousSibling.previousElementSibling; + } + + return "/" + el.tagName.toLowerCase() + "[" + index + "]"; + } + + let xpath = []; + + let currentElement = element; + while (currentElement) { + if (currentElement.tagName.toLowerCase() === 'html' || currentElement.tagName.toLowerCase() === 'body' || currentElement.tagName.startsWith() === '#' || currentElement.tagName.toLowerCase() === "temporary-div") { + break; + } + + xpath.unshift(indexElement(currentElement)); + + currentElement = currentElement.parentElement; + } + return xpath.join(""); + } + + const elements = document.elementsFromPoint(x, y); + const elementsXpaths = []; + + for (let i = 0; i < elements.length; i++) { + elementsXpaths.push(getAbsoluteXpath(elements[i])); + } + + return elementsXpaths; + } + """; +} diff --git a/bellatrix.playwright/src/main/java/solutions/bellatrix/playwright/infrastructure/WebScreenshotPlugin.java b/bellatrix.playwright/src/main/java/solutions/bellatrix/playwright/infrastructure/WebScreenshotPlugin.java index e8c1ab98..f3cbb6f5 100644 --- a/bellatrix.playwright/src/main/java/solutions/bellatrix/playwright/infrastructure/WebScreenshotPlugin.java +++ b/bellatrix.playwright/src/main/java/solutions/bellatrix/playwright/infrastructure/WebScreenshotPlugin.java @@ -30,6 +30,14 @@ public WebScreenshotPlugin() { super(Settings.web().getScreenshotsOnFailEnabled()); } + @Override + public byte[] takeScreenshot() { + return PlaywrightService.wrappedBrowser().getCurrentPage() + .screenshot(new Page.ScreenshotOptions() + .setType(ScreenshotType.PNG) + .setFullPage(false)); + } + @Override public String takeScreenshot(String name) { var screenshotSaveDir = getOutputFolder(); diff --git a/bellatrix.playwright/src/main/java/solutions/bellatrix/playwright/services/BrowserService.java b/bellatrix.playwright/src/main/java/solutions/bellatrix/playwright/services/BrowserService.java index 40cae43b..fcd977d1 100644 --- a/bellatrix.playwright/src/main/java/solutions/bellatrix/playwright/services/BrowserService.java +++ b/bellatrix.playwright/src/main/java/solutions/bellatrix/playwright/services/BrowserService.java @@ -64,6 +64,10 @@ public String getPageSource() { return page().content(); } + public void setSize(int width, int height) { + page().setViewportSize(width, height); + } + /** * Not possible to implement. */ diff --git a/bellatrix.playwright/src/main/java/solutions/bellatrix/playwright/services/ComponentCreateService.java b/bellatrix.playwright/src/main/java/solutions/bellatrix/playwright/services/ComponentCreateService.java index 95af6be9..246193bb 100644 --- a/bellatrix.playwright/src/main/java/solutions/bellatrix/playwright/services/ComponentCreateService.java +++ b/bellatrix.playwright/src/main/java/solutions/bellatrix/playwright/services/ComponentCreateService.java @@ -22,6 +22,7 @@ import solutions.bellatrix.playwright.findstrategies.options.*; import solutions.bellatrix.playwright.components.common.webelement.FrameElement; import solutions.bellatrix.playwright.components.common.webelement.WebElement; +import solutions.bellatrix.plugins.opencv.Base64Encodable; import java.util.ArrayList; import java.util.List; @@ -166,6 +167,14 @@ public List allById(Class TComponent byImage(Class componentClass, Base64Encodable encodedImage) { + return by(componentClass, new ImageBase64FindStrategy(encodedImage)); + } + + public List allByImage(Class componentClass, Base64Encodable encodedImage) { + return allBy(componentClass, new ImageBase64FindStrategy(encodedImage)); + } + public TComponent byClass(Class componentClass, String value) { return by(componentClass, new ClassFindStrategy(value)); } diff --git a/bellatrix.plugins.opencv/pom.xml b/bellatrix.plugins.opencv/pom.xml new file mode 100644 index 00000000..66dafc6c --- /dev/null +++ b/bellatrix.plugins.opencv/pom.xml @@ -0,0 +1,53 @@ + + + 4.0.0 + + solutions.bellatrix + bellatrix + 1.0-SNAPSHOT + + + solutions.bellatrix + bellatrix.plugins.opencv + 1.0 + + + 19 + 19 + UTF-8 + + + + + solutions.bellatrix + bellatrix.core + 1.0 + + + solutions.bellatrix + bellatrix.plugins.screenshots + 1.0 + + + org.openpnp + opencv + 4.3.0-3 + compile + + + jakarta.xml.bind + jakarta.xml.bind-api + 2.3.2 + test + + + jakarta.xml.bind + jakarta.xml.bind-api + 2.3.2 + compile + + + + \ No newline at end of file diff --git a/bellatrix.plugins.opencv/src/main/java/solutions/bellatrix/plugins/opencv/Base64Encodable.java b/bellatrix.plugins.opencv/src/main/java/solutions/bellatrix/plugins/opencv/Base64Encodable.java new file mode 100644 index 00000000..8589f88c --- /dev/null +++ b/bellatrix.plugins.opencv/src/main/java/solutions/bellatrix/plugins/opencv/Base64Encodable.java @@ -0,0 +1,8 @@ +package solutions.bellatrix.plugins.opencv; + +public interface Base64Encodable { + String getBase64Image(); + String getImageName(); + int getXOffset(); + int getYOffset(); +} \ No newline at end of file diff --git a/bellatrix.plugins.opencv/src/main/java/solutions/bellatrix/plugins/opencv/OpenCvService.java b/bellatrix.plugins.opencv/src/main/java/solutions/bellatrix/plugins/opencv/OpenCvService.java new file mode 100644 index 00000000..705ca8e9 --- /dev/null +++ b/bellatrix.plugins.opencv/src/main/java/solutions/bellatrix/plugins/opencv/OpenCvService.java @@ -0,0 +1,146 @@ +package solutions.bellatrix.plugins.opencv; + +import nu.pattern.OpenCV; +import org.opencv.core.Core; +import org.opencv.core.CvType; +import org.opencv.core.Mat; +import org.opencv.core.Point; +import org.opencv.imgcodecs.Imgcodecs; +import org.opencv.imgproc.Imgproc; +import plugins.screenshots.ScreenshotPlugin; +import solutions.bellatrix.core.utilities.SingletonFactory; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.util.Base64; + +public class OpenCvService { + /** + * @return the current scaling factor (e.g., 1.0 for 100%, 1.25 for 125%) + */ + public static double getJavaMonitorScaling() { + GraphicsConfiguration gc = GraphicsEnvironment + .getLocalGraphicsEnvironment() + .getDefaultScreenDevice() + .getDefaultConfiguration(); + + // Get the default transform + AffineTransform transform = gc.getDefaultTransform(); + + // The scaling factor is typically the same for both X and Y + double scaleX = transform.getScaleX(); + double scaleY = transform.getScaleY(); + + // Return X scale (usually same as Y scale) + return scaleX; + } + + /** + * @return the coordinates of the image found on the screen + */ + public static Point getLocation(Base64Encodable encodedImage, boolean shouldGrayScale) { + var screenshotPlugin = SingletonFactory.getInstance(ScreenshotPlugin.class); + + if (screenshotPlugin == null) { + throw new IllegalArgumentException("It seems that the screenshot plugin isn't registered by the 'ScreenshotPlugin.class' key inside SingletonFactory's map or isn't registered at all!\n" + + "Check the BaseTest class of your project where the plugins are registered. Register the specific screenshot plugin implementation as the base ScreenshotPlugin.class.\n" + + "for example: addPluginAs(ScreenshotPlugin.class, WebScreenshotPlugin.class);"); + } + + var screenshot = screenshotPlugin.takeScreenshot(); + + OpenCV.loadLocally(); + + Mat result = loadImages(encodedImage, screenshot, shouldGrayScale); + + return getMatchLocation(encodedImage, result); + } + + private static Point getMatchLocation(Base64Encodable encodedImage, Mat result) { + BufferedImage bufferedImage; + + Core.MinMaxLocResult mmr = Core.minMaxLoc(result); + Point matchLoc = mmr.maxLoc; + + if (encodedImage.getXOffset() == 0 && encodedImage.getYOffset() == 0) { + try { + bufferedImage = getImageWidthHeight(encodedImage); + } catch (IOException e) { + throw new RuntimeException(e); + } + + double[] imageCenterCoordinates = {matchLoc.x / getJavaMonitorScaling() + (double)(bufferedImage.getWidth() / 2), matchLoc.y / getJavaMonitorScaling() + (double)(bufferedImage.getHeight() / 2)}; + matchLoc.set(imageCenterCoordinates); + } + + return matchLoc; + } + + private static BufferedImage getImageWidthHeight(Base64Encodable encodedImage) throws IOException { + String cleanBase64 = removePrefixFromBase64(encodedImage); + + byte[] decodedBytes = Base64.getDecoder().decode(cleanBase64); + ByteArrayInputStream bis = new ByteArrayInputStream(decodedBytes); + BufferedImage bimg = ImageIO.read(bis); + + return bimg; + } + + private static Mat loadImages(Base64Encodable encodedImage, byte[] screenshot, boolean shouldGrayScale) { + Mat template = getMatrixFromBase64(encodedImage); + if (shouldGrayScale) { + changeToGrayscale(template); + } + + Mat source = getMatrixFromBinaryData(screenshot); + if (shouldGrayScale) { + changeToGrayscale(source); + } + + Mat result = createResultMatrix(source, template); + + Imgproc.matchTemplate(source, template, result, Imgproc.TM_CCOEFF_NORMED); + + return result; + } + + private static Mat changeToGrayscale(Mat template) { + Mat templateGrayscale = new Mat(); + Imgproc.cvtColor(template, templateGrayscale, Imgproc.COLOR_BGR2GRAY); + + template = templateGrayscale; + return template; + } + + private static Mat getMatrixFromBase64(Base64Encodable encodedImage) { + String cleanBase64 = removePrefixFromBase64(encodedImage); + + byte[] decodedBytes = Base64.getDecoder().decode(cleanBase64); + return getMatrixFromBinaryData(decodedBytes); + } + + private static String removePrefixFromBase64(Base64Encodable encodedImage) { + String base64Image = encodedImage.getBase64Image(); + return base64Image.replaceFirst("^data:.+?;base64,", ""); + } + + private static Mat getMatrixFromBinaryData(byte[] decodedBytes) { + Mat mat = new Mat(1, decodedBytes.length, CvType.CV_8U); + mat.put(0, 0, decodedBytes); + + return Imgcodecs.imdecode(mat, Imgcodecs.IMREAD_COLOR); + } + + private static Mat createResultMatrix(Mat source, Mat template) { + Mat result = new Mat(); + int result_cols = source.cols() - template.cols() + 1; + int result_rows = source.rows() - template.rows() + 1; + result.create(result_rows, result_cols, CvType.CV_32FC1); + + return result; + } +} \ No newline at end of file diff --git a/bellatrix.plugins.screenshots/src/main/java/plugins/screenshots/ScreenshotPlugin.java b/bellatrix.plugins.screenshots/src/main/java/plugins/screenshots/ScreenshotPlugin.java index 528d24e7..c6a4e880 100644 --- a/bellatrix.plugins.screenshots/src/main/java/plugins/screenshots/ScreenshotPlugin.java +++ b/bellatrix.plugins.screenshots/src/main/java/plugins/screenshots/ScreenshotPlugin.java @@ -29,6 +29,7 @@ public ScreenshotPlugin(boolean isEnabled) { this.isEnabled = isEnabled; } + public abstract byte[] takeScreenshot(); public abstract String takeScreenshot(String fileName); public abstract String takeScreenshot(String screenshotSaveDir, String filename); protected abstract String getOutputFolder(); diff --git a/bellatrix.plugins.visual-regression-tracker/src/main/java/solutions/bellatrix/plugins/vrt/VisualRegressionService.java b/bellatrix.plugins.visual-regression-tracker/src/main/java/solutions/bellatrix/plugins/vrt/VisualRegressionService.java index eeefd6eb..90ef489f 100644 --- a/bellatrix.plugins.visual-regression-tracker/src/main/java/solutions/bellatrix/plugins/vrt/VisualRegressionService.java +++ b/bellatrix.plugins.visual-regression-tracker/src/main/java/solutions/bellatrix/plugins/vrt/VisualRegressionService.java @@ -78,9 +78,12 @@ public static String takeSnapshot(String name) { var screenshotPlugin = SingletonFactory.getInstance(ScreenshotPlugin.class); if (screenshotPlugin == null) { - throw new IllegalArgumentException("It seems that the screenshot plugin isn't registered by the 'ScreenshotPlugin.class' key inside SingletonFactory's map or isn't registered at all!"); + throw new IllegalArgumentException("It seems that the screenshot plugin isn't registered by the 'ScreenshotPlugin.class' key inside SingletonFactory's map or isn't registered at all!\n" + + "Check the BaseTest class of your project where the plugins are registered. Register the specific screenshot plugin implementation as the base ScreenshotPlugin.class.\n" + + "for example: addPluginAs(ScreenshotPlugin.class, WebScreenshotPlugin.class);"); } + return screenshotPlugin.takeScreenshot(name); } diff --git a/bellatrix.web/pom.xml b/bellatrix.web/pom.xml index c6ffc9a6..b6efa38d 100644 --- a/bellatrix.web/pom.xml +++ b/bellatrix.web/pom.xml @@ -39,6 +39,12 @@ bellatrix.plugins.screenshots 1.0 + + solutions.bellatrix + bellatrix.plugins.opencv + 1.0 + compile + ru.yandex.qatools.ashot ashot diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/components/ActionImage.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/components/ActionImage.java new file mode 100644 index 00000000..fee784ee --- /dev/null +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/components/ActionImage.java @@ -0,0 +1,64 @@ +package solutions.bellatrix.web.components; + +import lombok.Getter; +import lombok.Setter; +import org.openqa.selenium.InvalidArgumentException; +import org.openqa.selenium.interactions.Actions; +import solutions.bellatrix.core.plugins.EventListener; +import solutions.bellatrix.plugins.opencv.OpenCvService; +import solutions.bellatrix.web.findstrategies.ImageBase64FindStrategy; +import solutions.bellatrix.web.services.App; + +import java.awt.*; + +@Getter +@Setter +public class ActionImage extends WebComponent { + public final static EventListener CLICKING = new EventListener<>(); + public final static EventListener HOVERING = new EventListener<>(); + + private Actions actions = new Actions(getWrappedDriver()); + + @Override + public Point getLocation() { + ImageBase64FindStrategy findStrategy; + try { + findStrategy = (ImageBase64FindStrategy)getFindStrategy(); + } catch (ClassCastException e) { + throw new InvalidArgumentException("Invalid image base 64 format"); + } + + var encodedImage = findStrategy.getEncodedImage(); + + var location = OpenCvService.getLocation(encodedImage, true); + return new Point((int)location.x + encodedImage.getXOffset(), (int)location.y + encodedImage.getYOffset()); + } + + public void click() { + CLICKING.broadcast(new ComponentActionEventArgs(this, null, "Coordinates: %d, %d".formatted(getLocation().x, getLocation().y))); + actions.moveByOffset(getLocation().x, getLocation().y) + .click() + .perform(); + } + + public void rightClick() { + CLICKING.broadcast(new ComponentActionEventArgs(this, null, "Coordinates: %d, %d".formatted(getLocation().x, getLocation().y))); + actions.moveByOffset(getLocation().x, getLocation().y) + .contextClick() + .perform(); + } + + public void hover() { + HOVERING.broadcast(new ComponentActionEventArgs(this, null, "Coordinates: %d, %d".formatted(getLocation().x, getLocation().y))); + actions.moveToLocation(getLocation().x, getLocation().y) + .perform(); + } + + public void dragAndDrop(ActionImage image) { + actions.moveByOffset(getLocation().x, getLocation().y) + .clickAndHold() + .moveToLocation(image.getLocation().x, image.getLocation().y) + .release() + .perform(); + } +} \ No newline at end of file diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/components/WebComponent.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/components/WebComponent.java index 98cc513a..13b967b1 100644 --- a/bellatrix.web/src/main/java/solutions/bellatrix/web/components/WebComponent.java +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/components/WebComponent.java @@ -28,6 +28,7 @@ import solutions.bellatrix.core.utilities.DebugInformation; import solutions.bellatrix.core.utilities.InstanceFactory; import solutions.bellatrix.core.utilities.Log; +import solutions.bellatrix.plugins.opencv.Base64Encodable; import solutions.bellatrix.web.components.contracts.Component; import solutions.bellatrix.web.components.contracts.ComponentStyle; import solutions.bellatrix.web.components.contracts.ComponentVisible; @@ -343,6 +344,10 @@ public TComponent createById(Class return create(componentClass, new IdFindStrategy(id)); } + public TComponent createByImage(Class componentClass, Base64Encodable encodedImage) { + return create(componentClass, new ImageBase64FindStrategy(encodedImage)); + } + public TComponent createByAttributeContaining(Class componentClass, String attributeName, String value) { return create(componentClass, new AttributeContainingWithFindStrategy(attributeName, value)); } @@ -403,6 +408,10 @@ public List createAllById(Class List createAllByImage(Class componentClass, Base64Encodable encodedImage) { + return createAll(componentClass, new ImageBase64FindStrategy(encodedImage)); + } + public List createAllByAttributeContaining(Class componentClass, String attributeName, String value) { return createAll(componentClass, new AttributeContainingWithFindStrategy(attributeName, value)); } diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/components/listeners/BddConsoleLogging.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/components/listeners/BddConsoleLogging.java index 0543f7d0..d3cc33e1 100644 --- a/bellatrix.web/src/main/java/solutions/bellatrix/web/components/listeners/BddConsoleLogging.java +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/components/listeners/BddConsoleLogging.java @@ -52,6 +52,8 @@ public void addListener() { // WebComponent.SCROLLING_TO_VISIBLE.addListener((x) -> Log.info("scrolling to %s", x.getComponent().getComponentName())); WebComponent.SETTING_ATTRIBUTE.addListener((x) -> Log.info("setting %s to '%s' in %s", x.getActionValue(), x.getMessage(), x.getComponent().getComponentName())); ComponentValidator.VALIDATING_ATTRIBUTE.addListener((x) -> Log.info(x.getMessage())); + ActionImage.CLICKING.addListener((x) -> Log.info("clicking %s", x.getMessage())); + ActionImage.HOVERED.addListener((x) -> Log.info("hovering %s", x.getMessage())); isBddLoggingTurnedOn = true; } } diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/components/listeners/BddToastNotificationsLogging.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/components/listeners/BddToastNotificationsLogging.java index 474b55a0..2701ce2a 100644 --- a/bellatrix.web/src/main/java/solutions/bellatrix/web/components/listeners/BddToastNotificationsLogging.java +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/components/listeners/BddToastNotificationsLogging.java @@ -25,7 +25,7 @@ public class BddToastNotificationsLogging extends Listener { @Override public void addListener() { - isBddLoggingTurnedOn = ConfigurationService.get(WebSettings.class).getToastNotificationBddLogging(); + isBddLoggingTurnedOn = ConfigurationService.get(WebSettings.class).getToastNotificationBddLogging() == null ? isBddLoggingTurnedOn : ConfigurationService.get(WebSettings.class).getToastNotificationBddLogging(); if (isBddLoggingTurnedOn) { Anchor.CLICKING.addListener((x) -> new BrowserService().injectInfoNotificationToast("clicking %s", x.getComponent().getComponentName())); Button.CLICKING.addListener((x) -> new BrowserService().injectInfoNotificationToast("clicking %s", x.getComponent().getComponentName())); @@ -55,6 +55,8 @@ public void addListener() { // WebComponent.SCROLLING_TO_VISIBLE.addListener((x) -> new BrowserService().injectInfoNotificationToast("scrolling to %s", x.getComponent().getComponentName())); WebComponent.SETTING_ATTRIBUTE.addListener((x) -> new BrowserService().injectInfoNotificationToast("setting %s to '%s' in %s", x.getActionValue(), x.getMessage(), x.getComponent().getComponentName())); ComponentValidator.VALIDATING_ATTRIBUTE.addListener((x) -> new BrowserService().injectInfoNotificationToast(x.getMessage())); + ActionImage.CLICKING.addListener((x) -> new BrowserService().injectInfoNotificationToast("clicking %s", x.getMessage())); + ActionImage.HOVERED.addListener((x) -> new BrowserService().injectInfoNotificationToast("hovering %s", x.getMessage())); isBddLoggingTurnedOn = true; } } diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/findstrategies/ImageBase64FindStrategy.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/findstrategies/ImageBase64FindStrategy.java new file mode 100644 index 00000000..6efa1658 --- /dev/null +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/findstrategies/ImageBase64FindStrategy.java @@ -0,0 +1,58 @@ +package solutions.bellatrix.web.findstrategies; + +import lombok.Getter; +import org.openqa.selenium.By; +import org.openqa.selenium.SearchContext; +import org.openqa.selenium.WebElement; +import solutions.bellatrix.core.utilities.Log; +import solutions.bellatrix.core.utilities.SingletonFactory; +import solutions.bellatrix.plugins.opencv.Base64Encodable; +import solutions.bellatrix.plugins.opencv.OpenCvService; +import solutions.bellatrix.web.services.App; +import solutions.bellatrix.web.services.JavaScriptService; + +import java.util.List; +import java.util.Objects; + +@Getter +public class ImageBase64FindStrategy extends FindStrategy { + private final Base64Encodable encodedImage; + + public ImageBase64FindStrategy(Base64Encodable encodedImage) { + super(encodedImage.getBase64Image()); + this.encodedImage = encodedImage; + } + + @Override + public By convert() { + return new ByImageBase64(encodedImage); + } + + @Override + public String toString() { + return String.format("image base 64: %s", encodedImage.getImageName()); + } + + public static class ByImageBase64 extends By { + private final Base64Encodable base64EncodedImage; + + public ByImageBase64(Base64Encodable base64EncodedImage) { + this.base64EncodedImage = base64EncodedImage; + } + + public static By byImageBase64(Base64Encodable encodedImage) { + return new ByImageBase64(encodedImage); + } + + @Override + public List findElements(SearchContext context) { + var location = OpenCvService.getLocation(base64EncodedImage, false); + Log.info("Coordinates located: %s", location.toString()); + return SingletonFactory.getInstance(JavaScriptService.class).>genericExecute("return document.elementsFromPoint(%s, %s);".formatted(location.x, location.y)); + } + + public String toString() { + return "By.imageBase64: " + this.base64EncodedImage; + } + } +} \ No newline at end of file diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/WebScreenshotPlugin.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/WebScreenshotPlugin.java index bc58145e..a3b0283b 100644 --- a/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/WebScreenshotPlugin.java +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/infrastructure/WebScreenshotPlugin.java @@ -13,6 +13,9 @@ package solutions.bellatrix.web.infrastructure; +import nu.pattern.OpenCV; +import org.openqa.selenium.OutputType; +import org.openqa.selenium.TakesScreenshot; import plugins.screenshots.ScreenshotPlugin; import plugins.screenshots.ScreenshotPluginEventArgs; import ru.yandex.qatools.ashot.AShot; @@ -20,7 +23,10 @@ import solutions.bellatrix.core.configuration.ConfigurationService; import solutions.bellatrix.core.utilities.Log; import solutions.bellatrix.core.utilities.PathNormalizer; +import solutions.bellatrix.core.utilities.SingletonFactory; import solutions.bellatrix.web.configuration.WebSettings; +import solutions.bellatrix.web.services.BrowserService; +import solutions.bellatrix.web.services.WebService; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; @@ -36,6 +42,11 @@ public WebScreenshotPlugin() { super(ConfigurationService.get(WebSettings.class).getScreenshotsOnFailEnabled()); } + @Override + public byte[] takeScreenshot() { + return ((TakesScreenshot)DriverService.getWrappedDriver()).getScreenshotAs(OutputType.BYTES); + } + @Override public String takeScreenshot(String name) { var screenshotSaveDir = getOutputFolder(); diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/services/App.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/services/App.java index e66a4920..82f8dd0c 100644 --- a/bellatrix.web/src/main/java/solutions/bellatrix/web/services/App.java +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/services/App.java @@ -22,31 +22,31 @@ public class App implements BellatrixApp { private boolean disposed = false; public NavigationService navigate() { - return new NavigationService(); + return SingletonFactory.getInstance(NavigationService.class); } public BrowserService browser() { - return new BrowserService(); + return SingletonFactory.getInstance(BrowserService.class); } public CookiesService cookies() { - return new CookiesService(); + return SingletonFactory.getInstance(CookiesService.class); } public DialogService dialogs() { - return new DialogService(); + return SingletonFactory.getInstance(DialogService.class); } public JavaScriptService script() { - return new JavaScriptService(); + return SingletonFactory.getInstance(JavaScriptService.class); } public ComponentCreateService create() { - return new ComponentCreateService(); + return SingletonFactory.getInstance(ComponentCreateService.class); } public ComponentWaitService waitFor() { - return new ComponentWaitService(); + return SingletonFactory.getInstance(ComponentWaitService.class); } @Override diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/services/BrowserService.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/services/BrowserService.java index 12e1bd7f..7f4c80a5 100644 --- a/bellatrix.web/src/main/java/solutions/bellatrix/web/services/BrowserService.java +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/services/BrowserService.java @@ -43,11 +43,12 @@ import java.util.logging.Level; public class BrowserService extends WebService { - private final JavascriptExecutor javascriptExecutor; - public BrowserService() { super(); - javascriptExecutor = (JavascriptExecutor)getWrappedDriver(); + } + + public JavascriptExecutor getJavascriptExecutor() { + return (JavascriptExecutor)getWrappedDriver(); } public String getPageSource() { @@ -66,6 +67,14 @@ public void back() { getWrappedDriver().navigate().back(); } + public void setSize(int width, int height) { + setSize(new Dimension(width, height)); + } + + public void setSize(Dimension dimension) { + getWrappedDriver().manage().window().setSize(dimension); + } + public void maximize() { getWrappedDriver().manage().window().maximize(); } @@ -136,36 +145,36 @@ public void switchToFrame(Frame frame) { } public void clearSessionStorage() { - ((JavascriptExecutor)getWrappedDriver()).executeScript("sessionStorage.clear()"); + getJavascriptExecutor().executeScript("sessionStorage.clear()"); } public void removeItemFromLocalStorage(String item) { - ((JavascriptExecutor)getWrappedDriver()).executeScript(String.format("window.localStorage.removeItem('%s');", item)); + getJavascriptExecutor().executeScript(String.format("window.localStorage.removeItem('%s');", item)); } public void scrollToBottom() { - ((JavascriptExecutor)getWrappedDriver()).executeScript("window.scrollTo(0, document.body.scrollHeight)"); + getJavascriptExecutor().executeScript("window.scrollTo(0, document.body.scrollHeight)"); } public void scrollToTop() { - ((JavascriptExecutor)getWrappedDriver()).executeScript("window.scrollTo(0, 0)"); + getJavascriptExecutor().executeScript("window.scrollTo(0, 0)"); } public boolean isItemPresentInLocalStorage(String item) { - return !(((JavascriptExecutor)getWrappedDriver()).executeScript(String.format("return window.localStorage.getItem('%s');", item)) == null); + return !(getJavascriptExecutor().executeScript(String.format("return window.localStorage.getItem('%s');", item)) == null); } public String getItemFromLocalStorage(String key) { - return (String)((JavascriptExecutor)getWrappedDriver()).executeScript(String.format("return window.localStorage.getItem('%s');", key)); + return (String)getJavascriptExecutor().executeScript(String.format("return window.localStorage.getItem('%s');", key)); } public void setItemInLocalStorage(String item, String value) { - ((JavascriptExecutor)getWrappedDriver()).executeScript(String.format("window.localStorage.setItem('%s','%s');", item, value)); + getJavascriptExecutor().executeScript(String.format("window.localStorage.setItem('%s','%s');", item, value)); } public void clearLocalStorage() { - ((JavascriptExecutor)getWrappedDriver()).executeScript("localStorage.clear()"); + getJavascriptExecutor().executeScript("localStorage.clear()"); } public List getBrowserLogs() { @@ -210,17 +219,16 @@ public List getSevereLogEntries() { } public List getRequestEntries(String partialUrl) { - return (List)((JavascriptExecutor)getWrappedDriver()).executeScript(String.format("return window.performance.getEntriesByType('resource').filter(x => x.name.indexOf('%s') >= 0).map(y => y.name);", partialUrl)); + return (List)getJavascriptExecutor().executeScript(String.format("return window.performance.getEntriesByType('resource').filter(x => x.name.indexOf('%s') >= 0).map(y => y.name);", partialUrl)); } public void waitForAjax() { long ajaxTimeout = ConfigurationService.get(WebSettings.class).getTimeoutSettings().getWaitForAjaxTimeout(); long sleepInterval = ConfigurationService.get(WebSettings.class).getTimeoutSettings().getSleepInterval(); - var javascriptExecutor = (JavascriptExecutor)getWrappedDriver(); AtomicInteger ajaxConnections = new AtomicInteger(); try { Wait.retry(() -> { - var numberOfAjaxConnections = javascriptExecutor.executeScript("return !isNaN(window.$openHTTPs) ? window.$openHTTPs : null"); + var numberOfAjaxConnections = getJavascriptExecutor().executeScript("return !isNaN(window.$openHTTPs) ? window.$openHTTPs : null"); if (Objects.nonNull(numberOfAjaxConnections)) { ajaxConnections.set(Integer.parseInt(numberOfAjaxConnections.toString())); if (ajaxConnections.get() > 0) { @@ -246,7 +254,7 @@ public void waitForAjax() { } private void monkeyPatchXMLHttpRequest() { - var numberOfAjaxConnections = javascriptExecutor.executeScript(("return !isNaN(window.$openHTTPs) ? window.$openHTTPs : null")); + var numberOfAjaxConnections = getJavascriptExecutor().executeScript(("return !isNaN(window.$openHTTPs) ? window.$openHTTPs : null")); if (Objects.isNull(numberOfAjaxConnections)) { var script = "(function() {" + @@ -263,7 +271,7 @@ private void monkeyPatchXMLHttpRequest() { "}" + "})();"; - javascriptExecutor.executeScript(script); + getJavascriptExecutor().executeScript(script); } } @@ -273,7 +281,7 @@ public void waitForAjaxRequest(String requestPartialUrl, int additionalTimeoutIn var webDriverWait = new WebDriverWait(getWrappedDriver(), Duration.ofSeconds(ajaxTimeout + additionalTimeoutInSeconds), Duration.ofSeconds(sleepInterval)); webDriverWait.until(d -> { String script = String.format("return performance.getEntriesByType('resource').filter(item => item.initiatorType == 'xmlhttprequest' && item.name.toLowerCase().includes('%s'))[0] !== undefined;", requestPartialUrl); - boolean result = (boolean)javascriptExecutor.executeScript(script); + boolean result = (boolean)getJavascriptExecutor().executeScript(script); return result; }); } @@ -375,8 +383,8 @@ public void waitForReactPageLoadsCompletely() { long waitUntilReadyTimeout = ConfigurationService.get(WebSettings.class).getTimeoutSettings().getWaitUntilReadyTimeout(); long sleepInterval = ConfigurationService.get(WebSettings.class).getTimeoutSettings().getSleepInterval(); var webDriverWait = new WebDriverWait(getWrappedDriver(), Duration.ofSeconds(waitUntilReadyTimeout), Duration.ofSeconds(sleepInterval)); - webDriverWait.until(d -> javascriptExecutor.executeScript("return document.querySelector('[data-reactroot]') !== null")); - webDriverWait.until(d -> javascriptExecutor.executeScript("return window.performance.timing.loadEventEnd > 0")); + webDriverWait.until(d -> getJavascriptExecutor().executeScript("return document.querySelector('[data-reactroot]') !== null")); + webDriverWait.until(d -> getJavascriptExecutor().executeScript("return window.performance.timing.loadEventEnd > 0")); } // TODO Refactor the other methods to reuse this one @@ -406,7 +414,7 @@ public void waitForJavaScriptAnimations() { long waitForJavaScriptAnimationsTimeout = ConfigurationService.get(WebSettings.class).getTimeoutSettings().getWaitForJavaScriptAnimationsTimeout(); long sleepInterval = ConfigurationService.get(WebSettings.class).getTimeoutSettings().getSleepInterval(); var webDriverWait = new WebDriverWait(getWrappedDriver(), Duration.ofSeconds(waitForJavaScriptAnimationsTimeout), Duration.ofSeconds(sleepInterval)); - webDriverWait.until(d -> (boolean)javascriptExecutor.executeScript("return jQuery && jQuery(':animated').length === 0")); + webDriverWait.until(d -> (boolean)getJavascriptExecutor().executeScript("return jQuery && jQuery(':animated').length === 0")); } public void waitForPartialUrl(String partialUrl) { @@ -424,11 +432,10 @@ public void waitNumberOfWindowsToBe(int numberOfWindows) { } public void waitForRequest(String partialUrl) { - var javascriptExecutor = (JavascriptExecutor)getWrappedDriver(); String script = String.format("return performance.getEntriesByType('resource').filter(item => item.name.toLowerCase().includes('%s'))[0] !== undefined;", partialUrl); try { - waitUntil(e -> (boolean)javascriptExecutor.executeScript(script)); + waitUntil(e -> (boolean)getJavascriptExecutor().executeScript(script)); } catch (TimeoutException exception) { throw new TimeoutException(String.format("The expected request with URL '%s' is not loaded!", partialUrl)); } @@ -439,9 +446,8 @@ public void tryWaitForResponse(String partialUrl, int additionalTimeoutInSeconds if(ProxyServer.get() != null) { ProxyServer.waitForResponse(getWrappedDriver(), partialUrl, HttpMethod.GET, 0); } else { - var javascriptExecutor = (JavascriptExecutor)getWrappedDriver(); String script = "return performance.getEntriesByType('resource').filter(item => item.name.toLowerCase().includes('" + partialUrl.toLowerCase() + "'))[0] !== undefined;"; - waitUntil(e -> (boolean)javascriptExecutor.executeScript(script)); + waitUntil(e -> (boolean)getJavascriptExecutor().executeScript(script)); } } catch (Exception exception) { Log.error("The expected request with URL '%s' is not loaded!", partialUrl); @@ -457,15 +463,15 @@ public void waitForAngular() { long sleepInterval = ConfigurationService.get(WebSettings.class).getTimeoutSettings().getSleepInterval(); var webDriverWait = new WebDriverWait(getWrappedDriver(), Duration.ofSeconds(angularTimeout), Duration.ofSeconds(sleepInterval)); - String isAngular5 = (String)javascriptExecutor.executeScript("return getAllAngularRootElements()[0].attributes['ng-version']"); + String isAngular5 = (String)getJavascriptExecutor().executeScript("return getAllAngularRootElements()[0].attributes['ng-version']"); if (StringUtils.isBlank(isAngular5)) { - webDriverWait.until(d -> (boolean)javascriptExecutor.executeScript("return window.getAllAngularTestabilities().findIndex(x=>!x.isStable()) === -1")); + webDriverWait.until(d -> (boolean)getJavascriptExecutor().executeScript("return window.getAllAngularTestabilities().findIndex(x=>!x.isStable()) === -1")); } else { - boolean isAngularDefined = (boolean)javascriptExecutor.executeScript("return window.angular === undefined"); + boolean isAngularDefined = (boolean)getJavascriptExecutor().executeScript("return window.angular === undefined"); if (!((boolean)isAngularDefined)) { - boolean isAngularInjectorUnDefined = (boolean)javascriptExecutor.executeScript("return angular.element(document).injector() === undefined"); + boolean isAngularInjectorUnDefined = (boolean)getJavascriptExecutor().executeScript("return angular.element(document).injector() === undefined"); if (!isAngularInjectorUnDefined) { - webDriverWait.until(d -> (boolean)javascriptExecutor.executeScript("return angular.element(document).injector().get('$http').pendingRequests.length === 0")); + webDriverWait.until(d -> (boolean)getJavascriptExecutor().executeScript("return angular.element(document).injector().get('$http').pendingRequests.length === 0")); } } } diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/services/ComponentCreateService.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/services/ComponentCreateService.java index 214e1ab4..f94dd512 100644 --- a/bellatrix.web/src/main/java/solutions/bellatrix/web/services/ComponentCreateService.java +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/services/ComponentCreateService.java @@ -14,6 +14,8 @@ package solutions.bellatrix.web.services; import solutions.bellatrix.core.utilities.InstanceFactory; +import solutions.bellatrix.plugins.opencv.Base64Encodable; +import solutions.bellatrix.web.components.ActionImage; import solutions.bellatrix.web.components.WebComponent; import solutions.bellatrix.web.findstrategies.*; import solutions.bellatrix.web.infrastructure.DriverService; @@ -36,6 +38,10 @@ public TComponent byId(Class compo return by(componentClass, new IdFindStrategy(id)); } + public TComponent byImage(Class componentClass, Base64Encodable encodedImage) { + return by(componentClass, new ImageBase64FindStrategy(encodedImage)); + } + public TComponent byAttributeContaining(Class componentClass, String attributeName, String value) { return by(componentClass, new AttributeContainingWithFindStrategy(attributeName, value)); } @@ -96,6 +102,10 @@ public List allById(Class List allByImage(Class componentClass, Base64Encodable encodedImage) { + return allBy(componentClass, new ImageBase64FindStrategy(encodedImage)); + } + public List allByAttributeContaining(Class componentClass, String attributeName, String value) { return allBy(componentClass, new AttributeContainingWithFindStrategy(attributeName, value)); } diff --git a/bellatrix.web/src/main/java/solutions/bellatrix/web/services/JavaScriptService.java b/bellatrix.web/src/main/java/solutions/bellatrix/web/services/JavaScriptService.java index f30b785f..b0ba2e29 100644 --- a/bellatrix.web/src/main/java/solutions/bellatrix/web/services/JavaScriptService.java +++ b/bellatrix.web/src/main/java/solutions/bellatrix/web/services/JavaScriptService.java @@ -18,16 +18,17 @@ import solutions.bellatrix.web.components.WebComponent; public class JavaScriptService extends WebService { - private final JavascriptExecutor javascriptExecutor; - public JavaScriptService() { super(); - javascriptExecutor = (JavascriptExecutor)getWrappedDriver(); + } + + public JavascriptExecutor getJavascriptExecutor() { + return (JavascriptExecutor)getWrappedDriver(); } public T genericExecute(String script, Object... args) { try { - T result = (T)javascriptExecutor.executeScript(script, args); + T result = (T)getJavascriptExecutor().executeScript(script, args); return result; } catch (Exception ex) { DebugInformation.printStackTrace(ex); @@ -37,7 +38,7 @@ public T genericExecute(String script, Object... args) { public Object execute(String script) { try { - var result = javascriptExecutor.executeScript(script); + var result = getJavascriptExecutor().executeScript(script); return result; } catch (Exception ex) { DebugInformation.printStackTrace(ex); @@ -54,7 +55,7 @@ public String execute(String frameName, String script) { public String execute(String script, Object... args) { try { - var result = (String)javascriptExecutor.executeScript(script, args); + var result = (String)getJavascriptExecutor().executeScript(script, args); return result; } catch (Exception ex) { DebugInformation.printStackTrace(ex); @@ -69,7 +70,7 @@ public String execute(String script, TComponen public String execute(String script, WebElement nativeElement) { try { - var result = (String)javascriptExecutor.executeScript(script, nativeElement); + var result = (String)getJavascriptExecutor().executeScript(script, nativeElement); return result; } catch (NoSuchSessionException | NoSuchWindowException ex) { throw ex; diff --git a/framework-tests/bellatrix.android.tests/src/main/resources/testFrameworkSettings.dev.json b/framework-tests/bellatrix.android.tests/src/main/resources/testFrameworkSettings.dev.json index b0e1c1f8..0487588e 100644 --- a/framework-tests/bellatrix.android.tests/src/main/resources/testFrameworkSettings.dev.json +++ b/framework-tests/bellatrix.android.tests/src/main/resources/testFrameworkSettings.dev.json @@ -19,6 +19,7 @@ "screenshotsSaveLocation": "${user.home}/BELLATRIX/videos", "videosOnFailEnabled": "false", "videosSaveLocation": "u${user.home}/BELLATRIX/videos", + "allowImageFindStrategies": "true", "timeoutSettings": { "implicitWaitTimeout": "5", "elementWaitTimeout": "30", diff --git a/framework-tests/bellatrix.android.tests/src/main/resources/testFrameworkSettings.qa.json b/framework-tests/bellatrix.android.tests/src/main/resources/testFrameworkSettings.qa.json index b0e1c1f8..0487588e 100644 --- a/framework-tests/bellatrix.android.tests/src/main/resources/testFrameworkSettings.qa.json +++ b/framework-tests/bellatrix.android.tests/src/main/resources/testFrameworkSettings.qa.json @@ -19,6 +19,7 @@ "screenshotsSaveLocation": "${user.home}/BELLATRIX/videos", "videosOnFailEnabled": "false", "videosSaveLocation": "u${user.home}/BELLATRIX/videos", + "allowImageFindStrategies": "true", "timeoutSettings": { "implicitWaitTimeout": "5", "elementWaitTimeout": "30", diff --git a/framework-tests/bellatrix.desktop.tests/src/main/resources/testFrameworkSettings.dev.json b/framework-tests/bellatrix.desktop.tests/src/main/resources/testFrameworkSettings.dev.json index a35f42aa..6f7aedd3 100644 --- a/framework-tests/bellatrix.desktop.tests/src/main/resources/testFrameworkSettings.dev.json +++ b/framework-tests/bellatrix.desktop.tests/src/main/resources/testFrameworkSettings.dev.json @@ -25,7 +25,8 @@ "elementToNotExistTimeout": "30", "elementToBeClickableTimeout": "30", "elementNotToBeVisibleTimeout": "30", - "elementToHaveContentTimeout": "15" + "elementToHaveContentTimeout": "15", + "allowImageFindStrategies": "true" }, "gridSettings": [ { diff --git a/framework-tests/bellatrix.desktop.tests/src/main/resources/testFrameworkSettings.qa.json b/framework-tests/bellatrix.desktop.tests/src/main/resources/testFrameworkSettings.qa.json index a35f42aa..6f7aedd3 100644 --- a/framework-tests/bellatrix.desktop.tests/src/main/resources/testFrameworkSettings.qa.json +++ b/framework-tests/bellatrix.desktop.tests/src/main/resources/testFrameworkSettings.qa.json @@ -25,7 +25,8 @@ "elementToNotExistTimeout": "30", "elementToBeClickableTimeout": "30", "elementNotToBeVisibleTimeout": "30", - "elementToHaveContentTimeout": "15" + "elementToHaveContentTimeout": "15", + "allowImageFindStrategies": "true" }, "gridSettings": [ { diff --git a/framework-tests/bellatrix.ios.tests/src/main/resources/testFrameworkSettings.dev.json b/framework-tests/bellatrix.ios.tests/src/main/resources/testFrameworkSettings.dev.json index b87c0157..db16647b 100644 --- a/framework-tests/bellatrix.ios.tests/src/main/resources/testFrameworkSettings.dev.json +++ b/framework-tests/bellatrix.ios.tests/src/main/resources/testFrameworkSettings.dev.json @@ -28,7 +28,8 @@ "elementToNotExistTimeout": "30", "elementToBeClickableTimeout": "30", "elementNotToBeVisibleTimeout": "30", - "elementToHaveContentTimeout": "15" + "elementToHaveContentTimeout": "15", + "allowImageFindStrategies": "true" }, "gridSettings": [ { diff --git a/framework-tests/bellatrix.ios.tests/src/main/resources/testFrameworkSettings.qa.json b/framework-tests/bellatrix.ios.tests/src/main/resources/testFrameworkSettings.qa.json index b87c0157..db16647b 100644 --- a/framework-tests/bellatrix.ios.tests/src/main/resources/testFrameworkSettings.qa.json +++ b/framework-tests/bellatrix.ios.tests/src/main/resources/testFrameworkSettings.qa.json @@ -28,7 +28,8 @@ "elementToNotExistTimeout": "30", "elementToBeClickableTimeout": "30", "elementNotToBeVisibleTimeout": "30", - "elementToHaveContentTimeout": "15" + "elementToHaveContentTimeout": "15", + "allowImageFindStrategies": "true" }, "gridSettings": [ { diff --git a/framework-tests/bellatrix.playwright.tests/src/test/java/opencv/OpenCvTests.java b/framework-tests/bellatrix.playwright.tests/src/test/java/opencv/OpenCvTests.java new file mode 100644 index 00000000..00277b65 --- /dev/null +++ b/framework-tests/bellatrix.playwright.tests/src/test/java/opencv/OpenCvTests.java @@ -0,0 +1,89 @@ +package opencv; + +import com.microsoft.playwright.Keyboard; +import com.microsoft.playwright.Locator; +import com.microsoft.playwright.options.ViewportSize; +import opencv.data.EncodedImageDemo; +import opencv.data.EncodedImageNavigationDemo; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; +import solutions.bellatrix.core.utilities.DebugInformation; +import solutions.bellatrix.playwright.components.*; +import solutions.bellatrix.playwright.infrastructure.BrowserTypes; +import solutions.bellatrix.playwright.infrastructure.ExecutionBrowser; +import solutions.bellatrix.playwright.infrastructure.Lifecycle; +import solutions.bellatrix.playwright.infrastructure.junit.WebTest; + +@ExecutionBrowser(browser = BrowserTypes.CHROME, lifecycle = Lifecycle.REUSE_IF_STARTED) +public class OpenCvTests extends WebTest { + @Override + public void beforeEach() throws Exception { + super.beforeEach(); + app().browser().setSize(1920, 1080); + } + + @Test + public void actionPerformed_when_convertBase64ToImage_and_clickImage() { + app().navigate().to("http://demos.bellatrix.solutions/"); + + var falcon9Image = app().create().byImage(Anchor.class, EncodedImageDemo.FALCON_9); + + falcon9Image.click(); + + app().browser().assertUrlPath("/product/falcon-9/"); + } + + @Test + public void actionPerformed_when_convertBase64ToImage_and_dragAndDropImage() { + app().navigate().to("https://demos.bellatrix.solutions/2018/04/06/proton-rocket-family/"); + + var emailNotes = app().create().byId(Span.class, "email-notes"); + var commentTextArea = app().create().byId(TextArea.class, "comment"); + var falcon9BackButtonImage = app().create().byImage(ActionImage.class, EncodedImageDemo.FALCON_9_BACK_BUTTON); + var commentTextAreaImage = app().create().byImage(ActionImage.class, EncodedImageDemo.COMMENT_TEXT_AREA); + + emailNotes.scrollToVisible(); + falcon9BackButtonImage.dragAndDrop(commentTextAreaImage); + + commentTextArea.validateTextIs("https://demos.bellatrix.solutions/2018/04/06/hello-world/"); + } + + @Test + public void actionPerformed_when_convertBase64ToImage_and_clickButton() { + app().navigate().to("http://demos.bellatrix.solutions/"); + + Button falcon9Image = app().create().byImage(Button.class, EncodedImageDemo.FALCON_9); + + falcon9Image.click(); + + app().browser().assertUrlPath("/product/falcon-9/"); + } + + @Test + public void actionPerformed_when_locateComplexComponents() { + app().navigate().to("http://demos.bellatrix.solutions/"); + + SearchField websiteSearch = app().create().byImage(SearchField.class, EncodedImageDemo.SEARCH_INPUT); + + DebugInformation.debugInfo(websiteSearch.getPlaceholder()); + + websiteSearch.setSearch("Falcon"); + websiteSearch.getWrappedElement().press("Enter", new Locator.PressOptions().setDelay(1500)); + + app().browser().assertUrlPath("?s=Falcon&post_type=product"); + app().create().byImage(ActionImage.class, EncodedImageDemo.FALCON_RESULTS).validateIsVisible(); + } + + @ParameterizedTest + @EnumSource(EncodedImageNavigationDemo.class) + public void actionPerformed_when_locateButtonComponents(EncodedImageNavigationDemo navigationItem) { + app().navigate().to("http://demos.bellatrix.solutions/"); + + Button navgationButton = app().create().byImage(Button.class, navigationItem); + + navgationButton.click(); + + app().browser().validateLandedOnPage(navigationItem.getExpectedUrl()); + } +} \ No newline at end of file diff --git a/framework-tests/bellatrix.playwright.tests/src/test/java/opencv/data/EncodedImageDemo.java b/framework-tests/bellatrix.playwright.tests/src/test/java/opencv/data/EncodedImageDemo.java new file mode 100644 index 00000000..a891aae8 --- /dev/null +++ b/framework-tests/bellatrix.playwright.tests/src/test/java/opencv/data/EncodedImageDemo.java @@ -0,0 +1,63 @@ +package opencv.data; + +import solutions.bellatrix.plugins.opencv.Base64Encodable; + +public enum EncodedImageDemo implements Base64Encodable { + /** + * + */ + FALCON_9("falcon9", ImageInBase64.falcon9, 50, 25), + /** + * + */ + SEARCH_INPUT("searchInput", ImageInBase64.searchInput), + /** + * + */ + FALCON_RESULTS("falconResults", ImageInBase64.falconResults), + /** + * + */ + FALCON_9_BACK_BUTTON("falcon9BackButton", ImageInBase64.falcon9BackButton), + /** + * + */ + COMMENT_TEXT_AREA("commentTextArea", ImageInBase64.commentTextArea); + + private final String imageName; + private final String encodedImage; + private int xOffset = 0; + private int yOffset = 0; + + EncodedImageDemo(String imageName, String encodedImage, int xOffset, int yOffset) { + this.imageName = imageName; + this.encodedImage = encodedImage; + this.xOffset = xOffset; + this.yOffset = yOffset; + } + + EncodedImageDemo(String imageName, String encodedImage) { + this.imageName = imageName; + this.encodedImage = encodedImage; + } + + @Override + public String getBase64Image() { + return encodedImage; + } + + @Override + public String getImageName() { + return imageName; + } + + @Override + public int getXOffset() { + return xOffset; + } + + @Override + public int getYOffset() { + return yOffset; + } +} diff --git a/framework-tests/bellatrix.playwright.tests/src/test/java/opencv/data/EncodedImageNavigationDemo.java b/framework-tests/bellatrix.playwright.tests/src/test/java/opencv/data/EncodedImageNavigationDemo.java new file mode 100644 index 00000000..895cb378 --- /dev/null +++ b/framework-tests/bellatrix.playwright.tests/src/test/java/opencv/data/EncodedImageNavigationDemo.java @@ -0,0 +1,61 @@ +package opencv.data; + +import lombok.Getter; +import solutions.bellatrix.plugins.opencv.Base64Encodable; + +public enum EncodedImageNavigationDemo implements Base64Encodable { + /** + * + */ + HOME_LABEL("homeLabel", NavigationImageInBase64.homeLabel, "https://demos.bellatrix.solutions/"), + /** + * + */ + BLOG_LABEL("blogLabel", NavigationImageInBase64.blogLabel, "/blog/"), + /** + * + */ + CHECKOUT_LABEL("checkoutLabel", NavigationImageInBase64.checkoutLabel, "/cart/"), + /** + * + */ + CONTACT_FORM_LABEL("contactFormLabel", NavigationImageInBase64.contactFormLabel, "/contact-form/"), + /** + * + */ + MY_ACCOUNT_LABEL("myAccountLabel", NavigationImageInBase64.myAccountLabel, "/my-account/"), + /** + * + */ + PROMOTIONS_LABEL("promotionsLabel", NavigationImageInBase64.promotionsLabel, "/welcome/"); + + private final String imageName; + private final String encodedImage; + @Getter private final String expectedUrl; + + EncodedImageNavigationDemo(String imageName, String encodedImage, String expectedUrl) { + this.imageName = imageName; + this.encodedImage = encodedImage; + this.expectedUrl = expectedUrl; + } + + @Override + public String getBase64Image() { + return encodedImage; + } + + @Override + public String getImageName() { + return imageName; + } + + @Override + public int getXOffset() { + return 0; + } + + @Override + public int getYOffset() { + return 0; + } +} diff --git a/framework-tests/bellatrix.playwright.tests/src/test/java/opencv/data/ImageInBase64.java b/framework-tests/bellatrix.playwright.tests/src/test/java/opencv/data/ImageInBase64.java new file mode 100644 index 00000000..2267eabd --- /dev/null +++ b/framework-tests/bellatrix.playwright.tests/src/test/java/opencv/data/ImageInBase64.java @@ -0,0 +1,24 @@ +package opencv.data; + +public class ImageInBase64 { + /** + * + */ + public static final String falcon9BackButton = "data:image/png;base64,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"; + /** + * + */ + public static final String commentTextArea = "data:image/png;base64,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"; + /** + * + */ + public static final String falcon9 = "data:image/png;base64,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"; + /** + * + */ + public static final String searchInput = "data:image/png;base64,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"; + /** + * + */ + public static final String falconResults = "data:image/png;base64,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"; +} diff --git a/framework-tests/bellatrix.playwright.tests/src/test/java/opencv/data/NavigationImageInBase64.java b/framework-tests/bellatrix.playwright.tests/src/test/java/opencv/data/NavigationImageInBase64.java new file mode 100644 index 00000000..fa7344ff --- /dev/null +++ b/framework-tests/bellatrix.playwright.tests/src/test/java/opencv/data/NavigationImageInBase64.java @@ -0,0 +1,29 @@ +package opencv.data; + +public class NavigationImageInBase64 { + /** + * + */ + public static final String homeLabel = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEMAAAAkCAIAAABdWRDGAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAASdEVYdFNvZnR3YXJlAEdyZWVuc2hvdF5VCAUAAAIHSURBVFhH7ZUxa9tAFID7nx4ItB0UBB0EhRqDDwz11Cz1VJFBdBGGoiFoqehQXAiiQ5eiTC4YDwVlUYZiQ8EFo0DghsJBQJDhwKDena9Rmgw9B0GP9D4k0Ht3euK7k54eNQ8Fa2Ie1sQ8rIl5WBPzsCbmYU3M478zWeeTKP+hAgkt3kfTU6oiA9A0KUKA8KsKJCQbAD4mKjIAa3LbhFUn4eixC+Ci52G+YSpNPo376fKySIYIANAwKeumXmXBUxcchI94dA0j8xiLWbxCUlyqrD7dmFTHGBycnhFKSflu5Do4O5cDFxkGz+uPMz60yQMP0LNe72VWEkrmIY/iMzmNl/vIJwb5pmaMlm8xDLJ9t3sPk7sok6tF4MD45Hp969krgMOF2Bdh0pvurLjwhx70p9V2F91Yi20ROq1V0yxj1N6lSRd78j31AWcXMi0hfIv8dM2vhEk7JPLtYt+q4B9MokgdAX/N/nzc3+nC5FuM7pqgeMmvNE1EhVHyZbGYt8f6p5ylTRcmND+48cZzyjcIXuTiX6NpIir4yUqm70snXzwrJh4MkqVsOPUqxY4Xncr2pWmyqzDkXU5GW1ad7/3P7cSEP5vOXvuiB4vTDz5XKq9r0lZATzzkuP7h7PeALpomelzVlNZMtaZ7wXgFXkJFe9GpyT/FmpiHNTEPa2Ie1sQ8HopJ0/wC1fAUHISDjIsAAAAASUVORK5CYII="; + /** + * + */ + public static final String blogLabel = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAAkCAIAAABaG87TAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAASdEVYdFNvZnR3YXJlAEdyZWVuc2hvdF5VCAUAAAJnSURBVFhH7Zbfp9tgGMf3Pz2E9y6M3IXDapxwOLGLc4xTRmOc6E2UIxdTo7GrjYqxKpNeTEu9o6RMz8XRMXIxKSUXh5cSevFSsje/lhy72JKusVo+Et7nfS/6eZvv+ySPgiOklq6KWroqaumqqKWr4n+Wvnfw1CFJcXAKSDsfNa0TXsYQ4+nC9WmywJipAKqdFAengLTdBji5jL3V5yICJH/wkrV/WrqdiZGhDLy+jItjkQ4+q8BpSf1Qmn631HMeAaDHsjpysxjt3HFbjhZ4MeZqkD6sApSTpr63MM5A7DlR+VB6ZUocSL2FR4h3a8gIpL4bLVC7zfMty2Ob2Cy7p6g5dMkmdzD+mILSeZ5oeJ3+ZCZN8UuAK8uPphn+RAFOwVs2tDUO1Fk8HXh9CS6scg2nbDyo744UgZPMVVRm0o4hsr8298zXpgSi8Y2NHOMElEmyT6cnwjWOx0XZI9MBHbfShGTSS53/VZrX78KhP1MFJHc/YTzUGijdcHH2kSaDZ9B4F+U1kybWBfA3i3AYc8t2cRnnwHsvSa8x7neNoe1sotVSlJSmG9d+JQGLxzqqcweRzjUBpO5dlGp/yc6r0LGjTHjmKTRHP9NenrIHkeOFcz07iPfWJQeok2yJTFT27gEU3mLLcnfxdOBPFTaVgvinivm1zB4KSP+GrU/yL/Yd9Qnxw6aRslvqgvR2RemGRHjjax7OzMP26X35oiPRSBt7iPNGLNf1KpTe2izswgtjPGXfW3hw00BC0yrVQCqUZlDizAdG+MllDOYOyaWpENVK/yVq6aqopauilq6KWroqjlA6CH4A7B4rEaIvT3wAAAAASUVORK5CYII="; + /** + * + */ + public static final String checkoutLabel = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEQAAAAqCAIAAACFj2rPAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAASdEVYdFNvZnR3YXJlAEdyZWVuc2hvdF5VCAUAAAH/SURBVGhD7ZWxS+RAFIf9nx4E0g0cBK5IdWHBAQur3UYrg3DhmrAgUZY0ilgoLKm2OXLVHsgKQmzWagthbbKwkGJhQBixCCzMTcYRT2VhbyPcU+ar8nuZFB/vzcua+EQYGawYGawYGawYGawYGawYGawYGawYmVc85Fk3Dtth2D5Kb7ku/g/qyvDryLPAbvhxt5d0fM8G7yzX75bkKoT1pNChFvVkeN+3gJ7lpc5C3OXFv/bmMkAhU3QpkGg41/EF8zI/j1vfCEgIjS6Yrhe97cbRaDaINghYwcmB636xwSKOK4mH+tCK1JEp+zsA7UynV/B+2IzTm4Ixlv/0idVKZ6o+TShQukHjq5zN+D1no0MPpJ48x/hzh1eijkyRrAPtLjMgWWhBcKkeKxnwfz/PYtVeBGNWybiHY53eUrLxeRLvbLouseFJW3UmmaoDCiQyImsDNNOn2/CSabrt2N5eOi7k8PzVQ7Qy4joiQE8nOmnUPhjtE/g+UFnyIWQEz3444PjpRF3dkg2PN0mzJ3tVyWylvBIri1+BIzf4AhlxEYDl99/jZ1tTRvaBDfYosaoNLLEb0eBxa03kmMml7BBCaCfr7S6WmY/ir/JLQuzWgpFdltoyj8xL/na1quJy61adfNBhZd5JBgdGBitGBitGBitGBitGBitGBiufSEaIP52unQiECIP2AAAAAElFTkSuQmCC"; + /** + * + */ + public static final String contactFormLabel = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAG4AAAAiCAIAAAAxo3u7AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAASdEVYdFNvZnR3YXJlAEdyZWVuc2hvdF5VCAUAAAPVSURBVGhD7ZbPh+NQHMD3f3qE3B5L6CEME2XDHGoPU8uWZWIO0UuV1aFy2ehphoo91DJy6zCyLBlGeqgMQ5eRYchhCSXMIZTs972kP2amTduZp7uH99FDv+/nN5+8H3mXchjBVTKDq2QGV8kMrpIZXCUzuEpmcJXM4CqZwVUyg6tkBlfJjM1UPgZu12g0G42maf+O88L/idE55PbkZ//Oq3bGepXxoKUISCxrRrdntTVFRMpZkNe9gqsG+mCFebAtbkNQrYc8WMStI7RX/b9Vxn1NQOpZkORxmo6D8C3r8pf+FpU6Wq2y7ubBP2KNyrCrItzyJnn4nLFrflKwgBBWqh03njW7NuTjfvjgtA4wgsoDw6P2vbYsvxeRgCUZMLw0TSKvV69gEVqJ8pHlz19SEl62KtAYuu9r1k1MxpRJQ1yina/zdhkrVRZmGNxY2p6IyqdBGvY+K+YwdtsqbawagziNfetIJjNO8y+mWGXSP0KoueJtx64uIenYDqIourP1EpLqbj4jLD0sSeWGcxdFoQPN8FfwliZx5H9TUNn0oUsUw0ofdWp61yUjhJ7xAUknfjZA+F1FgtK4JDXBpWH+jEnnoakgeOBp5wWWqyzOUFbVfa13G4YRlIUWzC4pta4XRoF9DBkrSrlmDcLF/IspVkkmULvLt+OoIyPZ8Gfv+daE2MxOKEgU6c60KjhTZpuaLPMVG5zoy6omri6gyo8oK5/zYKkFG1zEZLlmtMmTr8tQNm/pfwJ50vkdcH8K7+z0Lo8Kcl5kvUr52yiPnkAX7JOFAAcZ0i7oaqEqZ3WLqbxMK7n3eh29WpYlchjQXuSZlykrVnncJ8s1gyzaLTLMnnS+aJ5OxERl6jYROrRfLA8gsg+XJFo9p203VZn4bUUs1cyrIH5c6DVs4VeofL7Bt8hwFyrTAXmq0/s8yqFbxj/B6GNvbvlPrwI31JD+31BlZFdhH80Gn/Ui5Uj/lZUusJ3KLTLciUo4uutwdGv2Pd0XcON2KviQ5gfzCVg7D0nFJOrDUX0wnW+1yvSnjgStnx3+RJlsDOnIY9/8CLdl1itxmzCp7oxJAFXOgAqZODCudrHkNl1+7Wyc4W5UkiScr/QTgSKWW86fvCa+MatwwIni8y+GApUT3yiRKwKLVTuKvROFBCWM97TeBVzQ016TwP4ikelgbEGqfR9R36nfhkIRvxfzfTplucqNM9yVyowJfIy8+AYhrCovgHQhh+MsGK/o/kgaJrMrmFLUfjmvyPA1bKySsw6ukhlcJTO4SmZwlczgKpnBVTKDq2QGV8kMrpIRafoXhEVgioTlfegAAAAASUVORK5CYII="; + /** + * + */ + public static final String myAccountLabel = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAAAgCAIAAAAdc/jyAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAASdEVYdFNvZnR3YXJlAEdyZWVuc2hvdF5VCAUAAAOSSURBVGhD7ZbRZyNBGMDvfxrCvg1l6cNQukpDudWHRmmessJFX+qIlNqXrjylxD5FiO3DSakcx5STPlRK2XK2hH0oy7HkIYS9b2Y3yU6STXLtubvW/h5i55vd2ZnffvNNPgQpMVIdAqkOgVSHQKpDINUhkOoQSHUIpDoEEnR4tPb5xLwbRs0QHqzdeFHzPZKgo29mEUKFdtyH11Qhlq27UfuN4Zp7qPQtaiSRrGMnm83krGkqeI19rH5U3rCO3dfoIHqtjNXm2MdzQyWGcRxmh9s4JNplbNfcG8p2hcZzaTR0rvXcNoaEQjhb+Rq7+WfPLCg4g5CE1XLHGy0JUuOQB7GSq1I/DMLbj0i+OfkqXZ0Q/Xt4DV2Kcef36hqRYCiitZwwnCcyjCNtECD27CxLNkupc1vB+41wHW49S6o2jXTwjbNl2LwLsM8JOqZRI8Rvnxzo1oPreZ7T0jAk2jOPD+iJjOQjsws9btc8azggcWHQpyUIFi0HhvhhlTaRfEx9NgT7zrEkpSU0+eysS5aVfJ2NZF/Ajlcb8N7R0PfaGkLaFxjL8wfhzQtYpoMGvQrOmn1o28YWMR6DiY5g0NEyLMKxDbI8D+lJJroBtCJc6UbfOWJh0K4SRPTeJPgALwnfuEKHcsEzAhh1Yl3x2xJZroPNCZIieDQIT5OpDn6NT3vsCiY6txjG0LOvTb2gEoIhc/mDw3YBzebRukG2Hu0K0maFjoSuP6GDidgyrCoJi0hcRwBbiVuAnYLL3Sg4oW/lZUkpW7brD6ez9KyD+ZWvGWTrybVgGv9QB3uBJEnRESPoYDsIV24dcxd+o9CE3ilGnzpRIzZLFt81J0OEJAbHlYsBtRx21B1csdGmO+Lv6uBVs9gJDw1RB+86yKm4wveMAFvMkcXPgqF7WZIz4wdhZLi+YLWSdV13bLgnMYi1lsuCI69dlNFepIzrqzlwz8inp4o0LkxLdTi1HUTOJ9V/Mat1xJnRwQvquILM8ASbBQ5IGWOcPaON4vRB/1ZXoJZkJFiGtFOh/MRZHLw3cnBSQ3bCSHt6l58rjH5DhRCQkUtXjlVYR0fgXebZOBtYXjhhToKONRnREpwvD1FrFna8eVA5FsG65vrWDy4fPJnBiodepcOBA3Juz79pXqjDbebJJkaSaj5FkffBC3XAXwp6Y3u/m6v/Pa+rHe+OVIdAqkMg1SGQ6hBIdQikOgRSHTGC4Bd45Khv5YTxJAAAAABJRU5ErkJggg=="; + + /** + * + */ + public static final String promotionsLabel = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAAAbCAIAAABzzg+cAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAASdEVYdFNvZnR3YXJlAEdyZWVuc2hvdF5VCAUAAAPFSURBVFhH7ZbPa9tIFMf3f3pg0G2gIPBhoBARqCCwpoeYQHOKMNjkYgzFhaBLRU5ZKGIPugT1sDgQVAgosNgHo4DBgeCFgg6FgYJgDwKD9r2R/GOwtU7bTZZd9CWB+aU3731m3hv/lFVaU4VDUYVDUYVDUYVD0X8GR5qmResptYFDhBe9bhf/ztzBdRBORDovZv5N3XYBoHtb9J5OGzg+uyYwsyWJtJsGA6h3w6SYfD5h/K/cuOhkWTJ0e+7w6d3YisN0Pxe9bD51XgI/nxbdZ9NNR8HxXNqFI8vCU4DTkFq/27w1mN251ksN9i9mODJPwnN5g2rMOHLCr7SKJFfGDx6tBI2f+LN5Jj71TVypceuSPi30NXSODFYDYEbzPExkYg7POH+hoU2do+whDsXeMT/2FnjSB7/zMyPTLxqdj7NlUcEPrd/i+FpuVGPm2eo+4e4NtIn77FnuuPSa7cQhvNfA3kXUxBPjprlneZM4FmgxCU910C3/QQgx89vY7hRphSuZru93gwcRjxyzBnzPMHrBTIjpLyZAw/silyVhBz9q+TguMMI66KdkIE1E9N6AfSfCcZFQtOte/eGiQfP9MBZkvKGB+aHgiyeH2+Ybxddom/VHcuKL1wDev8U6mIqR6958Gw7DGZMj8SRw2wbUFn5gkMCdiWyj7h0O3L4rekpa0cpOsKjBQRugFSzOMKS5G2pNz8lAtCzVEzLo3FMz/mAqybLCkQYtgDf+MqDkyoKaFfxJbbrI7UAOo2YX+0hK2hj3GRyvvinXVhzA6nRNOTeaPS9apoAMUqYNKUU/1roo8uZkQGGrK1fpRlriSAcn6+MomrKuyEA5jikyK4LMRVPFIakbxe6rxcr5zH+jY542z/zpMpxt2l07VlKDFJfNLTgOfYGtR+EQ/uEWHM1LMlCOI8KD3sDB+mNqluKQSu59+4hroDV+XSteqr4fh7yBiypAUqvMbhxZ9I7Ba4+iz0UZXgRWjoMgsrdUXguN0I2mPIQdOHLJ5OquolD1AzhwvwNgJ34sq4K4snSlyuzGQXvVmHUpDczFoKXDwQLBpw5WhMEy29e8Sm+7Oph2/jokkXMAei/MC1MpjrFrX+duZsnHY2QuD22LfgSH9OaQHk8NnzBm2qOF+4/EgQbunObSwIG9ehjnkV3HccY0efKqV+Kqg5cev8L//BXPVYYjyX8c4MNdZ6AZKz83tIHj24XvYvEcfqfKDNB4Ip+MLZr/7ew2PcbPfwDH/0kVDkUVDkUVDkUVDkUVDkUVDkUVDkUVjjVl2V9vxEluSU1fmAAAAABJRU5ErkJggg=="; +} diff --git a/framework-tests/bellatrix.web.tests/pom.xml b/framework-tests/bellatrix.web.tests/pom.xml index 60718d05..b0e2fdac 100644 --- a/framework-tests/bellatrix.web.tests/pom.xml +++ b/framework-tests/bellatrix.web.tests/pom.xml @@ -34,6 +34,18 @@ javafaker 1.0.2 + + solutions.bellatrix + bellatrix.plugins.opencv + 1.0 + test + + + org.junit.jupiter + junit-jupiter-params + 5.9.2 + test + diff --git a/framework-tests/bellatrix.web.tests/src/test/java/opencv/OpenCvTests.java b/framework-tests/bellatrix.web.tests/src/test/java/opencv/OpenCvTests.java new file mode 100644 index 00000000..04bd7cb0 --- /dev/null +++ b/framework-tests/bellatrix.web.tests/src/test/java/opencv/OpenCvTests.java @@ -0,0 +1,79 @@ +package opencv; + +import opencv.data.EncodedImageDemo; +import opencv.data.EncodedImageNavigationDemo; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; +import org.openqa.selenium.Keys; +import solutions.bellatrix.web.components.*; +import solutions.bellatrix.web.infrastructure.Browser; +import solutions.bellatrix.web.infrastructure.ExecutionBrowser; +import solutions.bellatrix.web.infrastructure.Lifecycle; +import solutions.bellatrix.web.infrastructure.junit.WebTest; + +@ExecutionBrowser(browser = Browser.CHROME, lifecycle = Lifecycle.REUSE_IF_STARTED) +public class OpenCvTests extends WebTest { + @Override + public void beforeEach() throws Exception { + super.beforeEach(); + app().browser().maximize(); + } + + @Test + public void actionPerformed_when_convertBase64ToImage_and_clickImage() { + var falcon9Image = app().create().byImage(Anchor.class, EncodedImageDemo.FALCON_9); + + app().navigate().to("http://demos.bellatrix.solutions/"); + falcon9Image.click(); + + app().browser().assertLandedOnPage("product/falcon-9"); + } + + @Test + public void actionPerformed_when_convertBase64ToImage_and_dragAndDropImage() { + var emailNotes = app().create().byId(Span.class, "email-notes"); + var commentTextArea = app().create().byId(TextArea.class, "comment"); + var falcon9BackButtonImage = app().create().byImage(ActionImage.class, EncodedImageDemo.FALCON_9_BACK_BUTTON); + var commentTextAreaImage = app().create().byImage(ActionImage.class, EncodedImageDemo.COMMENT_TEXT_AREA); + + app().navigate().to("https://demos.bellatrix.solutions/2018/04/06/proton-rocket-family/"); + emailNotes.scrollToVisible(); + falcon9BackButtonImage.dragAndDrop(commentTextAreaImage); + + commentTextArea.validateTextIs("https://demos.bellatrix.solutions/2018/04/06/hello-world/"); + } + + @Test + public void actionPerformed_when_convertBase64ToImage_and_clickButton() { + Button falcon9Image = app().create().byImage(Button.class, EncodedImageDemo.FALCON_9); + + app().navigate().to("http://demos.bellatrix.solutions/"); + falcon9Image.click(); + + app().browser().assertLandedOnPage("product/falcon-9"); + } + + @Test + public void actionPerformed_when_locateComplexComponents() { + SearchField websiteSearch = app().create().byImage(SearchField.class, EncodedImageDemo.SEARCH_INPUT); + + app().navigate().to("http://demos.bellatrix.solutions/"); + websiteSearch.setSearch("Falcon"); + websiteSearch.getWrappedElement().sendKeys(Keys.ENTER); + + app().browser().assertLandedOnPage("?s=Falcon&post_type=product"); + app().create().byImage(ActionImage.class, EncodedImageDemo.FALCON_RESULTS).validateIsVisible(); + } + + @ParameterizedTest + @EnumSource(EncodedImageNavigationDemo.class) + public void actionPerformed_when_locateButtonComponents(EncodedImageNavigationDemo navigationItem) { + Button navgationButton = app().create().byImage(Button.class, navigationItem); + + app().navigate().to("http://demos.bellatrix.solutions/"); + navgationButton.click(); + + app().browser().assertLandedOnPage(navigationItem.getExpectedUrl()); + } +} \ No newline at end of file diff --git a/framework-tests/bellatrix.web.tests/src/test/java/opencv/data/EncodedImageDemo.java b/framework-tests/bellatrix.web.tests/src/test/java/opencv/data/EncodedImageDemo.java new file mode 100644 index 00000000..a891aae8 --- /dev/null +++ b/framework-tests/bellatrix.web.tests/src/test/java/opencv/data/EncodedImageDemo.java @@ -0,0 +1,63 @@ +package opencv.data; + +import solutions.bellatrix.plugins.opencv.Base64Encodable; + +public enum EncodedImageDemo implements Base64Encodable { + /** + * + */ + FALCON_9("falcon9", ImageInBase64.falcon9, 50, 25), + /** + * + */ + SEARCH_INPUT("searchInput", ImageInBase64.searchInput), + /** + * + */ + FALCON_RESULTS("falconResults", ImageInBase64.falconResults), + /** + * + */ + FALCON_9_BACK_BUTTON("falcon9BackButton", ImageInBase64.falcon9BackButton), + /** + * + */ + COMMENT_TEXT_AREA("commentTextArea", ImageInBase64.commentTextArea); + + private final String imageName; + private final String encodedImage; + private int xOffset = 0; + private int yOffset = 0; + + EncodedImageDemo(String imageName, String encodedImage, int xOffset, int yOffset) { + this.imageName = imageName; + this.encodedImage = encodedImage; + this.xOffset = xOffset; + this.yOffset = yOffset; + } + + EncodedImageDemo(String imageName, String encodedImage) { + this.imageName = imageName; + this.encodedImage = encodedImage; + } + + @Override + public String getBase64Image() { + return encodedImage; + } + + @Override + public String getImageName() { + return imageName; + } + + @Override + public int getXOffset() { + return xOffset; + } + + @Override + public int getYOffset() { + return yOffset; + } +} diff --git a/framework-tests/bellatrix.web.tests/src/test/java/opencv/data/EncodedImageNavigationDemo.java b/framework-tests/bellatrix.web.tests/src/test/java/opencv/data/EncodedImageNavigationDemo.java new file mode 100644 index 00000000..895cb378 --- /dev/null +++ b/framework-tests/bellatrix.web.tests/src/test/java/opencv/data/EncodedImageNavigationDemo.java @@ -0,0 +1,61 @@ +package opencv.data; + +import lombok.Getter; +import solutions.bellatrix.plugins.opencv.Base64Encodable; + +public enum EncodedImageNavigationDemo implements Base64Encodable { + /** + * + */ + HOME_LABEL("homeLabel", NavigationImageInBase64.homeLabel, "https://demos.bellatrix.solutions/"), + /** + * + */ + BLOG_LABEL("blogLabel", NavigationImageInBase64.blogLabel, "/blog/"), + /** + * + */ + CHECKOUT_LABEL("checkoutLabel", NavigationImageInBase64.checkoutLabel, "/cart/"), + /** + * + */ + CONTACT_FORM_LABEL("contactFormLabel", NavigationImageInBase64.contactFormLabel, "/contact-form/"), + /** + * + */ + MY_ACCOUNT_LABEL("myAccountLabel", NavigationImageInBase64.myAccountLabel, "/my-account/"), + /** + * + */ + PROMOTIONS_LABEL("promotionsLabel", NavigationImageInBase64.promotionsLabel, "/welcome/"); + + private final String imageName; + private final String encodedImage; + @Getter private final String expectedUrl; + + EncodedImageNavigationDemo(String imageName, String encodedImage, String expectedUrl) { + this.imageName = imageName; + this.encodedImage = encodedImage; + this.expectedUrl = expectedUrl; + } + + @Override + public String getBase64Image() { + return encodedImage; + } + + @Override + public String getImageName() { + return imageName; + } + + @Override + public int getXOffset() { + return 0; + } + + @Override + public int getYOffset() { + return 0; + } +} diff --git a/framework-tests/bellatrix.web.tests/src/test/java/opencv/data/ImageInBase64.java b/framework-tests/bellatrix.web.tests/src/test/java/opencv/data/ImageInBase64.java new file mode 100644 index 00000000..3b809171 --- /dev/null +++ b/framework-tests/bellatrix.web.tests/src/test/java/opencv/data/ImageInBase64.java @@ -0,0 +1,24 @@ +package opencv.data; + +public class ImageInBase64 { + /** + * + */ + public static final String falcon9BackButton = "data:image/png;base64,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"; + /** + * + */ + public static final String commentTextArea = "data:image/png;base64,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"; + /** + * + */ + public static final String falcon9 = "data:image/png;base64,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"; + /** + * + */ + public static final String searchInput = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPcAAABCCAIAAAAE6dfCAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAASdEVYdFNvZnR3YXJlAEdyZWVuc2hvdF5VCAUAAAagSURBVHhe7ZkBa9tGFID3V4VBGJFymNpMmDqZmxENRIgLbmuzTulMF6dQU1TmQB1aw1wyUbsjmOIkmM5JpuAqjTqjP9C9O50V2ZEXd0285Po+QtE7ne7O9XdPT/I3nxBEdNByRHzQckR80HJEfNByRHzQckR80HJEfNByRHzQckR8oi3vdDo7CHJ9AGO5u1FEW35ycvI3glwfwFjubhTRlsNlHoJcH8BY7m4UaDkiAmg5Ij5oOSI+aDkiPmg5Ij5oOSI+aDkiPmg5Ij5oOSI+aDkiPmg5Ij5oOSI+M7f84/HRX0fwd/yRNyDIZTNDy99vV1bSiRsBifRKpXnETyLI5TEry3u1lRS3e4TE7coe74Igl8RMLB/sPv6OOZ3SK68P/FLl414t/y1rvPXL2wFr+lfcfsfarDXe9NwpOn8u3bWktFznwWVSX5aSa10eILNiJpa/ylObibZxwBs472srhJ5ZeXHMWybQWVdlWVGX9MxNRZ7Lmju8/aK40pZ3zeyiiTvjS5iF5U2DVeN3GzwOwU/d/53HkTg1LUaM7WH0xupcdDq/0pbvlZOpMlr+JczC8sZdavL8k3c8DvHuyTw9F7UBTjk0M1KyFJG/ndaaRuKSBGm+YDm0xe3WDQ3yPW3LlrZZGyTDxay5Xc8RWUo/6UGD3TAWIJCkuJqr0wZquW42Ciq9Mp4ZXhjQKJJ81SprcFFMJksm32aviqTQ6Kxn5Jice+V5/VZ5icgxOqz+rO2yLpQ/azmVrogsGPkst7z7NAvX+udptiZFHrhtc1mlg8hEW287MAWsKSYrhPj9O0/pKqBFXTbbY8tEJjALy98+Sk9SufkjzeUJo8njaJzGHUWSk/pavXvqjteFMkYtUZsGdk1XtOfwnTuN9bK1TzvZv2pSwmizjuWUrKT0atcFoEtOkdRHbVrf25bFNg+1PEby9Z4Llq0mpQXTps0BdV2SyEqNzu62S6pEVtnA0Kwo2Z8sG8YddMuwHDimw8JyJG2DORhMB5fu1/OJoeXhuwdka0lnAQwiKcs1WAdMZL1xPNehH+Sm0Tq07b5Lz8f1Wh96uu2tFko+JbOw3Hv9gNUl84/HXqfsVW6zujwPifAcIEmXdciIkMMKDWqS1zbIaRlDhQuXHB9su2mcqpMaOgfWbWjSmQJgxLmdUjKet3jgA6Mny8HiN3U+AjQTfyN53rZBYnp9WErRWVTaZ2y6oGKJtnx0EA7MEowAt7WYamzRXYBMz0ws9w42fqA230jMF17sHp143snR7ovCvP/y/HYlopSZgLtT1RQ/lcKXL8lzcCMfwm7oNtQVCYUs6MV7GglZ7h/RIKzXkAmZNWDUcojkHJ0s7F/4GIAwRvuMTXeO5WOD+Iw20g9IZJlkipu01kKmYTaWe9775oNbzOkoEt9XdscS2GSoH7S8tvLxUC73oalOq/rVRrgMCFluP82cKUg+z/IgT4/4Z+Xl8B1gmO+hrApPd47lY4P4RKnPdrt8pisSzawsBwYHLx9qpz9+JtLaw5dNU+fRZNGd33KqXu18YAEtwWWl0IJD654i6zVWvcDXDpUxs4QUW6zFfq7LUZZ7+7ATSH6LFTADu9OlB1NYTooWKxMGHSidfVNH/BtYeVjOc+ZzuA8UVsGjs90I6nK6DfhSHesekfwZ6SBSpuInabe7ww7ohxrWRfstiz+aONWspG/So17dME7zeq++WqwGT+p9q1SoXvgrqWvHDC0PODmiRQvnuHGf/yg6UXS3W7tDXzvIcwr8qywOX3EMOuaiIsfp6wdFSRpNl+qVltn7iKS2ZmhQ49J+o5aDIFvFJOulxOXkagusmcZydYEoc/SFh6JXe/4CxrLsjpmdk6GIgmHJ8rCP/7JfgukURc2V7iS55QOrOCdJcQVWnt+q6sGMw0FgJmWpSruynvT6JXPXKsFZ+vmgT7rM/h9sc0Hi9xbg0MzGJHWdR/azbOjc18v/Yfk4geipn//gTREMXPvQtv2MHgYeNA+d8NOYa9sjcTSuczhNNx/QmVUsMFf/nGtg9ohFuo5tn71w4hrODEJ7Bj/60rPhZbhOeBC3PxI55y34a+AqWA4cNx9qK9VdHl05hpYj15MrYvkVp1EkWfyR/fqCliPig5Yj4oOWI+KDliPig5Yj4oOWI+KDliPig5Yj4oOWI+KDliPig5Yj4oOWI+KDliPig5Yj4oOWI+LzXyxHEJFAyxHxQcsR8UHLEfFByxHxQcsR8UHLEfFByxHxQcsR8UHLEfFByxHR+fTpHwJ2ejv6o58fAAAAAElFTkSuQmCC"; + /** + * + */ + public static final String falconResults = "data:image/png;base64,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"; +} diff --git a/framework-tests/bellatrix.web.tests/src/test/java/opencv/data/NavigationImageInBase64.java b/framework-tests/bellatrix.web.tests/src/test/java/opencv/data/NavigationImageInBase64.java new file mode 100644 index 00000000..fa7344ff --- /dev/null +++ b/framework-tests/bellatrix.web.tests/src/test/java/opencv/data/NavigationImageInBase64.java @@ -0,0 +1,29 @@ +package opencv.data; + +public class NavigationImageInBase64 { + /** + * + */ + public static final String homeLabel = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEMAAAAkCAIAAABdWRDGAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAASdEVYdFNvZnR3YXJlAEdyZWVuc2hvdF5VCAUAAAIHSURBVFhH7ZUxa9tAFID7nx4ItB0UBB0EhRqDDwz11Cz1VJFBdBGGoiFoqehQXAiiQ5eiTC4YDwVlUYZiQ8EFo0DghsJBQJDhwKDena9Rmgw9B0GP9D4k0Ht3euK7k54eNQ8Fa2Ie1sQ8rIl5WBPzsCbmYU3M478zWeeTKP+hAgkt3kfTU6oiA9A0KUKA8KsKJCQbAD4mKjIAa3LbhFUn4eixC+Ci52G+YSpNPo376fKySIYIANAwKeumXmXBUxcchI94dA0j8xiLWbxCUlyqrD7dmFTHGBycnhFKSflu5Do4O5cDFxkGz+uPMz60yQMP0LNe72VWEkrmIY/iMzmNl/vIJwb5pmaMlm8xDLJ9t3sPk7sok6tF4MD45Hp969krgMOF2Bdh0pvurLjwhx70p9V2F91Yi20ROq1V0yxj1N6lSRd78j31AWcXMi0hfIv8dM2vhEk7JPLtYt+q4B9MokgdAX/N/nzc3+nC5FuM7pqgeMmvNE1EhVHyZbGYt8f6p5ylTRcmND+48cZzyjcIXuTiX6NpIir4yUqm70snXzwrJh4MkqVsOPUqxY4Xncr2pWmyqzDkXU5GW1ad7/3P7cSEP5vOXvuiB4vTDz5XKq9r0lZATzzkuP7h7PeALpomelzVlNZMtaZ7wXgFXkJFe9GpyT/FmpiHNTEPa2Ie1sQ8HopJ0/wC1fAUHISDjIsAAAAASUVORK5CYII="; + /** + * + */ + public static final String blogLabel = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAAkCAIAAABaG87TAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAASdEVYdFNvZnR3YXJlAEdyZWVuc2hvdF5VCAUAAAJnSURBVFhH7Zbfp9tgGMf3Pz2E9y6M3IXDapxwOLGLc4xTRmOc6E2UIxdTo7GrjYqxKpNeTEu9o6RMz8XRMXIxKSUXh5cSevFSsje/lhy72JKusVo+Et7nfS/6eZvv+ySPgiOklq6KWroqaumqqKWr4n+Wvnfw1CFJcXAKSDsfNa0TXsYQ4+nC9WmywJipAKqdFAengLTdBji5jL3V5yICJH/wkrV/WrqdiZGhDLy+jItjkQ4+q8BpSf1Qmn631HMeAaDHsjpysxjt3HFbjhZ4MeZqkD6sApSTpr63MM5A7DlR+VB6ZUocSL2FR4h3a8gIpL4bLVC7zfMty2Ob2Cy7p6g5dMkmdzD+mILSeZ5oeJ3+ZCZN8UuAK8uPphn+RAFOwVs2tDUO1Fk8HXh9CS6scg2nbDyo744UgZPMVVRm0o4hsr8298zXpgSi8Y2NHOMElEmyT6cnwjWOx0XZI9MBHbfShGTSS53/VZrX78KhP1MFJHc/YTzUGijdcHH2kSaDZ9B4F+U1kybWBfA3i3AYc8t2cRnnwHsvSa8x7neNoe1sotVSlJSmG9d+JQGLxzqqcweRzjUBpO5dlGp/yc6r0LGjTHjmKTRHP9NenrIHkeOFcz07iPfWJQeok2yJTFT27gEU3mLLcnfxdOBPFTaVgvinivm1zB4KSP+GrU/yL/Yd9Qnxw6aRslvqgvR2RemGRHjjax7OzMP26X35oiPRSBt7iPNGLNf1KpTe2izswgtjPGXfW3hw00BC0yrVQCqUZlDizAdG+MllDOYOyaWpENVK/yVq6aqopauilq6KWroqjlA6CH4A7B4rEaIvT3wAAAAASUVORK5CYII="; + /** + * + */ + public static final String checkoutLabel = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEQAAAAqCAIAAACFj2rPAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAASdEVYdFNvZnR3YXJlAEdyZWVuc2hvdF5VCAUAAAH/SURBVGhD7ZWxS+RAFIf9nx4E0g0cBK5IdWHBAQur3UYrg3DhmrAgUZY0ilgoLKm2OXLVHsgKQmzWagthbbKwkGJhQBixCCzMTcYRT2VhbyPcU+ar8nuZFB/vzcua+EQYGawYGawYGawYGawYGawYGawYGawYmVc85Fk3Dtth2D5Kb7ku/g/qyvDryLPAbvhxt5d0fM8G7yzX75bkKoT1pNChFvVkeN+3gJ7lpc5C3OXFv/bmMkAhU3QpkGg41/EF8zI/j1vfCEgIjS6Yrhe97cbRaDaINghYwcmB636xwSKOK4mH+tCK1JEp+zsA7UynV/B+2IzTm4Ixlv/0idVKZ6o+TShQukHjq5zN+D1no0MPpJ48x/hzh1eijkyRrAPtLjMgWWhBcKkeKxnwfz/PYtVeBGNWybiHY53eUrLxeRLvbLouseFJW3UmmaoDCiQyImsDNNOn2/CSabrt2N5eOi7k8PzVQ7Qy4joiQE8nOmnUPhjtE/g+UFnyIWQEz3444PjpRF3dkg2PN0mzJ3tVyWylvBIri1+BIzf4AhlxEYDl99/jZ1tTRvaBDfYosaoNLLEb0eBxa03kmMml7BBCaCfr7S6WmY/ir/JLQuzWgpFdltoyj8xL/na1quJy61adfNBhZd5JBgdGBitGBitGBitGBitGBitGBiufSEaIP52unQiECIP2AAAAAElFTkSuQmCC"; + /** + * + */ + public static final String contactFormLabel = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAG4AAAAiCAIAAAAxo3u7AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAASdEVYdFNvZnR3YXJlAEdyZWVuc2hvdF5VCAUAAAPVSURBVGhD7ZbPh+NQHMD3f3qE3B5L6CEME2XDHGoPU8uWZWIO0UuV1aFy2ehphoo91DJy6zCyLBlGeqgMQ5eRYchhCSXMIZTs972kP2amTduZp7uH99FDv+/nN5+8H3mXchjBVTKDq2QGV8kMrpIZXCUzuEpmcJXM4CqZwVUyg6tkBlfJjM1UPgZu12g0G42maf+O88L/idE55PbkZ//Oq3bGepXxoKUISCxrRrdntTVFRMpZkNe9gqsG+mCFebAtbkNQrYc8WMStI7RX/b9Vxn1NQOpZkORxmo6D8C3r8pf+FpU6Wq2y7ubBP2KNyrCrItzyJnn4nLFrflKwgBBWqh03njW7NuTjfvjgtA4wgsoDw6P2vbYsvxeRgCUZMLw0TSKvV69gEVqJ8pHlz19SEl62KtAYuu9r1k1MxpRJQ1yina/zdhkrVRZmGNxY2p6IyqdBGvY+K+YwdtsqbawagziNfetIJjNO8y+mWGXSP0KoueJtx64uIenYDqIourP1EpLqbj4jLD0sSeWGcxdFoQPN8FfwliZx5H9TUNn0oUsUw0ofdWp61yUjhJ7xAUknfjZA+F1FgtK4JDXBpWH+jEnnoakgeOBp5wWWqyzOUFbVfa13G4YRlIUWzC4pta4XRoF9DBkrSrlmDcLF/IspVkkmULvLt+OoIyPZ8Gfv+daE2MxOKEgU6c60KjhTZpuaLPMVG5zoy6omri6gyo8oK5/zYKkFG1zEZLlmtMmTr8tQNm/pfwJ50vkdcH8K7+z0Lo8Kcl5kvUr52yiPnkAX7JOFAAcZ0i7oaqEqZ3WLqbxMK7n3eh29WpYlchjQXuSZlykrVnncJ8s1gyzaLTLMnnS+aJ5OxERl6jYROrRfLA8gsg+XJFo9p203VZn4bUUs1cyrIH5c6DVs4VeofL7Bt8hwFyrTAXmq0/s8yqFbxj/B6GNvbvlPrwI31JD+31BlZFdhH80Gn/Ui5Uj/lZUusJ3KLTLciUo4uutwdGv2Pd0XcON2KviQ5gfzCVg7D0nFJOrDUX0wnW+1yvSnjgStnx3+RJlsDOnIY9/8CLdl1itxmzCp7oxJAFXOgAqZODCudrHkNl1+7Wyc4W5UkiScr/QTgSKWW86fvCa+MatwwIni8y+GApUT3yiRKwKLVTuKvROFBCWM97TeBVzQ016TwP4ikelgbEGqfR9R36nfhkIRvxfzfTplucqNM9yVyowJfIy8+AYhrCovgHQhh+MsGK/o/kgaJrMrmFLUfjmvyPA1bKySsw6ukhlcJTO4SmZwlczgKpnBVTKDq2QGV8kMrpIRafoXhEVgioTlfegAAAAASUVORK5CYII="; + /** + * + */ + public static final String myAccountLabel = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAAAgCAIAAAAdc/jyAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAASdEVYdFNvZnR3YXJlAEdyZWVuc2hvdF5VCAUAAAOSSURBVGhD7ZbRZyNBGMDvfxrCvg1l6cNQukpDudWHRmmessJFX+qIlNqXrjylxD5FiO3DSakcx5STPlRK2XK2hH0oy7HkIYS9b2Y3yU6STXLtubvW/h5i55vd2ZnffvNNPgQpMVIdAqkOgVSHQKpDINUhkOoQSHUIpDoEEnR4tPb5xLwbRs0QHqzdeFHzPZKgo29mEUKFdtyH11Qhlq27UfuN4Zp7qPQtaiSRrGMnm83krGkqeI19rH5U3rCO3dfoIHqtjNXm2MdzQyWGcRxmh9s4JNplbNfcG8p2hcZzaTR0rvXcNoaEQjhb+Rq7+WfPLCg4g5CE1XLHGy0JUuOQB7GSq1I/DMLbj0i+OfkqXZ0Q/Xt4DV2Kcef36hqRYCiitZwwnCcyjCNtECD27CxLNkupc1vB+41wHW49S6o2jXTwjbNl2LwLsM8JOqZRI8Rvnxzo1oPreZ7T0jAk2jOPD+iJjOQjsws9btc8azggcWHQpyUIFi0HhvhhlTaRfEx9NgT7zrEkpSU0+eysS5aVfJ2NZF/Ajlcb8N7R0PfaGkLaFxjL8wfhzQtYpoMGvQrOmn1o28YWMR6DiY5g0NEyLMKxDbI8D+lJJroBtCJc6UbfOWJh0K4SRPTeJPgALwnfuEKHcsEzAhh1Yl3x2xJZroPNCZIieDQIT5OpDn6NT3vsCiY6txjG0LOvTb2gEoIhc/mDw3YBzebRukG2Hu0K0maFjoSuP6GDidgyrCoJi0hcRwBbiVuAnYLL3Sg4oW/lZUkpW7brD6ez9KyD+ZWvGWTrybVgGv9QB3uBJEnRESPoYDsIV24dcxd+o9CE3ilGnzpRIzZLFt81J0OEJAbHlYsBtRx21B1csdGmO+Lv6uBVs9gJDw1RB+86yKm4wveMAFvMkcXPgqF7WZIz4wdhZLi+YLWSdV13bLgnMYi1lsuCI69dlNFepIzrqzlwz8inp4o0LkxLdTi1HUTOJ9V/Mat1xJnRwQvquILM8ASbBQ5IGWOcPaON4vRB/1ZXoJZkJFiGtFOh/MRZHLw3cnBSQ3bCSHt6l58rjH5DhRCQkUtXjlVYR0fgXebZOBtYXjhhToKONRnREpwvD1FrFna8eVA5FsG65vrWDy4fPJnBiodepcOBA3Juz79pXqjDbebJJkaSaj5FkffBC3XAXwp6Y3u/m6v/Pa+rHe+OVIdAqkMg1SGQ6hBIdQikOgRSHTGC4Bd45Khv5YTxJAAAAABJRU5ErkJggg=="; + + /** + * + */ + public static final String promotionsLabel = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAAAbCAIAAABzzg+cAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAASdEVYdFNvZnR3YXJlAEdyZWVuc2hvdF5VCAUAAAPFSURBVFhH7ZbPa9tIFMf3f3pg0G2gIPBhoBARqCCwpoeYQHOKMNjkYgzFhaBLRU5ZKGIPugT1sDgQVAgosNgHo4DBgeCFgg6FgYJgDwKD9r2R/GOwtU7bTZZd9CWB+aU3731m3hv/lFVaU4VDUYVDUYVDUYVD0X8GR5qmResptYFDhBe9bhf/ztzBdRBORDovZv5N3XYBoHtb9J5OGzg+uyYwsyWJtJsGA6h3w6SYfD5h/K/cuOhkWTJ0e+7w6d3YisN0Pxe9bD51XgI/nxbdZ9NNR8HxXNqFI8vCU4DTkFq/27w1mN251ksN9i9mODJPwnN5g2rMOHLCr7SKJFfGDx6tBI2f+LN5Jj71TVypceuSPi30NXSODFYDYEbzPExkYg7POH+hoU2do+whDsXeMT/2FnjSB7/zMyPTLxqdj7NlUcEPrd/i+FpuVGPm2eo+4e4NtIn77FnuuPSa7cQhvNfA3kXUxBPjprlneZM4FmgxCU910C3/QQgx89vY7hRphSuZru93gwcRjxyzBnzPMHrBTIjpLyZAw/silyVhBz9q+TguMMI66KdkIE1E9N6AfSfCcZFQtOte/eGiQfP9MBZkvKGB+aHgiyeH2+Ybxddom/VHcuKL1wDev8U6mIqR6958Gw7DGZMj8SRw2wbUFn5gkMCdiWyj7h0O3L4rekpa0cpOsKjBQRugFSzOMKS5G2pNz8lAtCzVEzLo3FMz/mAqybLCkQYtgDf+MqDkyoKaFfxJbbrI7UAOo2YX+0hK2hj3GRyvvinXVhzA6nRNOTeaPS9apoAMUqYNKUU/1roo8uZkQGGrK1fpRlriSAcn6+MomrKuyEA5jikyK4LMRVPFIakbxe6rxcr5zH+jY542z/zpMpxt2l07VlKDFJfNLTgOfYGtR+EQ/uEWHM1LMlCOI8KD3sDB+mNqluKQSu59+4hroDV+XSteqr4fh7yBiypAUqvMbhxZ9I7Ba4+iz0UZXgRWjoMgsrdUXguN0I2mPIQdOHLJ5OquolD1AzhwvwNgJ34sq4K4snSlyuzGQXvVmHUpDczFoKXDwQLBpw5WhMEy29e8Sm+7Oph2/jokkXMAei/MC1MpjrFrX+duZsnHY2QuD22LfgSH9OaQHk8NnzBm2qOF+4/EgQbunObSwIG9ehjnkV3HccY0efKqV+Kqg5cev8L//BXPVYYjyX8c4MNdZ6AZKz83tIHj24XvYvEcfqfKDNB4Ip+MLZr/7ew2PcbPfwDH/0kVDkUVDkUVDkUVDkUVDkUVDkUVDkUVjjVl2V9vxEluSU1fmAAAAABJRU5ErkJggg=="; +} diff --git a/getting-started/bellatrix.playwright.getting.started/pom.xml b/getting-started/bellatrix.playwright.getting.started/pom.xml index 77ea044f..f11c2982 100644 --- a/getting-started/bellatrix.playwright.getting.started/pom.xml +++ b/getting-started/bellatrix.playwright.getting.started/pom.xml @@ -45,6 +45,11 @@ 1.0 compile + + solutions.bellatrix + bellatrix.plugins.opencv + 1.0 + solutions.bellatrix bellatrix.plugins.visual-regression-tracker diff --git a/getting-started/bellatrix.playwright.getting.started/src/test/java/O26_openCv_image_actions/OpenCvDemoTests.java b/getting-started/bellatrix.playwright.getting.started/src/test/java/O26_openCv_image_actions/OpenCvDemoTests.java new file mode 100644 index 00000000..216c332a --- /dev/null +++ b/getting-started/bellatrix.playwright.getting.started/src/test/java/O26_openCv_image_actions/OpenCvDemoTests.java @@ -0,0 +1,40 @@ +package O26_openCv_image_actions; + +import O26_openCv_image_actions.data.enums.EncodedImageDemo; +import org.junit.jupiter.api.Test; +import solutions.bellatrix.playwright.components.ActionImage; +import solutions.bellatrix.playwright.components.Span; +import solutions.bellatrix.playwright.components.TextArea; +import solutions.bellatrix.playwright.infrastructure.junit.WebTest; + +public class OpenCvDemoTests extends WebTest { + @Override + public void beforeEach() throws Exception { + super.beforeEach(); + app().browser().setSize(1920, 1080); + } + + @Test + public void actionPerformed_when_convertBase64ToImage_and_clickImage() { + var falcon9Image = app().create().byImage(ActionImage.class, EncodedImageDemo.FALCON_9); + + app().navigate().to("http://demos.bellatrix.solutions/"); + falcon9Image.click(); + + app().browser().validateLandedOnPage("product/falcon-9"); + } + + @Test + public void actionPerformed_when_convertBase64ToImage_and_dragAndDropImage() { + var emailNotes = app().create().byId(Span.class, "email-notes"); + var commentTextArea = app().create().byId(TextArea.class, "comment"); + var falcon9BackButtonImage = app().create().byImage(ActionImage.class, EncodedImageDemo.FALCON_9_BACK_BUTTON); + var commentTextAreaImage = app().create().byImage(ActionImage.class, EncodedImageDemo.COMMENT_TEXT_AREA); + + app().navigate().to("https://demos.bellatrix.solutions/2018/04/06/proton-rocket-family/"); + emailNotes.scrollToVisible(); + falcon9BackButtonImage.dragAndDrop(commentTextAreaImage); + + commentTextArea.validateTextIs("https://demos.bellatrix.solutions/2018/04/06/hello-world/"); + } +} \ No newline at end of file diff --git a/getting-started/bellatrix.playwright.getting.started/src/test/java/O26_openCv_image_actions/data/ImageInBase64.java b/getting-started/bellatrix.playwright.getting.started/src/test/java/O26_openCv_image_actions/data/ImageInBase64.java new file mode 100644 index 00000000..69137665 --- /dev/null +++ b/getting-started/bellatrix.playwright.getting.started/src/test/java/O26_openCv_image_actions/data/ImageInBase64.java @@ -0,0 +1,16 @@ +package O26_openCv_image_actions.data; + +public class ImageInBase64 { + /** + * + */ + public static final String falcon9BackButton = "data:image/png;base64,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"; + /** + * + */ + public static final String commentTextArea = "data:image/png;base64,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"; + /** + * + */ + public static final String falcon9 = "data:image/png;base64,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"; +} diff --git a/getting-started/bellatrix.playwright.getting.started/src/test/java/O26_openCv_image_actions/data/enums/EncodedImageDemo.java b/getting-started/bellatrix.playwright.getting.started/src/test/java/O26_openCv_image_actions/data/enums/EncodedImageDemo.java new file mode 100644 index 00000000..2801310f --- /dev/null +++ b/getting-started/bellatrix.playwright.getting.started/src/test/java/O26_openCv_image_actions/data/enums/EncodedImageDemo.java @@ -0,0 +1,56 @@ +package O26_openCv_image_actions.data.enums; + +import O26_openCv_image_actions.data.ImageInBase64; +import solutions.bellatrix.plugins.opencv.Base64Encodable; + +public enum EncodedImageDemo implements Base64Encodable { + /** + * + */ + FALCON_9("falcon9", ImageInBase64.falcon9, 50, 25), + /** + * + */ + FALCON_9_BACK_BUTTON("falcon9BackButton", ImageInBase64.falcon9BackButton), + /** + * + */ + COMMENT_TEXT_AREA("commentTextArea", ImageInBase64.commentTextArea); + + private final String imageName; + private final String encodedImage; + private int xOffset = 0; + private int yOffset = 0; + + EncodedImageDemo(String imageName, String encodedImage, int xOffset, int yOffset) { + this.imageName = imageName; + this.encodedImage = encodedImage; + this.xOffset = xOffset; + this.yOffset = yOffset; + } + + EncodedImageDemo(String imageName, String encodedImage) { + this.imageName = imageName; + this.encodedImage = encodedImage; + } + + @Override + public String getBase64Image() { + return encodedImage; + } + + @Override + public String getImageName() { + return imageName; + } + + @Override + public int getXOffset() { + return xOffset; + } + + @Override + public int getYOffset() { + return yOffset; + } +} diff --git a/getting-started/bellatrix.playwright.getting.started/src/test/java/O26_openCv_image_actions/todo.txt b/getting-started/bellatrix.playwright.getting.started/src/test/java/O26_openCv_image_actions/todo.txt new file mode 100644 index 00000000..688c96b8 --- /dev/null +++ b/getting-started/bellatrix.playwright.getting.started/src/test/java/O26_openCv_image_actions/todo.txt @@ -0,0 +1,6 @@ + 1. Take a screenshot of the place on the screen that you want to perform actions on + 2. Convert the image to a base 64 format with an online tool + 3. Create an enum implementing the Base64Encodable interface + 4. Add the base 64 string, the name of the image and the offsets to the enum - check example enum: EncodedImageDemo + (Note) If the x and y offsets are set to 0 -> it will take the coordinates of the center of the picture + 5. Create ActionImage component using the ImageBase64FindStrategy and passing the enum as an argument \ No newline at end of file diff --git a/getting-started/bellatrix.web.getting.started/pom.xml b/getting-started/bellatrix.web.getting.started/pom.xml index b5dc88f2..140e874f 100644 --- a/getting-started/bellatrix.web.getting.started/pom.xml +++ b/getting-started/bellatrix.web.getting.started/pom.xml @@ -50,6 +50,18 @@ 5.9.2 test + + jakarta.xml.bind + jakarta.xml.bind-api + 2.3.2 + test + + + jakarta.xml.bind + jakarta.xml.bind-api + 2.3.2 + compile + solutions.bellatrix bellatrix.plugins.visual-regression-tracker diff --git a/getting-started/bellatrix.web.getting.started/src/test/java/O26_openCv_image_actions/OpenCvDemoTests.java b/getting-started/bellatrix.web.getting.started/src/test/java/O26_openCv_image_actions/OpenCvDemoTests.java new file mode 100644 index 00000000..3fe3b9d3 --- /dev/null +++ b/getting-started/bellatrix.web.getting.started/src/test/java/O26_openCv_image_actions/OpenCvDemoTests.java @@ -0,0 +1,70 @@ +package O26_openCv_image_actions; + +import O26_openCv_image_actions.data.enums.EncodedImageDemo; +import org.junit.jupiter.api.Test; +import plugins.screenshots.ScreenshotPlugin; +import solutions.bellatrix.web.components.ActionImage; +import solutions.bellatrix.web.components.Button; +import solutions.bellatrix.web.components.Span; +import solutions.bellatrix.web.components.TextArea; +import solutions.bellatrix.web.infrastructure.*; +import solutions.bellatrix.web.infrastructure.junit.WebTest; + +/** + * Image locators are generated from real images using the tool: OpenCV Image Match Finder + * Where you can supply either: + * - Image from disc + * - Paste image from clipboard + * - Drag and drop image + * In addition it helps in troubleshooting where you want to check the confidence level of a match in a context image. + */ +@ExecutionBrowser(browser = Browser.CHROME, lifecycle = Lifecycle.RESTART_EVERY_TIME) +public class OpenCvDemoTests extends WebTest { + + @Override + protected void configure() { + addPlugin(BrowserLifecyclePlugin.class); + // Adding the screenshot plugin as a WebScreenshot plugin is required for the feature to work correctly + addPluginAs(ScreenshotPlugin.class, WebScreenshotPlugin.class); + } + + @Override + public void beforeEach() throws Exception { + super.beforeEach(); + app().browser().setSize(1920, 1080); + } + + @Test + public void actionPerformed_when_convertBase64ToImage_and_clickImage() { + var falcon9Image = app().create().byImage(ActionImage.class, EncodedImageDemo.FALCON_9); + + app().navigate().to("http://demos.bellatrix.solutions/"); + falcon9Image.click(); + + app().browser().assertLandedOnPage("product/falcon-9"); + } + + @Test + public void actionPerformed_when_convertBase64ToImage_and_clickButton() { + var falcon9Image = app().create().byImage(Button.class, EncodedImageDemo.FALCON_9); + + app().navigate().to("http://demos.bellatrix.solutions/"); + falcon9Image.click(); + + app().browser().assertLandedOnPage("product/falcon-9"); + } + + @Test + public void actionPerformed_when_convertBase64ToImage_and_dragAndDropImage() { + var emailNotes = app().create().byId(Span.class, "email-notes"); + var commentTextArea = app().create().byId(TextArea.class, "comment"); + var falcon9BackButtonImage = app().create().byImage(ActionImage.class, EncodedImageDemo.FALCON_9_BACK_BUTTON); + var commentTextAreaImage = app().create().byImage(ActionImage.class, EncodedImageDemo.COMMENT_TEXT_AREA); + + app().navigate().to("https://demos.bellatrix.solutions/2018/04/06/proton-rocket-family/"); + emailNotes.scrollToVisible(); + falcon9BackButtonImage.dragAndDrop(commentTextAreaImage); + + commentTextArea.validateTextIs("https://demos.bellatrix.solutions/2018/04/06/hello-world/"); + } +} \ No newline at end of file diff --git a/getting-started/bellatrix.web.getting.started/src/test/java/O26_openCv_image_actions/data/ImageInBase64.java b/getting-started/bellatrix.web.getting.started/src/test/java/O26_openCv_image_actions/data/ImageInBase64.java new file mode 100644 index 00000000..9af74c49 --- /dev/null +++ b/getting-started/bellatrix.web.getting.started/src/test/java/O26_openCv_image_actions/data/ImageInBase64.java @@ -0,0 +1,24 @@ +package O26_openCv_image_actions.data; + +/** + * Base64 data is generated from real images using the tool: OpenCV Image Match Finder + * Where you can supply either: + * - Image from disc + * - Paste image from clipboard + * - Drag and drop image + * In addition it helps in troubleshooting where you want to check the confidence level of a match in a context image. + */ +public class ImageInBase64 { + /** + * + */ + public static final String falcon9BackButton = "data:image/png;base64,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"; + /** + * + */ + public static final String commentTextArea = "data:image/png;base64,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"; + /** + * + */ + public static final String falcon9 = "data:image/png;base64,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"; +} diff --git a/getting-started/bellatrix.web.getting.started/src/test/java/O26_openCv_image_actions/data/enums/EncodedImageDemo.java b/getting-started/bellatrix.web.getting.started/src/test/java/O26_openCv_image_actions/data/enums/EncodedImageDemo.java new file mode 100644 index 00000000..2801310f --- /dev/null +++ b/getting-started/bellatrix.web.getting.started/src/test/java/O26_openCv_image_actions/data/enums/EncodedImageDemo.java @@ -0,0 +1,56 @@ +package O26_openCv_image_actions.data.enums; + +import O26_openCv_image_actions.data.ImageInBase64; +import solutions.bellatrix.plugins.opencv.Base64Encodable; + +public enum EncodedImageDemo implements Base64Encodable { + /** + * + */ + FALCON_9("falcon9", ImageInBase64.falcon9, 50, 25), + /** + * + */ + FALCON_9_BACK_BUTTON("falcon9BackButton", ImageInBase64.falcon9BackButton), + /** + * + */ + COMMENT_TEXT_AREA("commentTextArea", ImageInBase64.commentTextArea); + + private final String imageName; + private final String encodedImage; + private int xOffset = 0; + private int yOffset = 0; + + EncodedImageDemo(String imageName, String encodedImage, int xOffset, int yOffset) { + this.imageName = imageName; + this.encodedImage = encodedImage; + this.xOffset = xOffset; + this.yOffset = yOffset; + } + + EncodedImageDemo(String imageName, String encodedImage) { + this.imageName = imageName; + this.encodedImage = encodedImage; + } + + @Override + public String getBase64Image() { + return encodedImage; + } + + @Override + public String getImageName() { + return imageName; + } + + @Override + public int getXOffset() { + return xOffset; + } + + @Override + public int getYOffset() { + return yOffset; + } +} diff --git a/getting-started/bellatrix.web.getting.started/src/test/java/O26_openCv_image_actions/todo.txt b/getting-started/bellatrix.web.getting.started/src/test/java/O26_openCv_image_actions/todo.txt new file mode 100644 index 00000000..11644461 --- /dev/null +++ b/getting-started/bellatrix.web.getting.started/src/test/java/O26_openCv_image_actions/todo.txt @@ -0,0 +1,7 @@ + 1. Take a screenshot of the place on the screen that you want to perform actions on + 2. Convert the image to a base 64 format with the tool created for this purpose: https://automatetheplanet.github.io/OpenCV-Image-Match-Finder/ + 3. Create an enum implementing the Base64Encodable interface + 4. Add the base 64 string, the name of the image and the offsets to the enum - check example enum: EncodedImageDemo + (Note) If the x and y offsets are set to 0 -> it will take the coordinates of the center of the picture + 5. Create ActionImage component using the ImageBase64FindStrategy and passing the enum as an argument + 6. If an image match is not found - use the Image Match Finder tool to troubleshoot: https://automatetheplanet.github.io/OpenCV-Image-Match-Finder/ \ No newline at end of file diff --git a/pom.xml b/pom.xml index bc875e58..b40c83bd 100644 --- a/pom.xml +++ b/pom.xml @@ -15,6 +15,8 @@ bellatrix.plugins.video bellatrix.plugins.jira.zephyr bellatrix.plugins.visual-regression-tracker + bellatrix.plugins.opencv + bellatrix.sms bellatrix.web bellatrix.playwright bellatrix.desktop @@ -31,7 +33,8 @@ getting-started/bellatrix.web.getting.started getting-started/bellatrix.playwright.getting.started - bellatrix.sms + +