Skip to content

[Feature] Visualization #77

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Mar 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
# Log file
*.log

# Visualization
visualDumps/

# BlueJ files
*.ctxt

Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>com.github.aquality-automation</groupId>
<artifactId>aquality-selenium-core</artifactId>
<version>2.0.6</version>
<version>3.0.0</version>

<packaging>jar</packaging>
<name>Aquality Selenium Core</name>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import aquality.selenium.core.utilities.IElementActionRetrier;
import aquality.selenium.core.utilities.ISettingsFile;
import aquality.selenium.core.utilities.IUtilitiesModule;
import aquality.selenium.core.visualization.IImageComparator;
import aquality.selenium.core.visualization.IVisualizationModule;
import aquality.selenium.core.waitings.IConditionalWait;
import aquality.selenium.core.waitings.IWaitingsModule;
import com.google.inject.AbstractModule;
Expand All @@ -22,7 +24,8 @@
* Describes all dependencies which is registered for the project.
*/
public class AqualityModule<T extends IApplication> extends AbstractModule
implements IConfigurationsModule, IElementsModule, ILocalizationModule, IUtilitiesModule, IWaitingsModule {
implements IConfigurationsModule, IElementsModule, ILocalizationModule, IUtilitiesModule, IWaitingsModule,
IVisualizationModule {

private final Provider<T> applicationProvider;

Expand All @@ -42,12 +45,14 @@ protected void configure() {
bind(ITimeoutConfiguration.class).to(getTimeoutConfigurationImplementation()).in(Singleton.class);
bind(IRetryConfiguration.class).to(getRetryConfigurationImplementation()).in(Singleton.class);
bind(IElementCacheConfiguration.class).to(getElementCacheConfigurationImplementation()).in(Singleton.class);
bind(IVisualizationConfiguration.class).to(getVisualConfigurationImplementation()).in(Singleton.class);
bind(IElementActionRetrier.class).to(getElementActionRetrierImplementation()).in(Singleton.class);
bind(IActionRetrier.class).to(getActionRetrierImplementation()).in(Singleton.class);
bind(ILocalizationManager.class).to(getLocalizationManagerImplementation()).in(Singleton.class);
bind(ILocalizedLogger.class).to(getLocalizedLoggerImplementation()).in(Singleton.class);
bind(IConditionalWait.class).to(getConditionalWaitImplementation());
bind(IElementFinder.class).to(getElementFinderImplementation());
bind(IElementFactory.class).to(getElementFactoryImplementation());
bind(IImageComparator.class).to(getImageComparatorImplementation());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@
* Describes implementations of configurations to be registered in DI container.
*/
public interface IConfigurationsModule {
/**
* @return class which implements {@link IVisualizationConfiguration}
*/
default Class<? extends IVisualizationConfiguration> getVisualConfigurationImplementation() {
return VisualizationConfiguration.class;
}

/**
* @return class which implements {@link IElementCacheConfiguration}
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package aquality.selenium.core.configurations;

/**
* Represents visualization configuration, used for image comparison.
*/
public interface IVisualizationConfiguration {
/**
* Image format for comparison.
* @return image format.
*/
String getImageFormat();

/**
* Gets maximum length of full file name with path for image comparison.
* @return maximum symbols count in file path.
*/
int getMaxFullFileNameLength();

/**
* Gets default threshold used for image comparison.
* @return The default threshold value.
*/
float getDefaultThreshold();

/**
* Gets width of the image resized for comparison.
* @return comparison width.
*/
int getComparisonWidth();

/**
* Gets height of the image resized for comparison.
* @return comparison height.
*/
int getComparisonHeight();

/**
* Gets path used to save and load page dumps.
* @return path to dumps.
*/
String getPathToDumps();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package aquality.selenium.core.configurations;

import aquality.selenium.core.logging.Logger;
import aquality.selenium.core.utilities.ISettingsFile;
import com.google.inject.Inject;

import java.io.File;
import java.io.IOException;

/**
* Represents visualization configuration, used for image comparison.
* Uses {@link ISettingsFile} as source for configuration values.
*/
public class VisualizationConfiguration implements IVisualizationConfiguration {
private String imageFormat;
private Integer maxFullFileNameLength;
private Float defaultThreshold;
private Integer comparisonWidth;
private Integer comparisonHeight;
private String pathToDumps;

private final ISettingsFile settingsFile;

/**
* Instantiates class using {@link ISettingsFile} with visualization settings.
* @param settingsFile settings file.
*/
@Inject
public VisualizationConfiguration(ISettingsFile settingsFile) {
this.settingsFile = settingsFile;
}

@Override
public String getImageFormat() {
if (imageFormat == null) {
String valueFromConfig = settingsFile.getValueOrDefault("/visualization/imageExtension", "png").toString();
imageFormat = valueFromConfig.startsWith(".") ? valueFromConfig.substring(1) : valueFromConfig;
}
return imageFormat;
}

@Override
public int getMaxFullFileNameLength() {
if (maxFullFileNameLength == null) {
maxFullFileNameLength = Integer.valueOf(
settingsFile.getValueOrDefault("/visualization/maxFullFileNameLength", 255).toString());
}
return maxFullFileNameLength;
}

@Override
public float getDefaultThreshold() {
if (defaultThreshold == null) {
defaultThreshold = Float.valueOf(
settingsFile.getValueOrDefault("/visualization/defaultThreshold", 0.012f).toString());
}
return defaultThreshold;
}

@Override
public int getComparisonWidth() {
if (comparisonWidth == null) {
comparisonWidth = Integer.valueOf(
settingsFile.getValueOrDefault("/visualization/comparisonWidth", 16).toString());
}
return comparisonWidth;
}

@Override
public int getComparisonHeight() {
if (comparisonHeight == null) {
comparisonHeight = Integer.valueOf(
settingsFile.getValueOrDefault("/visualization/comparisonHeight", 16).toString());
}
return comparisonHeight;
}

@Override
public String getPathToDumps() {
if (pathToDumps == null) {
pathToDumps = settingsFile.getValueOrDefault("/visualization/pathToDumps", "./src/test/resources/visualDumps/").toString();
if (pathToDumps.startsWith(".")) {
try {
pathToDumps = new File(pathToDumps).getCanonicalPath();
} catch (IOException e) {
String errorMessage = "Failed to resolve path to dumps: " + e.getMessage();
Logger.getInstance().fatal(errorMessage, e);
throw new IllegalArgumentException(errorMessage, e);
}
}
}
return pathToDumps;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package aquality.selenium.core.elements;

import aquality.selenium.core.elements.interfaces.IElementCacheHandler;
import aquality.selenium.core.elements.interfaces.ILogElementState;
import aquality.selenium.core.logging.ILogElementState;
import aquality.selenium.core.waitings.IConditionalWait;
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package aquality.selenium.core.elements;

import aquality.selenium.core.elements.interfaces.IElementFinder;
import aquality.selenium.core.elements.interfaces.ILogElementState;
import aquality.selenium.core.logging.ILogElementState;
import aquality.selenium.core.waitings.IConditionalWait;
import org.openqa.selenium.By;

Expand Down
16 changes: 16 additions & 0 deletions src/main/java/aquality/selenium/core/elements/Element.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@
import aquality.selenium.core.elements.interfaces.*;
import aquality.selenium.core.localization.ILocalizationManager;
import aquality.selenium.core.localization.ILocalizedLogger;
import aquality.selenium.core.logging.ILogElementState;
import aquality.selenium.core.logging.ILogVisualState;
import aquality.selenium.core.logging.Logger;
import aquality.selenium.core.utilities.IElementActionRetrier;
import aquality.selenium.core.visualization.IImageComparator;
import aquality.selenium.core.visualization.IVisualStateProvider;
import aquality.selenium.core.visualization.VisualStateProvider;
import aquality.selenium.core.waitings.IConditionalWait;
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
Expand Down Expand Up @@ -37,6 +42,8 @@ protected Element(final By loc, final String name, final ElementState state) {

protected abstract IElementFinder getElementFinder();

protected abstract IImageComparator getImageComparator();

protected abstract IElementCacheConfiguration getElementCacheConfiguration();

protected abstract IElementActionRetrier getElementActionRetrier();
Expand Down Expand Up @@ -70,6 +77,10 @@ protected ILogElementState logElementState() {
getLocalizationManager().getLocalizedMessage(stateKey)));
}

protected ILogVisualState logVisualState() {
return this::logElementAction;
}

@Override
public By getLocator() {
return locator;
Expand All @@ -87,6 +98,11 @@ public IElementStateProvider state() {
: new DefaultElementStateProvider(locator, getConditionalWait(), getElementFinder(), logElementState());
}

@Override
public IVisualStateProvider visual() {
return new VisualStateProvider(getImageComparator(), getElementActionRetrier(), this::getElement, logVisualState());
}

@Override
public RemoteWebElement getElement(Duration timeout) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ protected void waitForElementsCount(By locator, ElementsCount count, ElementStat
localizationManager.getLocalizedMessage("loc.elements.found.but.should.not",
locator.toString(), state.toString()));
break;
case MORE_THEN_ZERO:
case MORE_THAN_ZERO:
conditionalWait.waitForTrue(() -> !elementFinder.findElements(locator, state, ZERO_TIMEOUT).isEmpty(),
localizationManager.getLocalizedMessage("loc.no.elements.found.by.locator",
locator.toString(), state.toString()));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package aquality.selenium.core.elements;

import aquality.selenium.core.elements.interfaces.IElementStateProvider;
import aquality.selenium.core.elements.interfaces.ILogElementState;
import aquality.selenium.core.logging.ILogElementState;
import org.openqa.selenium.WebElement;

public abstract class ElementStateProvider implements IElementStateProvider {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

public enum ElementsCount {
ZERO,
MORE_THEN_ZERO,
MORE_THAN_ZERO,
ANY
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package aquality.selenium.core.elements.interfaces;

import aquality.selenium.core.visualization.IVisualStateProvider;
import org.openqa.selenium.By;
import org.openqa.selenium.remote.RemoteWebElement;

Expand Down Expand Up @@ -27,6 +28,12 @@ public interface IElement extends IParent {
*/
IElementStateProvider state();

/**
* Gets element visual state.
* @return provider to define element's visual state.
*/
IVisualStateProvider visual();

/**
* Gets current element by specified {@link #getLocator()}
* Default timeout is provided in {@link aquality.selenium.core.configurations.ITimeoutConfiguration}
Expand Down
Loading