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.javascript;
16  
17  import org.htmlunit.WebDriverTestCase;
18  import org.htmlunit.junit.annotation.Alerts;
19  import org.junit.jupiter.api.Test;
20  
21  /**
22   * String is a native JavaScript object and therefore provided by Rhino but some tests are needed here.
23   *
24   * @author Marc Guillemot
25   * @author Ahmed Ashour
26   * @author Frank Danek
27   * @author Ronald Brill
28   */
29  public class NativeStringTest extends WebDriverTestCase {
30  
31      /**
32       * Test for bug <a href="http://sourceforge.net/support/tracker.php?aid=2783950">2783950</a>.
33       * @throws Exception if the test fails
34       */
35      @Test
36      @Alerts("key\\:b_M")
37      public void replace() throws Exception {
38          final String html = DOCTYPE_HTML
39              + "<html><head><script>\n"
40              + LOG_TITLE_FUNCTION
41              + "function doTest() {\n"
42              + "  log('key:b_M'.replace(':', '\\\\:'));\n"
43              + "}\n"
44              + "</script></head><body onload='doTest()'>\n"
45              + "</body></html>";
46  
47          loadPageVerifyTitle2(html);
48      }
49  
50      /**
51       * Test for the methods with the same expectations for all browsers.
52       * @throws Exception if the test fails
53       */
54      @Test
55      @Alerts({"anchor: function", "big: function", "blink: function", "bold: function", "charAt: function",
56               "charCodeAt: function", "concat: function", "constructor: function", "equals: undefined",
57               "equalsIgnoreCase: undefined", "fixed: function", "fontcolor: function", "fontsize: function",
58               "fromCharCode: undefined", "indexOf: function", "italics: function", "lastIndexOf: function",
59               "link: function", "localeCompare: function", "match: function", "replace: function", "search: function",
60               "slice: function", "small: function", "split: function", "strike: function", "sub: function",
61               "substr: function", "substring: function", "sup: function", "toLocaleLowerCase: function",
62               "toLocaleUpperCase: function", "toLowerCase: function", "toString: function", "toUpperCase: function",
63               "valueOf: function"})
64      public void methods_common() throws Exception {
65          final String[] methods = {
66              "anchor", "big", "blink", "bold", "charAt", "charCodeAt", "concat", "constructor",
67              "equals", "equalsIgnoreCase", "fixed", "fontcolor", "fontsize", "fromCharCode", "indexOf", "italics",
68              "lastIndexOf", "link", "localeCompare", "match", "replace", "search", "slice", "small", "split",
69              "strike", "sub", "substr", "substring", "sup", "toLocaleLowerCase", "toLocaleUpperCase", "toLowerCase",
70              "toString", "toUpperCase", "valueOf"};
71          final String html = NativeDateTest.createHTMLTestMethods("'hello'", methods);
72          loadPageVerifyTitle2(html);
73      }
74  
75      /**
76       * Test for the methods with different expectations depending on the browsers.
77       * Function contains is introduced in FF18.
78       * @throws Exception if the test fails
79       */
80      @Test
81      @Alerts({"contains: undefined", "toSource: undefined", "trim: function"})
82      public void methods_differences() throws Exception {
83          final String[] methods = {"contains", "toSource", "trim" };
84          final String html = NativeDateTest.createHTMLTestMethods("'hello'", methods);
85          loadPageVerifyTitle2(html);
86      }
87  
88      /**
89       * @throws Exception if the test fails
90       */
91      @Test
92      @Alerts("2")
93      public void trim() throws Exception {
94          final String html = DOCTYPE_HTML
95              + "<html><head><script>\n"
96              + LOG_TITLE_FUNCTION
97              + "function doTest() {\n"
98              + "  var string = ' hi  ';\n"
99              + "  if (''.trim) {\n"
100             + "    log(string.trim().length);\n"
101             + "  }\n"
102             + "}\n"
103             + "</script></head><body onload='doTest()'>\n"
104             + "</body></html>";
105 
106         loadPageVerifyTitle2(html);
107     }
108 
109     /**
110      * @throws Exception if the test fails
111      */
112     @Test
113     @Alerts("3")
114     public void trimRight() throws Exception {
115         final String html = DOCTYPE_HTML
116             + "<html><head><script>\n"
117             + LOG_TITLE_FUNCTION
118             + "function doTest() {\n"
119             + "  var string = ' hi  ';\n"
120             + "  if (''.trimRight) {\n"
121             + "    log(string.trimRight().length);\n"
122             + "  }\n"
123             + "}\n"
124             + "</script></head><body onload='doTest()'>\n"
125             + "</body></html>";
126 
127         loadPageVerifyTitle2(html);
128     }
129 
130     /**
131      * @throws Exception if the test fails
132      */
133     @Test
134     @Alerts("4")
135     public void trimLeft() throws Exception {
136         final String html = DOCTYPE_HTML
137             + "<html><head><script>\n"
138             + LOG_TITLE_FUNCTION
139             + "function doTest() {\n"
140             + "  var string = ' hi  ';\n"
141             + "  if (''.trimLeft) {\n"
142             + "    log(string.trimLeft().length);\n"
143             + "  }\n"
144             + "}\n"
145             + "</script></head><body onload='doTest()'>\n"
146             + "</body></html>";
147 
148         loadPageVerifyTitle2(html);
149     }
150 
151     /**
152      * @throws Exception if the test fails
153      */
154     @Test
155     @Alerts("contains not supported")
156     public void contains() throws Exception {
157         final String html = DOCTYPE_HTML
158             + "<html><head><script>\n"
159             + LOG_TITLE_FUNCTION
160             + "function doTest() {\n"
161             + "  if ('contains' in String.prototype) {\n"
162             + "    var str = 'To be, or not to be, that is the question.';\n"
163             + "    log(str.contains('To be'));\n"
164             + "    log(str.contains('TO'));\n"
165             + "    log(str.contains(''));\n"
166             + "    log(str.contains(' '));\n"
167             + "    log(str.contains('To be', 0));\n"
168             + "    log(str.contains('TO', 0));\n"
169             + "    log(str.contains(' ', 0));\n"
170             + "    log(str.contains('', 0));\n"
171             + "    log(str.contains('or', 7));\n"
172             + "    log(str.contains('or', 8));\n"
173 
174             + "    log(str.contains('or', -3));\n"
175             + "    log(str.contains('or', 7.9));\n"
176             + "    log(str.contains('or', 8.1));\n"
177             + "    log(str.contains());\n"
178             + "  } else {\n"
179             + "    log('contains not supported');\n"
180             + "  }\n"
181             + "}\n"
182             + "</script></head><body onload='doTest()'>\n"
183             + "</body></html>";
184 
185         loadPageVerifyTitle2(html);
186     }
187 
188     /**
189      * @throws Exception if the test fails
190      */
191     @Test
192     @Alerts({"true", "true", "true", "false"})
193     public void startsWith() throws Exception {
194         final String html = DOCTYPE_HTML
195             + "<html><head><script>\n"
196             + LOG_TITLE_FUNCTION
197             + "function doTest() {\n"
198             + "  if ('startsWith' in String.prototype) {\n"
199             + "    var str = 'To be, or not to be, that is the question.';\n"
200             + "    log(str.startsWith('To be'));\n"
201             + "    log(str.startsWith('T'));\n"
202             + "    log(str.startsWith(str));\n"
203 
204             + "    log(str.startsWith('question.'));\n"
205             + "  } else {\n"
206             + "    log('startsWith not supported');\n"
207             + "  }\n"
208             + "}\n"
209             + "</script></head><body onload='doTest()'>\n"
210             + "</body></html>";
211 
212         loadPageVerifyTitle2(html);
213     }
214 
215     /**
216      * @throws Exception if the test fails
217      */
218     @Test
219     @Alerts({"true", "true", "true", "false"})
220     public void endsWith() throws Exception {
221         final String html = DOCTYPE_HTML
222             + "<html><head><script>\n"
223             + LOG_TITLE_FUNCTION
224             + "function doTest() {\n"
225             + "  if ('endsWith' in String.prototype) {\n"
226             + "    var str = 'To be, or not to be, that is the question.';\n"
227             + "    log(str.endsWith('question.'));\n"
228             + "    log(str.endsWith('.'));\n"
229             + "    log(str.endsWith(str));\n"
230 
231             + "    log(str.endsWith('the'));\n"
232             + "  } else {\n"
233             + "    log('endsWith not supported');\n"
234             + "  }\n"
235             + "}\n"
236             + "</script></head><body onload='doTest()'>\n"
237             + "</body></html>";
238 
239         loadPageVerifyTitle2(html);
240     }
241 
242     /**
243      * @throws Exception if the test fails
244      */
245     @Test
246     @Alerts({"true", "true", "true", "true", "false"})
247     public void includes() throws Exception {
248         final String html = DOCTYPE_HTML
249             + "<html><head><script>\n"
250             + LOG_TITLE_FUNCTION
251             + "function doTest() {\n"
252             + "  if ('includes' in String.prototype) {\n"
253             + "    var str = 'To be, or not to be, that is the question.';\n"
254             + "    log(str.includes('to be'));\n"
255             + "    log(str.includes('question.'));\n"
256             + "    log(str.includes('To be'));\n"
257             + "    log(str.includes(str));\n"
258 
259             + "    log(str.includes('test'));\n"
260             + "  } else {\n"
261             + "    log('includes not supported');\n"
262             + "  }\n"
263             + "}\n"
264             + "</script></head><body onload='doTest()'>\n"
265             + "</body></html>";
266 
267         loadPageVerifyTitle2(html);
268     }
269 
270     /**
271      * @throws Exception if the test fails
272      */
273     @Test
274     @Alerts({"", "abc", "abcabc"})
275     public void repeat() throws Exception {
276         final String html = DOCTYPE_HTML
277             + "<html><head><script>\n"
278             + LOG_TITLE_FUNCTION
279             + "function doTest() {\n"
280             + "  if ('repeat' in String.prototype) {\n"
281             + "    var str = 'abc';\n"
282             + "    log(str.repeat(0));\n"
283             + "    log(str.repeat(1));\n"
284             + "    log(str.repeat(2));\n"
285             + "  } else {\n"
286             + "    log('repeat not supported');\n"
287             + "  }\n"
288             + "}\n"
289             + "</script></head><body onload='doTest()'>\n"
290             + "</body></html>";
291 
292         loadPageVerifyTitle2(html);
293     }
294 
295     /**
296      * @throws Exception if something goes wrong
297      */
298     @Test
299     @Alerts({"\u0069\u0307", "\u0069"})
300     public void toLocaleLowerCase() throws Exception {
301         final String html = DOCTYPE_HTML
302             + "<html><head><script>\n"
303             + LOG_TITLE_FUNCTION
304             + "  function doTest() {\n"
305             + "    log('\\u0130'.toLocaleLowerCase('en'));\n"
306             + "    log('\\u0130'.toLocaleLowerCase('tr'));\n"
307             + "  }\n"
308             + "</script></head>"
309             + "<body onload='doTest()'>\n"
310             + "</body></html>";
311 
312         loadPageVerifyTitle2(html);
313     }
314 
315     /**
316      * @throws Exception if something goes wrong
317      */
318     @Test
319     @Alerts({"Error", "true"})
320     public void includesRegExpMatch() throws Exception {
321         final String html = DOCTYPE_HTML
322             + "<html><head><script>\n"
323             + LOG_TITLE_FUNCTION
324             + "  function doTest() {\n"
325             + "    if (window.Symbol) {\n"
326             + "      var regExp = /./;\n"
327             + "      var res = '';\n"
328             + "      try {\n"
329             + "        log('/./'.includes(regExp));\n"
330             + "      } catch(e) {\n"
331             + "        log('Error');\n"
332             + "      }\n"
333             + "      regExp[Symbol.match] = false;\n"
334             + "      log('/./'.includes(regExp));\n"
335             + "    }\n"
336             + "  }\n"
337             + "</script></head>"
338             + "<body onload='doTest()'>\n"
339             + "</body></html>";
340 
341         loadPageVerifyTitle2(html);
342     }
343 
344     /**
345      * @throws Exception if something goes wrong
346      */
347     @Test
348     @Alerts({"TypeError", "true"})
349     public void startsWithRegExpMatch() throws Exception {
350         final String html = DOCTYPE_HTML
351             + "<html><head><script>\n"
352             + LOG_TITLE_FUNCTION
353             + "  function doTest() {\n"
354             + "    if (window.Symbol) {\n"
355             + "      var regExp = /./;\n"
356             + "      var res = '';\n"
357             + "      try {\n"
358             + "        log('/./'.startsWith(regExp));\n"
359             + "      } catch(e) { logEx(e); }\n"
360             + "      regExp[Symbol.match] = false;\n"
361             + "      log('/./'.startsWith(regExp));\n"
362             + "    }\n"
363             + "  }\n"
364             + "</script></head>"
365             + "<body onload='doTest()'>\n"
366             + "</body></html>";
367 
368         loadPageVerifyTitle2(html);
369     }
370 
371     /**
372      * @throws Exception if something goes wrong
373      */
374     @Test
375     @Alerts({"TypeError", "true"})
376     public void endsWithRegExpMatch() throws Exception {
377         final String html = DOCTYPE_HTML
378             + "<html><head><script>\n"
379             + LOG_TITLE_FUNCTION
380             + "  function doTest() {\n"
381             + "    if (window.Symbol) {\n"
382             + "      var regExp = /./;\n"
383             + "      var res = '';\n"
384             + "      try {\n"
385             + "        log('/./'.endsWith(regExp));\n"
386             + "      } catch(e) { logEx(e); }\n"
387             + "      regExp[Symbol.match] = false;\n"
388             + "      log('/./'.endsWith(regExp));\n"
389             + "    }\n"
390             + "  }\n"
391             + "</script></head>"
392             + "<body onload='doTest()'>\n"
393             + "</body></html>";
394 
395         loadPageVerifyTitle2(html);
396     }
397 }