diff --git a/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingOptions.java b/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingOptions.java index baad10d2a..e2990ea23 100644 --- a/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingOptions.java +++ b/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingOptions.java @@ -24,6 +24,8 @@ public class OccurrenceMatchingOptions extends BaseComparisonOptions { private Double threshold; + private Boolean multiple; + private Integer matchNeighbourThreshold; /** * At what normalized threshold to reject an occurrence. @@ -36,11 +38,38 @@ public OccurrenceMatchingOptions withThreshold(double threshold) { return this; } + /** + * Whether to enable the support of multiple image occurrences. + * + * @since Appium 1.21.0 + * @return self instance for chaining. + */ + public OccurrenceMatchingOptions enableMultiple() { + this.multiple = true; + return this; + } + + /** + * The pixel distance between matches we consider + * to be part of the same template match. This option is only + * considered if multiple matches mode is enabled. + * 10 pixels by default. + * + * @since Appium 1.21.0 + * @return self instance for chaining. + */ + public OccurrenceMatchingOptions withMatchNeighbourThreshold(int threshold) { + this.matchNeighbourThreshold = threshold; + return this; + } + @Override public Map build() { final ImmutableMap.Builder builder = ImmutableMap.builder(); builder.putAll(super.build()); ofNullable(threshold).map(x -> builder.put("threshold", x)); + ofNullable(matchNeighbourThreshold).map(x -> builder.put("matchNeighbourThreshold", x)); + ofNullable(multiple).map(x -> builder.put("multiple", x)); return builder.build(); } } diff --git a/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingResult.java b/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingResult.java index 273747247..256a1636a 100644 --- a/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingResult.java +++ b/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingResult.java @@ -18,13 +18,23 @@ import org.openqa.selenium.Rectangle; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; public class OccurrenceMatchingResult extends ComparisonResult { private static final String RECT = "rect"; + private static final String MULTIPLE = "multiple"; + + private final boolean isAtRoot; public OccurrenceMatchingResult(Map input) { + this(input, true); + } + + private OccurrenceMatchingResult(Map input, boolean isAtRoot) { super(input); + this.isAtRoot = isAtRoot; } /** @@ -37,4 +47,25 @@ public Rectangle getRect() { //noinspection unchecked return mapToRect((Map) getCommandResult().get(RECT)); } + + /** + * Returns the list of multiple matches (if any). + * This property only works if the `multiple` option is enabled. + * + * @since Appium 1.21.0 + * @return The list containing properties of each single match or an empty list. + * @throws IllegalStateException If the accessor is called on a non-root match instance. + */ + public List getMultiple() { + if (!isAtRoot) { + throw new IllegalStateException("Only the root match could contain multiple submatches"); + } + verifyPropertyPresence(MULTIPLE); + + //noinspection unchecked + List> multiple = (List>) getCommandResult().get(MULTIPLE); + return multiple.stream() + .map((m) -> new OccurrenceMatchingResult(m, false)) + .collect(Collectors.toList()); + } }