Skip to content

Commit 3ac9596

Browse files
committed
Extracted chunk definitions to not repeat them on every interface method
1 parent 246bf1d commit 3ac9596

11 files changed

+247
-226
lines changed

src/main/java/net/itarray/automotion/internal/ResponsiveUIChunkValidatorBase.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ public ResponsiveUIChunkValidatorBase alignedAsGrid(int horizontalGridSize, int
8484

8585
@Override
8686
public ChunkUIElementValidator areAlignedAsGridCells() {
87+
if (rootElements.size() == 2) {
88+
errors.add("banane");
89+
}
8790
return this;
8891
}
8992

src/main/java/net/itarray/automotion/validation/Chunk.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@
1515
public @interface Chunk {
1616
Element[] value() default {};
1717
String name() default "";
18+
String parameters() default "";
1819
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package net.itarray.automotion.validation;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Inherited;
5+
import java.lang.annotation.Retention;
6+
import java.lang.annotation.RetentionPolicy;
7+
import java.lang.annotation.Target;
8+
9+
10+
@Target(ElementType.TYPE)
11+
@Retention(RetentionPolicy.RUNTIME)
12+
@Inherited
13+
public @interface ChunkDef {
14+
Element[] value() default {};
15+
String name() default "";
16+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package net.itarray.automotion.validation;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Inherited;
5+
import java.lang.annotation.Retention;
6+
import java.lang.annotation.RetentionPolicy;
7+
import java.lang.annotation.Target;
8+
9+
10+
@Target(ElementType.TYPE)
11+
@Retention(RetentionPolicy.RUNTIME)
12+
@Inherited
13+
public @interface ChunkDefs {
14+
ChunkDef[] value() default {};
15+
}

src/main/java/net/itarray/automotion/validation/ChunkUIElementValidator.java

Lines changed: 70 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,53 @@
22

33
import org.openqa.selenium.WebElement;
44

5+
@ChunkDefs({
6+
@ChunkDef(name = "empty", value={
7+
}),
8+
@ChunkDef(name = "one element", value={
9+
@Element({10, 20, 40, 50})
10+
}),
11+
@ChunkDef(name = "two overlapping elements", value={
12+
@Element({10, 20, 30, 35}),
13+
@Element({15, 25, 35, 50}),
14+
}),
15+
@ChunkDef(name="three elements with different sizes in a row with different gutters", value={
16+
@Element({100, 50, 300, 60}),
17+
@Element({400, 50, 700, 60}),
18+
@Element({900, 50, 1200, 60}),
19+
}),
20+
@ChunkDef(name="seven elements in three rows with different sizes and gutters", value={
21+
@Element({100, 50, 300, 60}),
22+
@Element({400, 50, 700, 70}),
23+
@Element({900, 50, 1200, 80}),
24+
@Element({100, 150, 300, 160}),
25+
@Element({400, 150, 700, 170}),
26+
@Element({900, 150, 1200, 180}),
27+
@Element({100, 250, 300, 160}),
28+
})
29+
30+
})
531
public interface ChunkUIElementValidator {
632

733
boolean validate();
834

935
// ? filled needs to be expressed somehow
1036
// areAlignedInColumns(numberOfColumns)
37+
@ValidChunks({
38+
@Chunk(parameters = "3", name = "empty"),
39+
@Chunk(parameters = "1", name = "one element"),
40+
@Chunk(parameters = "3", name="three elements with different sizes in a row with different gutters"),
41+
@Chunk(parameters = "4", name="three elements with different sizes in a row with different gutters"),
42+
@Chunk(parameters = "3", name = "seven elements in three rows with different sizes and gutters"),
43+
})
44+
@InvalidChunks({
45+
@Chunk(parameters = "2", name="three elements with different sizes in a row with different gutters"),
46+
@Chunk(parameters = "2", name = "seven elements in three rows with different sizes and gutters"),
47+
@Chunk(parameters = "4", name = "seven elements in three rows with different sizes and gutters"),
48+
})
1149
ChunkUIElementValidator alignedAsGrid(int horizontalGridSize);
1250

1351
// areAlignedInColumnsAndRows(numberOfColumns)
14-
ChunkUIElementValidator alignedAsGrid(int horizontalGridSize, int verticalGridSize);
15-
1652
/**
1753
* Validate that this chunks elements are aligned in a grid of cells (not areas).
1854
*
@@ -21,21 +57,32 @@ public interface ChunkUIElementValidator {
2157
* @return this
2258
*/
2359
@ValidChunks({
24-
@Chunk(name = "empty chunk", value={
25-
}),
26-
@Chunk(name = "single element chunk", value={
27-
@Element({10, 20, 30, 35}),
28-
}),
60+
@Chunk(name = "empty"),
61+
@Chunk(name = "single element"),
62+
@Chunk(name = "seven elements in three rows with different sizes and gutters"),
2963
})
3064
@InvalidChunks({
31-
@Chunk(name = "chunk with two overlapping elements", value={
32-
@Element({10, 20, 30, 35}),
33-
@Element({15, 25, 35, 50}),
34-
}),
65+
@Chunk(name = "two overlapping elements"),
3566
})
3667
ChunkUIElementValidator areAlignedAsGridCells();
3768

69+
3870
// area
71+
@ValidChunks({
72+
@Chunk(parameters = "1, 1", name = "one element"),
73+
@Chunk(parameters = "3, 1", name="three elements with different sizes in a row with different gutters"),
74+
@Chunk(parameters = "4, 1", name="three elements with different sizes in a row with different gutters"),
75+
@Chunk(parameters = "3, 3", name = "seven elements in three rows with different sizes and gutters"),
76+
})
77+
@InvalidChunks({
78+
@Chunk(parameters = "3, 3", name = "empty"),
79+
@Chunk(parameters = "3, 2", name="three elements with different sizes in a row with different gutters"),
80+
@Chunk(parameters = "4, 2", name="three elements with different sizes in a row with different gutters"),
81+
@Chunk(parameters = "3, 2", name = "seven elements in three rows with different sizes and gutters"),
82+
@Chunk(parameters = "3, 4", name = "seven elements in three rows with different sizes and gutters"),
83+
@Chunk(parameters = "4, 1", name = "seven elements in three rows with different sizes and gutters"),
84+
})
85+
ChunkUIElementValidator alignedAsGrid(int horizontalGridSize, int verticalGridSize);
3986

4087
ChunkUIElementValidator doNotOverlap();
4188
ChunkUIElementValidator areInsideOf(WebElement containerElement, String readableContainerName);
@@ -51,9 +98,21 @@ public interface ChunkUIElementValidator {
5198

5299
// alignment
53100

101+
@ValidChunks({
102+
@Chunk(name = "one element"),
103+
})
54104
ChunkUIElementValidator areLeftAligned();
105+
@ValidChunks({
106+
@Chunk(name = "one element"),
107+
})
55108
ChunkUIElementValidator areRightAligned();
109+
@ValidChunks({
110+
@Chunk(name = "one element"),
111+
})
56112
ChunkUIElementValidator areTopAligned();
113+
@ValidChunks({
114+
@Chunk(name = "one element"),
115+
})
57116
ChunkUIElementValidator areBottomAligned();
58117

59118
//
Lines changed: 99 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,149 @@
11
package net.itarray.automotion.tests.grid;
22

33
import com.google.common.collect.Lists;
4+
import net.itarray.automotion.internal.ResponsiveUIValidatorBase;
45
import net.itarray.automotion.validation.Chunk;
56
import net.itarray.automotion.validation.ChunkUIElementValidator;
7+
import net.itarray.automotion.validation.Element;
68
import net.itarray.automotion.validation.InvalidChunks;
9+
import net.itarray.automotion.validation.ResponsiveUIValidator;
10+
import net.itarray.automotion.validation.UISnapshot;
711
import net.itarray.automotion.validation.ValidChunks;
12+
import org.junit.Before;
813
import org.junit.Test;
914
import org.junit.runner.RunWith;
1015
import org.junit.runners.Parameterized;
1116
import org.junit.runners.Parameterized.Parameter;
1217
import org.junit.runners.Parameterized.Parameters;
18+
import org.openqa.selenium.Dimension;
19+
import org.openqa.selenium.WebElement;
20+
import rectangles.DummyDriverFacade;
1321

14-
import java.lang.annotation.Annotation;
22+
import java.lang.reflect.InvocationTargetException;
1523
import java.lang.reflect.Method;
16-
import java.util.ArrayList;
17-
import java.util.Arrays;
1824
import java.util.Collection;
1925
import java.util.List;
20-
import java.util.Objects;
21-
import java.util.stream.Collectors;
22-
import java.util.stream.Stream;
26+
import java.util.Optional;
27+
28+
import static com.google.common.collect.Lists.newArrayList;
29+
import static org.assertj.core.api.Assertions.assertThat;
30+
import static rectangles.DummyWebElement.createElement;
2331

2432
@RunWith(Parameterized.class)
33+
@PageSize
2534
public class AnnotatedSpecificationTest {
2635

36+
protected ChunkUIElementValidator chunkValidator;
37+
38+
@Before
39+
public void setUp() {
40+
DummyDriverFacade driverFacade = new DummyDriverFacade();
41+
42+
PageSize pageSize = getClass().getAnnotation(PageSize.class);
43+
driverFacade.setPageSize(new Dimension(pageSize.xy()[0], pageSize.xy()[1]));
44+
45+
ResponsiveUIValidator uiValidator = new ResponsiveUIValidator(driverFacade);
46+
UISnapshot snapshot = uiValidator.snapshot();
47+
48+
List<WebElement> webElements = chunk;
49+
boolean allowEmpty = true;
50+
chunkValidator =
51+
allowEmpty ?
52+
snapshot.findZeroOrMoreElements(webElements) :
53+
snapshot.findElements(webElements);
54+
}
55+
56+
public static List<WebElement> toWebElements(Chunk chunk) {
57+
List<WebElement> webElements = newArrayList();
58+
for (Element element : chunk.value()) {
59+
webElements.add(createElement(
60+
element.value()[0],
61+
element.value()[1],
62+
element.value()[2],
63+
element.value()[3]
64+
));
65+
}
66+
return webElements;
67+
}
68+
2769
@Parameters(name = "{2}")
2870
public static Collection<Object[]> data() {
71+
72+
ChunkRepository repository = new ChunkRepository();
73+
repository.addClass(ChunkUIElementValidator.class);
74+
2975
Collection<Object[]> result = Lists.newArrayList();
3076
for (Method method : ChunkUIElementValidator.class.getDeclaredMethods()) {
3177
ValidChunks validChunks = method.getAnnotation(ValidChunks.class);
3278
if (validChunks != null) {
3379
for (Chunk chunk : validChunks.value()) {
34-
String name = String.format("%s is valid on %s", method.getName(), chunk.name());
35-
result.add(new Object[]{method, chunk, name});
80+
String name = String.format("%s(%s) is valid on %s chunk", method.getName(), chunk.parameters(), chunk.name());
81+
Optional<List<WebElement>> repositoryChunk = repository.getChunk(chunk.name());
82+
List<WebElement> webElements = repositoryChunk.orElse(toWebElements(chunk));
83+
result.add(new Object[]{method, webElements, name, true, parseArgs(chunk.parameters())});
3684
}
3785
}
3886
InvalidChunks invalidChunks = method.getAnnotation(InvalidChunks.class);
39-
if (validChunks != null) {
87+
if (invalidChunks != null) {
4088
for (Chunk chunk : invalidChunks.value()) {
41-
String name = String.format("%s is invalid on %s", method.getName(), chunk.name());
42-
result.add(new Object[]{method, chunk, name});
89+
String name = String.format("%s(%s) is not valid on %s chunk", method.getName(), chunk.parameters(), chunk.name());
90+
Optional<List<WebElement>> repositoryChunk = repository.getChunk(chunk.name());
91+
List<WebElement> webElements = repositoryChunk.orElse(toWebElements(chunk));
92+
result.add(new Object[]{method, webElements, name, false, parseArgs(chunk.parameters())});
4393
}
4494
}
4595
}
4696
return result;
4797
}
4898

99+
public static Object[] parseArgs(String parameters1) {
100+
String parameterString = parameters1.trim();
101+
String[] parameters = parameterString.isEmpty() ? new String[0] : parameterString.split(",");
102+
List<Object> p = Lists.newArrayList();
103+
for (String parameter : parameters) {
104+
p.add(Integer.parseInt(parameter.trim()));
105+
}
106+
return p.toArray();
107+
}
108+
49109
@Parameter
50110
public Method method;
51111

52112
@Parameter(1)
53-
public Chunk chunk;
113+
public List<WebElement> chunk;
54114

55115
@Parameter(2)
56116
public String name;
57117

118+
@Parameter(3)
119+
public boolean shouldBeValid;
120+
121+
@Parameter(4)
122+
public Object[] arguments;
123+
58124
@Test
59125
public void valid() {
126+
try {
127+
method.invoke(chunkValidator, arguments);
128+
} catch (IllegalAccessException | InvocationTargetException e) {
129+
throw new RuntimeException(e);
130+
}
131+
if (shouldBeValid) {
132+
assertValid();
133+
} else {
134+
assertInvalid();
135+
}
136+
}
137+
138+
public void assertValid() {
139+
ResponsiveUIValidatorBase base = (ResponsiveUIValidatorBase) chunkValidator;
140+
String lastMessage = base.getErrors().getLastMessage();
141+
assertThat(lastMessage).describedAs("should be valid").isNull();
142+
}
60143

61-
System.out.println("method = " + method);
144+
public void assertInvalid() {
145+
ResponsiveUIValidatorBase base = (ResponsiveUIValidatorBase) chunkValidator;
146+
String lastMessage = base.getErrors().getLastMessage();
147+
assertThat(lastMessage).describedAs("should not be valid").isNotNull();
62148
}
63149
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package net.itarray.automotion.tests.grid;
2+
3+
import net.itarray.automotion.validation.ChunkDef;
4+
import net.itarray.automotion.validation.ChunkDefs;
5+
import net.itarray.automotion.validation.Element;
6+
import org.assertj.core.util.Maps;
7+
import org.openqa.selenium.WebElement;
8+
9+
import java.util.List;
10+
import java.util.Map;
11+
import java.util.Optional;
12+
13+
import static com.google.common.collect.Lists.newArrayList;
14+
import static rectangles.DummyWebElement.createElement;
15+
16+
public class ChunkRepository {
17+
18+
Map<String, List<WebElement>> chunksByName = Maps.newHashMap();
19+
20+
public void addClass(Class<?> aClass) {
21+
ChunkDefs definitions = aClass.getAnnotation(ChunkDefs.class);
22+
if (definitions == null) {
23+
return;
24+
}
25+
for (ChunkDef definition : definitions.value()) {
26+
List<WebElement> chunk = newArrayList();
27+
Element[] elements = definition.value();
28+
for (Element element : elements) {
29+
chunk.add(createElement(
30+
element.value()[0],
31+
element.value()[1],
32+
element.value()[2],
33+
element.value()[3]
34+
));
35+
}
36+
chunksByName.put(definition.name(), chunk);
37+
}
38+
}
39+
40+
public Optional<List<WebElement>> getChunk(String name) {
41+
return Optional.ofNullable(chunksByName.get(name));
42+
}
43+
}

0 commit comments

Comments
 (0)