View Javadoc
1   /*
2    * Copyright (c) 2002-2025 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.junit;
16  
17  import java.lang.reflect.Method;
18  import java.util.Optional;
19  
20  import org.htmlunit.BrowserVersion;
21  import org.htmlunit.WebDriverTestCase;
22  import org.htmlunit.WebTestCase;
23  import org.htmlunit.junit.annotation.Alerts;
24  import org.htmlunit.junit.annotation.BuggyWebDriver;
25  import org.htmlunit.junit.annotation.HtmlUnitNYI;
26  import org.junit.jupiter.api.Assertions;
27  import org.junit.jupiter.api.extension.BeforeTestExecutionCallback;
28  import org.junit.jupiter.api.extension.ExtensionContext;
29  import org.junit.platform.commons.util.ReflectionUtils;
30  import org.opentest4j.AssertionFailedError;
31  
32  
33  /**
34   * BeforeTestExecutionCallback to set the {@code alerts} property.
35   *
36   * @author Ronald Brill
37   */
38  public class SetExpectedAlertsBeforeTestExecutionCallback implements BeforeTestExecutionCallback {
39  
40      /** If no alerts defined. */
41      public static final String[] NO_ALERTS_DEFINED = {"no alerts defined"};
42  
43      /**
44       * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK.</span><br>
45       */
46      public static final String EMPTY_DEFAULT = "~InTerNal_To_BrowSeRRunNer#@$";
47  
48      @Override
49      public void beforeTestExecution(final ExtensionContext context) throws Exception {
50          final Object testInstance = context.getRequiredTestInstance();
51  
52          if (testInstance instanceof WebTestCase) {
53              final WebTestCase webTestCase = (WebTestCase) testInstance;
54  
55              Method testMethod = context.getRequiredTestMethod();
56              final Optional<Method> potentialOberwrittenMethod =
57                      ReflectionUtils.findMethod(testInstance.getClass(), context.getDisplayName(), new Class[] {});
58              if (potentialOberwrittenMethod.isPresent()) {
59                  testMethod = potentialOberwrittenMethod.get();
60              }
61  
62              setAlerts(webTestCase, testMethod);
63          }
64      }
65  
66      private static void setAlerts(final WebTestCase webTestCase, final Method method) {
67          final Alerts alerts = method.getAnnotation(Alerts.class);
68          final BrowserVersion browserVersion = webTestCase.getBrowserVersion();
69  
70          String[] expectedAlerts = {};
71          if (alerts != null) {
72              expectedAlerts = NO_ALERTS_DEFINED;
73              if (isDefined(alerts.value())) {
74                  expectedAlerts = alerts.value();
75              }
76              else {
77                  if (browserVersion == BrowserVersion.EDGE) {
78                      expectedAlerts = firstDefined(alerts.EDGE(), alerts.DEFAULT());
79                  }
80                  else if (browserVersion == BrowserVersion.FIREFOX_ESR) {
81                      expectedAlerts = firstDefined(alerts.FF_ESR(), alerts.DEFAULT());
82                  }
83                  else if (browserVersion == BrowserVersion.FIREFOX) {
84                      expectedAlerts = firstDefined(alerts.FF(), alerts.DEFAULT());
85                  }
86                  else if (browserVersion == BrowserVersion.CHROME) {
87                      expectedAlerts = firstDefined(alerts.CHROME(), alerts.DEFAULT());
88                  }
89              }
90          }
91  
92          boolean realBrowser = false;
93          if (webTestCase instanceof WebDriverTestCase) {
94              realBrowser = ((WebDriverTestCase) webTestCase).useRealBrowser();
95          }
96          if (realBrowser) {
97              final BuggyWebDriver buggyWebDriver = method.getAnnotation(BuggyWebDriver.class);
98              if (buggyWebDriver != null) {
99                  if (isDefined(buggyWebDriver.value())) {
100                     expectedAlerts = buggyWebDriver.value();
101                 }
102                 else {
103                     if (browserVersion == BrowserVersion.EDGE) {
104                         expectedAlerts = firstDefinedOrGiven(expectedAlerts,
105                                             buggyWebDriver.EDGE(), buggyWebDriver.DEFAULT());
106                     }
107                     else if (browserVersion == BrowserVersion.FIREFOX_ESR) {
108                         expectedAlerts = firstDefinedOrGiven(expectedAlerts,
109                                             buggyWebDriver.FF_ESR(), buggyWebDriver.DEFAULT());
110                     }
111                     else if (browserVersion == BrowserVersion.FIREFOX) {
112                         expectedAlerts = firstDefinedOrGiven(expectedAlerts,
113                                             buggyWebDriver.FF(), buggyWebDriver.DEFAULT());
114                     }
115                     else if (browserVersion == BrowserVersion.CHROME) {
116                         expectedAlerts = firstDefinedOrGiven(expectedAlerts,
117                                             buggyWebDriver.CHROME(), buggyWebDriver.DEFAULT());
118                     }
119                 }
120             }
121         }
122         else {
123             final HtmlUnitNYI htmlUnitNYI = method.getAnnotation(HtmlUnitNYI.class);
124             if (htmlUnitNYI != null) {
125                 if (browserVersion == BrowserVersion.EDGE) {
126                     expectedAlerts = firstDefinedOrGiven(expectedAlerts, htmlUnitNYI.EDGE());
127                 }
128                 else if (browserVersion == BrowserVersion.FIREFOX_ESR) {
129                     expectedAlerts = firstDefinedOrGiven(expectedAlerts, htmlUnitNYI.FF_ESR());
130                 }
131                 else if (browserVersion == BrowserVersion.FIREFOX) {
132                     expectedAlerts = firstDefinedOrGiven(expectedAlerts, htmlUnitNYI.FF());
133                 }
134                 else if (browserVersion == BrowserVersion.CHROME) {
135                     expectedAlerts = firstDefinedOrGiven(expectedAlerts, htmlUnitNYI.CHROME());
136                 }
137             }
138         }
139 
140         webTestCase.setExpectedAlerts(expectedAlerts);
141     }
142 
143 
144     /**
145      * @param alerts the alerts to check
146      * @return true if there is exactly one alert defined
147      */
148     public static boolean isDefined(final String[] alerts) {
149         return alerts.length != 1 || !alerts[0].equals(EMPTY_DEFAULT);
150     }
151 
152     private static String[] firstDefined(final String[]... variants) {
153         for (final String[] var : variants) {
154             if (isDefined(var)) {
155                 return var;
156             }
157         }
158         return NO_ALERTS_DEFINED;
159     }
160 
161     /**
162      * @param given the default
163      * @param variants variants
164      * @return a string array containing the first defined value or the provided one
165      */
166     public static String[] firstDefinedOrGiven(final String[] given, final String[]... variants) {
167         for (final String[] var : variants) {
168             if (isDefined(var)) {
169                 try {
170                     Assertions.assertArrayEquals(var, given);
171                     Assertions.fail("BuggyWebDriver duplicates expectations");
172                 }
173                 catch (final AssertionFailedError e) {
174                     // ok
175                 }
176                 return var;
177             }
178         }
179         return given;
180     }
181 
182 }