1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.archunit;
16
17 import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.methods;
18 import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
19
20 import java.util.HashSet;
21 import java.util.Set;
22 import java.util.stream.Collectors;
23
24 import org.htmlunit.BrowserVersion;
25 import org.htmlunit.junit.annotation.AnnotationUtils;
26 import org.junit.jupiter.api.Assertions;
27 import org.junit.jupiter.api.Test;
28
29 import com.tngtech.archunit.core.domain.JavaClasses;
30 import com.tngtech.archunit.core.domain.JavaMethod;
31 import com.tngtech.archunit.junit.AnalyzeClasses;
32 import com.tngtech.archunit.junit.ArchTest;
33 import com.tngtech.archunit.lang.ArchCondition;
34 import com.tngtech.archunit.lang.ArchRule;
35 import com.tngtech.archunit.lang.ConditionEvents;
36 import com.tngtech.archunit.lang.SimpleConditionEvent;
37
38
39
40
41
42
43 @AnalyzeClasses(packages = "org.htmlunit")
44 public class Architecture2Test {
45
46
47
48
49
50 @ArchTest
51 public static void allPropertyTestShouldTestTheSameObjects(final JavaClasses classes) {
52 compare(classes, "ElementPropertiesTest", "ElementOwnPropertiesTest");
53 compare(classes, "ElementPropertiesTest", "ElementOwnPropertySymbolsTest");
54 }
55
56
57
58
59
60 @ArchTest
61 public static void allElementTestShouldTestTheSameObjects(final JavaClasses classes) {
62 compare(classes, "ElementChildNodesTest", "ElementClosesItselfTest");
63 compare(classes, "ElementChildNodesTest", "ElementCreationTest");
64 compare(classes, "ElementChildNodesTest", "ElementDefaultStyleDisplayTest");
65 compare(classes, "ElementChildNodesTest", "ElementOuterHtmlTest");
66 }
67
68
69
70
71
72 @ArchTest
73 public static void allHostTestShouldTestTheSameObjects(final JavaClasses classes) {
74 compare(classes, "HostClassNameTest", "HostTypeOfTest");
75 compare(classes, "HostClassNameTest", "DedicatedWorkerGlobalScopeClassNameTest");
76 compare(classes, "HostClassNameTest", "DedicatedWorkerGlobalScopeTypeOfTest");
77 }
78
79 private static void compare(final JavaClasses classes, final String oneName, final String anotherName) {
80 final Set<String> oneTests =
81 classes.get("org.htmlunit.general." + oneName).getAllMethods().stream()
82 .filter(m -> m.tryGetAnnotationOfType("org.junit.Test").isPresent())
83 .map(m -> m.getName())
84 .collect(Collectors.toSet());
85
86 final Set<String> anotherTests =
87 classes.get("org.htmlunit.general." + anotherName).getAllMethods().stream()
88 .filter(m -> m.tryGetAnnotationOfType("org.junit.Test").isPresent())
89 .map(m -> m.getName())
90 .collect(Collectors.toSet());
91
92 final Set<String> tmp = new HashSet<>(anotherTests);
93 tmp.removeAll(oneTests);
94 oneTests.removeAll(anotherTests);
95
96 if (tmp.size() + oneTests.size() > 0) {
97 if (tmp.size() == 0) {
98 Assertions.fail("The " + oneTests.size() + " method(s) "
99 + oneTests.stream().sorted().collect(Collectors.toList())
100 + " are available in " + oneName + " but missing in " + anotherName + ".");
101 }
102 else if (oneTests.size() == 0) {
103 anotherTests.removeAll(oneTests);
104 Assertions.fail("The " + tmp.size() + " method(s) "
105 + tmp.stream().sorted().collect(Collectors.toList())
106 + " are available in " + anotherName + " but missing in " + oneName + ".");
107 }
108
109 Assertions.fail("The " + tmp.size() + " method(s) "
110 + tmp.stream().sorted().collect(Collectors.toList())
111 + " are available in " + anotherName + " but missing in " + oneName
112 + " and the " + oneTests.size() + " method(s) "
113 + oneTests.stream().sorted().collect(Collectors.toList())
114 + " are available in " + oneName + " but missing in " + anotherName + ".");
115 }
116 }
117
118
119
120
121 @ArchTest
122 public static final ArchRule isChrome = noClasses()
123 .that()
124 .doNotHaveFullyQualifiedName("org.htmlunit.BrowserVersion")
125 .and().doNotHaveFullyQualifiedName("org.htmlunit.javascript.configuration.AbstractJavaScriptConfiguration")
126 .and().doNotHaveFullyQualifiedName("org.htmlunit.css.BrowserConfiguration$Chrome")
127 .and().doNotHaveFullyQualifiedName("org.htmlunit.css.BrowserConfiguration$ChromeAndEdge")
128 .and().doNotHaveFullyQualifiedName("org.htmlunit.css.BrowserConfiguration$ChromeAndEdgeAndFirefox")
129 .and().doNotHaveFullyQualifiedName("org.htmlunit.css.BrowserConfiguration$ChromeAndEdgeNotIterable")
130 .and().doNotHaveFullyQualifiedName("org.htmlunit.javascript.host.dom.Document")
131 .and().doNotHaveFullyQualifiedName("org.htmlunit.javascript.host.intl.DateTimeFormat")
132 .and().doNotHaveFullyQualifiedName("org.htmlunit.javascript.host.intl.NumberFormat")
133
134 .should().callMethod(BrowserVersion.class, "isChrome", new Class[] {});
135
136
137
138
139 @ArchTest
140 public static final ArchRule isEdge = noClasses()
141 .that()
142 .doNotHaveFullyQualifiedName("org.htmlunit.BrowserVersion")
143 .and().doNotHaveFullyQualifiedName("org.htmlunit.javascript.configuration.AbstractJavaScriptConfiguration")
144 .and().doNotHaveFullyQualifiedName("org.htmlunit.css.BrowserConfiguration$Edge")
145 .and().doNotHaveFullyQualifiedName("org.htmlunit.css.BrowserConfiguration$Chrome")
146 .and().doNotHaveFullyQualifiedName("org.htmlunit.css.BrowserConfiguration$ChromeAndEdge")
147 .and().doNotHaveFullyQualifiedName("org.htmlunit.css.BrowserConfiguration$ChromeAndEdgeAndFirefox")
148 .and().doNotHaveFullyQualifiedName("org.htmlunit.css.BrowserConfiguration$ChromeAndEdgeNotIterable")
149 .and().doNotHaveFullyQualifiedName("org.htmlunit.javascript.host.dom.Document")
150 .and().doNotHaveFullyQualifiedName("org.htmlunit.javascript.host.intl.DateTimeFormat")
151 .and().doNotHaveFullyQualifiedName("org.htmlunit.javascript.host.intl.NumberFormat")
152
153 .should().callMethod(BrowserVersion.class, "isEdge", new Class[] {});
154
155
156
157
158 @ArchTest
159 public static final ArchRule isFirefox = noClasses()
160 .that()
161 .doNotHaveFullyQualifiedName("org.htmlunit.BrowserVersion")
162 .and().doNotHaveFullyQualifiedName("org.htmlunit.javascript.configuration.AbstractJavaScriptConfiguration")
163 .and().doNotHaveFullyQualifiedName("org.htmlunit.javascript.host.worker.DedicatedWorkerGlobalScope")
164
165 .and().doNotHaveFullyQualifiedName("org.htmlunit.css.BrowserConfiguration$FF")
166 .and().doNotHaveFullyQualifiedName("org.htmlunit.css.BrowserConfiguration$FFNotIterable")
167 .and().doNotHaveFullyQualifiedName("org.htmlunit.css.BrowserConfiguration$FFESR")
168 .and().doNotHaveFullyQualifiedName("org.htmlunit.css.BrowserConfiguration$FFLatest")
169 .and().doNotHaveFullyQualifiedName("org.htmlunit.css.BrowserConfiguration$ChromeAndEdgeAndFirefox")
170
171 .and().doNotHaveFullyQualifiedName("org.htmlunit.general.huge.ElementClosesElementTest")
172 .should().callMethod(BrowserVersion.class, "isFirefox", new Class[] {});
173
174
175
176
177 @ArchTest
178 public static final ArchRule isFirefoxESR = noClasses()
179 .that()
180 .doNotHaveFullyQualifiedName("org.htmlunit.BrowserVersion")
181 .and().doNotHaveFullyQualifiedName("org.htmlunit.javascript.configuration.AbstractJavaScriptConfiguration")
182 .and().doNotHaveFullyQualifiedName("org.htmlunit.javascript.host.worker.DedicatedWorkerGlobalScope")
183
184 .and().doNotHaveFullyQualifiedName("org.htmlunit.javascript.host.intl.DateTimeFormat")
185 .and().doNotHaveFullyQualifiedName("org.htmlunit.javascript.host.intl.NumberFormat")
186 .should().callMethod(BrowserVersion.class, "isFirefoxESR", new Class[] {});
187
188
189
190
191 @ArchTest
192 public static final ArchRule hamcrest = noClasses()
193 .should().dependOnClassesThat().resideInAPackage("org.hamcrest..");
194
195 private static final ArchCondition<JavaMethod> haveConsistentTestAnnotations =
196 new ArchCondition<JavaMethod>("have consistent HtmlUnit test annotations") {
197 @Override
198 public void check(final JavaMethod method, final ConditionEvents events) {
199 try {
200 AnnotationUtils.assertAlerts(method.reflect());
201 }
202 catch (final AssertionError e) {
203 events.add(SimpleConditionEvent.violated(method, e.getMessage()));
204 }
205 }
206 };
207
208
209
210
211 @ArchTest
212 public static final ArchRule consistentTestAnnotations = methods()
213 .that().areAnnotatedWith(Test.class)
214 .and().areNotDeclaredIn("org.htmlunit.junit.annotation.AnnotationUtilsTest")
215 .should(haveConsistentTestAnnotations);
216 }