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