1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.junit;
16
17 import static org.junit.Assert.assertArrayEquals;
18 import static org.junit.Assert.assertTrue;
19 import static org.junit.Assert.fail;
20
21 import java.lang.reflect.Method;
22 import java.util.List;
23
24 import org.apache.commons.lang3.SystemUtils;
25 import org.htmlunit.BrowserVersion;
26 import org.htmlunit.WebDriverTestCase;
27 import org.htmlunit.WebTestCase;
28 import org.htmlunit.junit.annotation.Alerts;
29 import org.htmlunit.junit.annotation.BuggyWebDriver;
30 import org.htmlunit.junit.annotation.HtmlUnitNYI;
31 import org.htmlunit.junit.annotation.NotYetImplemented;
32 import org.htmlunit.junit.annotation.OS;
33 import org.htmlunit.junit.annotation.TestedBrowser;
34 import org.htmlunit.junit.annotation.Tries;
35 import org.junit.Test;
36 import org.junit.internal.runners.model.ReflectiveCallable;
37 import org.junit.internal.runners.statements.Fail;
38 import org.junit.rules.RunRules;
39 import org.junit.rules.TestRule;
40 import org.junit.runners.BlockJUnit4ClassRunner;
41 import org.junit.runners.model.FrameworkMethod;
42 import org.junit.runners.model.InitializationError;
43 import org.junit.runners.model.Statement;
44
45
46
47
48
49
50
51
52
53 public class BrowserVersionClassRunner extends BlockJUnit4ClassRunner {
54
55
56 public static final String[] NO_ALERTS_DEFINED = {"no alerts defined"};
57
58 private final BrowserVersion browserVersion_;
59 private final boolean realBrowser_;
60 static final boolean MAVEN = System.getProperty("htmlunit.maven") != null;
61
62
63
64
65
66
67
68
69 public BrowserVersionClassRunner(final Class<WebTestCase> klass,
70 final BrowserVersion browserVersion, final boolean realBrowser) throws InitializationError {
71 super(klass);
72 browserVersion_ = browserVersion;
73 realBrowser_ = realBrowser;
74 }
75
76 private void setAlerts(final WebTestCase testCase, final Method method) {
77 final Alerts alerts = method.getAnnotation(Alerts.class);
78 String[] expectedAlerts = {};
79 if (alerts != null) {
80 expectedAlerts = NO_ALERTS_DEFINED;
81 if (isDefined(alerts.value())) {
82 expectedAlerts = alerts.value();
83 }
84 else {
85 if (browserVersion_ == BrowserVersion.EDGE) {
86 expectedAlerts = firstDefined(alerts.EDGE(), alerts.DEFAULT());
87 }
88 else if (browserVersion_ == BrowserVersion.FIREFOX_ESR) {
89 expectedAlerts = firstDefined(alerts.FF_ESR(), alerts.DEFAULT());
90 }
91 else if (browserVersion_ == BrowserVersion.FIREFOX) {
92 expectedAlerts = firstDefined(alerts.FF(), alerts.DEFAULT());
93 }
94 else if (browserVersion_ == BrowserVersion.CHROME) {
95 expectedAlerts = firstDefined(alerts.CHROME(), alerts.DEFAULT());
96 }
97 }
98 }
99
100 if (isRealBrowser()) {
101 final BuggyWebDriver buggyWebDriver = method.getAnnotation(BuggyWebDriver.class);
102 if (buggyWebDriver != null) {
103 if (isDefined(buggyWebDriver.value())) {
104 expectedAlerts = buggyWebDriver.value();
105 }
106 else {
107 if (browserVersion_ == BrowserVersion.EDGE) {
108 expectedAlerts = firstDefinedOrGiven(expectedAlerts,
109 buggyWebDriver.EDGE(), buggyWebDriver.DEFAULT());
110 }
111 else if (browserVersion_ == BrowserVersion.FIREFOX_ESR) {
112 expectedAlerts = firstDefinedOrGiven(expectedAlerts,
113 buggyWebDriver.FF_ESR(), buggyWebDriver.DEFAULT());
114 }
115 else if (browserVersion_ == BrowserVersion.FIREFOX) {
116 expectedAlerts = firstDefinedOrGiven(expectedAlerts,
117 buggyWebDriver.FF(), buggyWebDriver.DEFAULT());
118 }
119 else if (browserVersion_ == BrowserVersion.CHROME) {
120 expectedAlerts = firstDefinedOrGiven(expectedAlerts,
121 buggyWebDriver.CHROME(), buggyWebDriver.DEFAULT());
122 }
123 }
124 }
125 }
126 else {
127 final HtmlUnitNYI htmlUnitNYI = method.getAnnotation(HtmlUnitNYI.class);
128 if (htmlUnitNYI != null) {
129 if (browserVersion_ == BrowserVersion.EDGE) {
130 expectedAlerts = firstDefinedOrGiven(expectedAlerts, htmlUnitNYI.EDGE());
131 }
132 else if (browserVersion_ == BrowserVersion.FIREFOX_ESR) {
133 expectedAlerts = firstDefinedOrGiven(expectedAlerts, htmlUnitNYI.FF_ESR());
134 }
135 else if (browserVersion_ == BrowserVersion.FIREFOX) {
136 expectedAlerts = firstDefinedOrGiven(expectedAlerts, htmlUnitNYI.FF());
137 }
138 else if (browserVersion_ == BrowserVersion.CHROME) {
139 expectedAlerts = firstDefinedOrGiven(expectedAlerts, htmlUnitNYI.CHROME());
140 }
141 }
142 }
143
144 testCase.setExpectedAlerts(expectedAlerts);
145 }
146
147 private static String[] firstDefined(final String[]... variants) {
148 for (final String[] var : variants) {
149 if (isDefined(var)) {
150 return var;
151 }
152 }
153 return NO_ALERTS_DEFINED;
154 }
155
156
157
158
159
160
161 public static String[] firstDefinedOrGiven(final String[] given, final String[]... variants) {
162 for (final String[] var : variants) {
163 if (isDefined(var)) {
164 try {
165 assertArrayEquals(var, given);
166 fail("BuggyWebDriver duplicates expectations");
167 }
168 catch (final AssertionError e) {
169
170 }
171 return var;
172 }
173 }
174 return given;
175 }
176
177
178
179
180 @Override
181 protected Object createTest() throws Exception {
182 final Object test = super.createTest();
183 assertTrue("Test class must inherit WebTestCase", test instanceof WebTestCase);
184 final WebTestCase object = (WebTestCase) test;
185 object.setBrowserVersion(browserVersion_);
186 if (test instanceof WebDriverTestCase) {
187 ((WebDriverTestCase) test).setUseRealBrowser(realBrowser_);
188 }
189 return object;
190 }
191
192 @Override
193 protected String getName() {
194 String browserString = browserVersion_.getNickname();
195 if (realBrowser_) {
196 browserString = "Real " + browserString;
197 }
198 return String.format("[%s]", browserString);
199 }
200
201 @Override
202 protected String testName(final FrameworkMethod method) {
203 String prefix = "";
204 if (isNotYetImplemented(method) && !realBrowser_) {
205 prefix = "(NYI) ";
206 }
207
208 String browserString = browserVersion_.getNickname();
209 if (realBrowser_) {
210 browserString = "Real " + browserString;
211 }
212 if (!MAVEN) {
213 return String.format("%s [%s]", method.getName(), browserString);
214 }
215 String className = method.getMethod().getDeclaringClass().getName();
216 className = className.substring(className.lastIndexOf('.') + 1);
217 return String.format("%s%s [%s]", prefix, className + '.' + method.getName(), browserString);
218 }
219
220
221
222
223
224
225
226 public static boolean containsTestMethods(final Class<WebTestCase> klass) {
227 for (final Method method : klass.getMethods()) {
228 if (method.getAnnotation(Test.class) != null) {
229 return true;
230 }
231 }
232 return false;
233 }
234
235
236
237
238
239 public static boolean isDefined(final String[] alerts) {
240 return alerts.length != 1 || !alerts[0].equals(BrowserRunner.EMPTY_DEFAULT);
241 }
242
243
244
245
246 private boolean isDefinedIn(final OS[] oses) {
247 for (final OS os : oses) {
248 switch (os) {
249 case Linux:
250 return SystemUtils.IS_OS_LINUX;
251 case Windows:
252 return SystemUtils.IS_OS_WINDOWS;
253 default:
254 break;
255 }
256 }
257 return false;
258 }
259
260
261
262
263 private boolean isDefinedIn(final TestedBrowser[] browsers) {
264 for (final TestedBrowser browser : browsers) {
265 switch (browser) {
266 case EDGE:
267 if (browserVersion_ == BrowserVersion.EDGE) {
268 return true;
269 }
270 break;
271
272 case FF_ESR:
273 if (browserVersion_ == BrowserVersion.FIREFOX_ESR) {
274 return true;
275 }
276 break;
277
278 case FF:
279 if (browserVersion_ == BrowserVersion.FIREFOX) {
280 return true;
281 }
282 break;
283
284 case CHROME:
285 if (browserVersion_ == BrowserVersion.CHROME) {
286 return true;
287 }
288 break;
289
290 default:
291 }
292 }
293 return false;
294 }
295
296 @Override
297 @SuppressWarnings("deprecation")
298 protected Statement methodBlock(final FrameworkMethod method) {
299 final Object test;
300 final WebTestCase testCase;
301 try {
302 testCase = (WebTestCase) createTest();
303 test = new ReflectiveCallable() {
304 @Override
305 protected Object runReflectiveCall() throws Throwable {
306 return testCase;
307 }
308 } .run();
309 }
310 catch (final Throwable e) {
311 return new Fail(e);
312 }
313
314 Statement statement = methodInvoker(method, test);
315 statement = possiblyExpectingExceptions(method, test, statement);
316 statement = withPotentialTimeout(method, test, statement);
317 statement = withBefores(method, test, statement);
318 statement = withAfters(method, test, statement);
319 statement = withRules(method, test, statement);
320 statement = withInterruptIsolation(statement);
321
322
323
324 boolean notYetImplemented = false;
325 final int tries;
326
327 if (testCase instanceof WebDriverTestCase && realBrowser_) {
328 tries = 1;
329 }
330 else {
331 notYetImplemented = isNotYetImplemented(method);
332 tries = getTries(method);
333 }
334 setAlerts(testCase, method.getMethod());
335 statement = new BrowserStatement(statement, method, realBrowser_,
336 notYetImplemented, tries, browserVersion_);
337 return statement;
338 }
339
340 private Statement withRules(final FrameworkMethod method, final Object target, final Statement statement) {
341 Statement result = statement;
342 result = withMethodRules(method, target, result);
343 result = withTestRules(method, target, result);
344 return result;
345 }
346
347 private Statement withMethodRules(final FrameworkMethod method, final Object target, Statement result) {
348 final List<TestRule> testRules = getTestRules(target);
349 for (final org.junit.rules.MethodRule each : getMethodRules(target)) {
350 if (!testRules.contains(each)) {
351 result = each.apply(result, method, target);
352 }
353 }
354 return result;
355 }
356
357 private List<org.junit.rules.MethodRule> getMethodRules(final Object target) {
358 return rules(target);
359 }
360
361
362
363
364
365
366
367 private Statement withTestRules(final FrameworkMethod method, final Object target, final Statement statement) {
368 final List<TestRule> testRules = getTestRules(target);
369 return testRules.isEmpty() ? statement : new RunRules(statement, testRules, describeChild(method));
370 }
371
372
373
374
375
376
377 protected boolean isNotYetImplemented(final FrameworkMethod method) {
378 final NotYetImplemented notYetImplementedBrowsers = method.getAnnotation(NotYetImplemented.class);
379 if (notYetImplementedBrowsers == null) {
380 return false;
381 }
382 return isDefinedIn(notYetImplementedBrowsers.value()) || isDefinedIn(notYetImplementedBrowsers.os());
383 }
384
385 private static int getTries(final FrameworkMethod method) {
386 final Tries tries = method.getAnnotation(Tries.class);
387 return tries != null ? tries.value() : 1;
388 }
389
390
391
392
393
394 protected BrowserVersion getBrowserVersion() {
395 return browserVersion_;
396 }
397
398
399
400
401
402 protected boolean isRealBrowser() {
403 return realBrowser_;
404 }
405 }