Skip to content

Commit 4ac6faf

Browse files
committed
Implemented DumpsManager and Form abstraction
Finished visualization implementation, add tests
1 parent cdcc63e commit 4ac6faf

File tree

18 files changed

+777
-44
lines changed

18 files changed

+777
-44
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
# Log file
55
*.log
66

7+
# Visualization
8+
visualDumps/
9+
710
# BlueJ files
811
*.ctxt
912

src/main/java/aquality/selenium/core/applications/AqualityModule.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ protected void configure() {
4545
bind(ITimeoutConfiguration.class).to(getTimeoutConfigurationImplementation()).in(Singleton.class);
4646
bind(IRetryConfiguration.class).to(getRetryConfigurationImplementation()).in(Singleton.class);
4747
bind(IElementCacheConfiguration.class).to(getElementCacheConfigurationImplementation()).in(Singleton.class);
48-
bind(IVisualConfiguration.class).to(getVisualConfigurationImplementation()).in(Singleton.class);
48+
bind(IVisualizationConfiguration.class).to(getVisualConfigurationImplementation()).in(Singleton.class);
4949
bind(IElementActionRetrier.class).to(getElementActionRetrierImplementation()).in(Singleton.class);
5050
bind(IActionRetrier.class).to(getActionRetrierImplementation()).in(Singleton.class);
5151
bind(ILocalizationManager.class).to(getLocalizationManagerImplementation()).in(Singleton.class);

src/main/java/aquality/selenium/core/configurations/IConfigurationsModule.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
*/
66
public interface IConfigurationsModule {
77
/**
8-
* @return class which implements {@link IVisualConfiguration}
8+
* @return class which implements {@link IVisualizationConfiguration}
99
*/
10-
default Class<? extends IVisualConfiguration> getVisualConfigurationImplementation() {
11-
return VisualConfiguration.class;
10+
default Class<? extends IVisualizationConfiguration> getVisualConfigurationImplementation() {
11+
return VisualizationConfiguration.class;
1212
}
1313

1414
/**

src/main/java/aquality/selenium/core/configurations/IVisualConfiguration.java renamed to src/main/java/aquality/selenium/core/configurations/IVisualizationConfiguration.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
/**
44
* Represents visualization configuration, used for image comparison.
55
*/
6-
public interface IVisualConfiguration {
6+
public interface IVisualizationConfiguration {
77
/**
88
* Image format for comparison.
99
* @return image format.

src/main/java/aquality/selenium/core/configurations/VisualConfiguration.java renamed to src/main/java/aquality/selenium/core/configurations/VisualizationConfiguration.java

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,14 @@
44
import aquality.selenium.core.utilities.ISettingsFile;
55
import com.google.inject.Inject;
66

7-
import javax.imageio.ImageIO;
87
import java.io.File;
98
import java.io.IOException;
10-
import java.util.Arrays;
119

1210
/**
1311
* Represents visualization configuration, used for image comparison.
1412
* Uses {@link ISettingsFile} as source for configuration values.
1513
*/
16-
public class VisualConfiguration implements IVisualConfiguration {
14+
public class VisualizationConfiguration implements IVisualizationConfiguration {
1715
private String imageFormat;
1816
private Integer maxFullFileNameLength;
1917
private Float defaultThreshold;
@@ -28,21 +26,15 @@ public class VisualConfiguration implements IVisualConfiguration {
2826
* @param settingsFile settings file.
2927
*/
3028
@Inject
31-
public VisualConfiguration(ISettingsFile settingsFile) {
29+
public VisualizationConfiguration(ISettingsFile settingsFile) {
3230
this.settingsFile = settingsFile;
3331
}
3432

3533
@Override
3634
public String getImageFormat() {
3735
if (imageFormat == null) {
38-
String[] supportedFormats = ImageIO.getWriterFormatNames();
3936
String valueFromConfig = settingsFile.getValueOrDefault("/visualization/imageExtension", "png").toString();
40-
String actualFormat = valueFromConfig.startsWith(".") ? valueFromConfig.substring(1) : valueFromConfig;
41-
if (Arrays.stream(supportedFormats).noneMatch(format -> format.equals(actualFormat))) {
42-
throw new IllegalArgumentException(String.format(
43-
"Format [%s] is not supported by current JRE. Supported formats: %s", actualFormat, Arrays.toString(supportedFormats)));
44-
}
45-
imageFormat = actualFormat;
37+
imageFormat = valueFromConfig.startsWith(".") ? valueFromConfig.substring(1) : valueFromConfig;
4638
}
4739
return imageFormat;
4840
}
@@ -86,7 +78,7 @@ public int getComparisonHeight() {
8678
@Override
8779
public String getPathToDumps() {
8880
if (pathToDumps == null) {
89-
pathToDumps = settingsFile.getValueOrDefault(".visualization.pathToDumps", "./src/test/resources/VisualDumps/").toString();
81+
pathToDumps = settingsFile.getValueOrDefault("/visualization/pathToDumps", "./src/test/resources/visualDumps/").toString();
9082
if (pathToDumps.startsWith(".")) {
9183
try {
9284
pathToDumps = new File(pathToDumps).getCanonicalPath();
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
package aquality.selenium.core.forms;
2+
3+
import aquality.selenium.core.configurations.IVisualizationConfiguration;
4+
import aquality.selenium.core.elements.Element;
5+
import aquality.selenium.core.elements.ElementState;
6+
import aquality.selenium.core.elements.interfaces.IElement;
7+
import aquality.selenium.core.localization.ILocalizedLogger;
8+
import aquality.selenium.core.logging.Logger;
9+
import aquality.selenium.core.visualization.DumpManager;
10+
import aquality.selenium.core.visualization.IDumpManager;
11+
12+
import java.lang.reflect.Field;
13+
import java.util.HashMap;
14+
import java.util.Map;
15+
import java.util.stream.Collectors;
16+
17+
/**
18+
* Describes form that could be used for visualization purposes (see {@link IDumpManager}).
19+
*
20+
* @param <T> Base type(class or interface) of elements of this form.
21+
*/
22+
public abstract class Form<T extends IElement> implements IForm {
23+
private final Class<T> elementClass;
24+
25+
/**
26+
* Initializes the form.
27+
*
28+
* @param elementClass Base type(class or interface) of elements of this form.
29+
*/
30+
protected Form(Class<T> elementClass) {
31+
this.elementClass = elementClass;
32+
}
33+
34+
/**
35+
* Visualization configuration used by {@link IDumpManager}.
36+
* Could be obtained from AqualityServices.
37+
*
38+
* @return visualization configuration.
39+
*/
40+
protected abstract IVisualizationConfiguration getVisualizationConfiguration();
41+
42+
/**
43+
* Localized logger used by {@link IDumpManager}.
44+
* Could be obtained from AqualityServices.
45+
*
46+
* @return localized logger.
47+
*/
48+
protected abstract ILocalizedLogger getLocalizedLogger();
49+
50+
/**
51+
* Name of the current form.
52+
*
53+
* @return form's name.
54+
*/
55+
@Override
56+
public abstract String getName();
57+
58+
/**
59+
* Gets dump manager for the current form that could be used for visualization purposes,
60+
* such as saving and comparing dumps.
61+
* Uses getElementsForVisualization() as basis for dump creation and comparison.
62+
*
63+
* @return form's dump manager.
64+
*/
65+
@Override
66+
public IDumpManager dump() {
67+
return new DumpManager<>(getElementsForVisualization(), getName(), getVisualizationConfiguration(), getLocalizedLogger());
68+
}
69+
70+
/**
71+
* List of pairs uniqueName-element to be used for dump saving and comparing.
72+
* By default, only currently displayed elements to be used with getDisplayedElements().
73+
* You can override this property with defined getAllElements(), getAllCurrentFormElements,
74+
* getElementsInitializedAsDisplayed(), or your own element set.
75+
*
76+
* @return elements for visualization.
77+
*/
78+
protected Map<String, T> getElementsForVisualization() {
79+
return getDisplayedElements();
80+
}
81+
82+
/**
83+
* List of pairs uniqueName-element from the current form and it's parent forms, which are currently displayed.
84+
*
85+
* @return list of displayed elements.
86+
*/
87+
protected Map<String, T> getDisplayedElements() {
88+
return getAllElements().entrySet().stream().filter(element -> element.getValue().state().isDisplayed())
89+
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
90+
}
91+
92+
/**
93+
* List of pairs uniqueName-element from the current form and it's parent forms, which were initialized as displayed.
94+
*
95+
* @return list of displayed elements.
96+
*/
97+
protected Map<String, T> getElementsInitializedAsDisplayed() {
98+
return getAllElements().entrySet().stream().filter(element -> {
99+
try {
100+
Field stateField = Element.class.getDeclaredField("elementState");
101+
stateField.setAccessible(true);
102+
ElementState elementState = (ElementState) stateField.get(element.getValue());
103+
stateField.setAccessible(false);
104+
return ElementState.DISPLAYED == elementState;
105+
} catch (ReflectiveOperationException exception) {
106+
Logger.getInstance().fatal("Failed to read state the element: " + element.getKey(), exception);
107+
return false;
108+
}
109+
}).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
110+
}
111+
112+
/**
113+
* List of pairs uniqueName-element from the current form and it's parent forms.
114+
*
115+
* @return list of elements.
116+
*/
117+
protected Map<String, T> getAllElements() {
118+
Map<String, T> map = new HashMap<>();
119+
addElementsToMap(map, this.getClass().getDeclaredFields());
120+
Class<?> superClass = this.getClass().getSuperclass();
121+
while (superClass != null) {
122+
addElementsToMap(map, superClass.getDeclaredFields());
123+
superClass = superClass.getSuperclass();
124+
}
125+
return map;
126+
}
127+
128+
/**
129+
* List of pairs uniqueName-element from the current form.
130+
*
131+
* @return list of elements.
132+
*/
133+
protected Map<String, T> getAllCurrentFormElements() {
134+
Map<String, T> map = new HashMap<>();
135+
addElementsToMap(map, this.getClass().getDeclaredFields());
136+
return map;
137+
}
138+
139+
/**
140+
* Adds pairs uniqueName-element from the specified fields array to map using the reflection.
141+
*
142+
* @param map map to save elements.
143+
* @param fields any class fields (only assignable from target type will be added to map).
144+
*/
145+
protected void addElementsToMap(Map<String, T> map, Field[] fields) {
146+
for (Field field : fields) {
147+
try {
148+
if (elementClass.isAssignableFrom(field.getType())) {
149+
field.setAccessible(true);
150+
//noinspection unchecked
151+
map.put(field.getName(), (T) field.get(this));
152+
field.setAccessible(false);
153+
}
154+
}
155+
catch (IllegalAccessException exception) {
156+
Logger.getInstance().fatal("Failed to read the element: " + field.getName(), exception);
157+
}
158+
}
159+
}
160+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package aquality.selenium.core.forms;
2+
3+
import aquality.selenium.core.visualization.IDumpManager;
4+
5+
/**
6+
* Describes form that could be used for visualization purposes, such as saving and comparing dumps.
7+
* See {@link aquality.selenium.core.visualization.IDumpManager} for more details.
8+
*/
9+
public interface IForm {
10+
/**
11+
* Name of the current form.
12+
*
13+
* @return form's name.
14+
*/
15+
String getName();
16+
17+
/**
18+
* Gets dump manager for the current form that could be used for visualization purposes,
19+
* such as saving and comparing dumps.
20+
*
21+
* @return form's dump manager.
22+
*/
23+
IDumpManager dump();
24+
}

0 commit comments

Comments
 (0)