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.general;
16  
17  import static org.htmlunit.BrowserVersionFeatures.JS_ERROR_STACK_TRACE_LIMIT;
18  
19  import java.util.ArrayList;
20  import java.util.Collection;
21  import java.util.Collections;
22  import java.util.Comparator;
23  import java.util.HashMap;
24  import java.util.List;
25  import java.util.Set;
26  
27  import org.htmlunit.TestCaseTest;
28  import org.htmlunit.WebDriverTestCase;
29  import org.htmlunit.javascript.configuration.ClassConfiguration;
30  import org.htmlunit.javascript.configuration.ClassConfiguration.ConstantInfo;
31  import org.htmlunit.javascript.configuration.JavaScriptConfiguration;
32  import org.junit.jupiter.params.ParameterizedTest;
33  import org.junit.jupiter.params.provider.Arguments;
34  import org.junit.jupiter.params.provider.MethodSource;
35  
36  /**
37   * Test all {@code constant}s defined in host classes.
38   *
39   * @author Ahmed Ashour
40   * @author Ronald Brill
41   */
42  public class HostConstantsTest extends WebDriverTestCase {
43  
44      /**
45       * Returns the parameterized data.
46       * @return the parameterized data
47       * @throws Exception if an error occurs
48       */
49      public static Collection<Arguments> data() throws Exception {
50          final List<Arguments> list = new ArrayList<>();
51          final Set<String> classNames = TestCaseTest.getAllConfiguredJsClassNames();
52          final ArrayList<String> classNamesSorted = new ArrayList<>(classNames);
53          Collections.sort(classNamesSorted);
54  
55          for (final String host : classNamesSorted) {
56              if (!"Audio".equals(host)) {
57                  list.add(Arguments.of(host));
58              }
59          }
60          return list;
61      }
62  
63      @ParameterizedTest
64      @MethodSource("data")
65      void test(final String host) throws Exception {
66          setExpectedAlerts(getExpectedString(host));
67  
68          final String html = DOCTYPE_HTML
69                  + "<html><head>\n"
70                  + "<script>\n"
71                  + LOG_TEXTAREA_FUNCTION
72                  + "function test() {\n"
73                  + "  try {\n"
74                  + "    var all = [];\n"
75                  + "    for (var x in " + host + ") {\n"
76                  + "      if (typeof " + host + "[x] == 'number') {\n"
77                  + "        all.push(x);\n"
78                  + "      }\n"
79                  + "    }\n"
80                  + "    all.sort();\n"
81  
82                  // uncomment to generate java code
83                  // + "    var helper = '';\n"
84                  // + "    for (var i in all) {\n"
85                  // + "      var x = all[i];\n"
86                  // + "      string += '\\r\\n    /** The constant {@code ' + x + '}. */\\r\\n';\n"
87                  //    + "      string += '    @JsxConstant\\r\\n';\n"
88                  //    + "      string += '    public static final long ' + x + ' = ' + " + host_ + "[x] + 'L;\\r\\n';\n"
89                  //    + "    }\n"
90                  //    + "    alert(string);\n"
91  
92                  + "    for (var i in all) {\n"
93                  + "      var x = all[i];\n"
94                  + "      log(x + ':' + " + host + "[x]);\n"
95                  + "    }\n"
96                  + "  } catch(e) {}\n"
97                  + "}\n"
98                  + "</script>\n"
99                  + "</head>\n"
100                 + "<body onload='test()'>\n"
101                 + LOG_TEXTAREA
102                 + "</body></html>";
103 
104         loadPageVerifyTextArea2(html);
105     }
106 
107     private String[] getExpectedString(final String host) throws Exception {
108         if (host.endsWith("Array") || "Image".equals(host) || "Option".equals(host)) {
109             return new String[0];
110         }
111         if ("Error".equals(host) && getBrowserVersion().hasFeature(JS_ERROR_STACK_TRACE_LIMIT)) {
112             return new String[] {"stackTraceLimit:10"};
113         }
114 
115         final JavaScriptConfiguration javaScriptConfig = JavaScriptConfiguration.getInstance(getBrowserVersion());
116         final HashMap<String, ClassConfiguration> classConfigurationIndex = new HashMap<>();
117         for (final ClassConfiguration config : javaScriptConfig.getAll()) {
118             classConfigurationIndex.put(config.getClassName(), config);
119         }
120 
121         final List<String> constants = new ArrayList<>();
122         ClassConfiguration classConfig = classConfigurationIndex.get(host);
123 
124         boolean first = true;
125         while (classConfig != null) {
126             if (first && !classConfig.isJsObject()) {
127                 break;
128             }
129             if (first || classConfig.getJsConstructor() != null) {
130                 final List<ConstantInfo> constantInfos = classConfig.getConstants();
131                 if (constantInfos != null) {
132                     for (final ConstantInfo constantInfo : constantInfos) {
133                         constants.add(constantInfo.getName() + ":" + constantInfo.getValue());
134                     }
135                 }
136             }
137             classConfig = classConfigurationIndex.get(classConfig.getExtendedClassName());
138             first = false;
139         }
140 
141         Collections.sort(constants, new Comparator<String>() {
142             @Override
143             public int compare(final String o1, final String o2) {
144                 return o1.substring(0, o1.indexOf(':')).compareTo(o2.substring(0, o2.indexOf(':')));
145             }
146         });
147         return constants.toArray(new String[0]);
148     }
149 
150     /**
151      * {@inheritDoc}
152      */
153     @Override
154     protected boolean isWebClientCached() {
155         return true;
156     }
157 }