1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.javascript.regexp;
16
17 import org.htmlunit.WebDriverTestCase;
18 import org.htmlunit.junit.annotation.Alerts;
19 import org.htmlunit.junit.annotation.HtmlUnitNYI;
20 import org.junit.jupiter.api.Test;
21 import org.openqa.selenium.WebDriver;
22
23
24
25
26
27
28 public class RegExpTest extends WebDriverTestCase {
29
30
31
32
33 @Test
34 @Alerts({"g", "true", "false", "false", "false", "false"})
35 public void globalCtor() throws Exception {
36 testEvaluateProperties("new RegExp('foo', 'g');");
37 }
38
39
40
41
42 @Test
43 @Alerts({"g", "true", "false", "false", "false", "false"})
44 public void global() throws Exception {
45 testEvaluateProperties("/foo/g;");
46 }
47
48
49
50
51 @Test
52 @Alerts({"i", "false", "true", "false", "false", "false"})
53 public void ignoreCaseCtor() throws Exception {
54 testEvaluateProperties("new RegExp('foo', 'i');");
55 }
56
57
58
59
60 @Test
61 @Alerts({"i", "false", "true", "false", "false", "false"})
62 public void ignoreCase() throws Exception {
63 testEvaluateProperties("/foo/i;");
64 }
65
66
67
68
69 @Test
70 @Alerts({"m", "false", "false", "true", "false", "false"})
71 public void multilineCtor() throws Exception {
72 testEvaluateProperties("new RegExp('foo', 'm');");
73 }
74
75
76
77
78 @Test
79 @Alerts({"m", "false", "false", "true", "false", "false"})
80 public void multiline() throws Exception {
81 testEvaluateProperties("/foo/m;");
82 }
83
84
85
86
87 @Test
88 @Alerts({"y", "false", "false", "false", "true", "false"})
89 public void stickyCtor() throws Exception {
90 testEvaluateProperties("new RegExp('foo', 'y');");
91 }
92
93
94
95
96 @Test
97 @Alerts({"y", "false", "false", "false", "true", "false"})
98 public void sticky() throws Exception {
99 testEvaluateProperties("/foo/y;");
100 }
101
102
103
104
105 @Test
106 @Alerts({"gm", "true", "false", "true", "false", "false"})
107 public void globalMultilineCtor() throws Exception {
108 testEvaluateProperties("new RegExp('foo', 'gm');");
109 }
110
111
112
113
114 @Test
115 @Alerts({"gm", "true", "false", "true", "false", "false"})
116 public void globalMultiline() throws Exception {
117 testEvaluateProperties("/foo/gm;");
118 }
119
120
121
122
123 @Test
124 @Alerts({"gi", "true", "true", "false", "false", "false"})
125 public void globalIgnoreCaseCtor() throws Exception {
126 testEvaluateProperties("new RegExp('foo', 'ig');");
127 }
128
129
130
131
132 @Test
133 @Alerts({"gi", "true", "true", "false", "false", "false"})
134 public void globalIgnoreCase() throws Exception {
135 testEvaluateProperties("/foo/ig;");
136 }
137
138
139
140
141 @Test
142 @Alerts({"u", "false", "false", "false", "false", "true"})
143 public void unicodeCaseCtor() throws Exception {
144 testEvaluateProperties("new RegExp('foo', 'u');");
145 }
146
147
148
149
150 @Test
151 @Alerts({"u", "false", "false", "false", "false", "true"})
152 public void unicodeCase() throws Exception {
153 testEvaluateProperties("/foo/u;");
154 }
155
156
157
158
159 @Test
160 @Alerts({"mu", "false", "false", "true", "false", "true"})
161 public void multilineUnicodeCtor() throws Exception {
162 testEvaluateProperties("new RegExp('foo', 'mu');");
163 }
164
165
166
167
168 @Test
169 @Alerts({"mu", "false", "false", "true", "false", "true"})
170 public void multilineUnicode() throws Exception {
171 testEvaluateProperties("/foo/mu;");
172 }
173
174
175
176
177 @Test
178 @Alerts({"gy", "true", "false", "false", "true", "false"})
179 public void globalStickyCtor() throws Exception {
180 testEvaluateProperties("new RegExp('foo', 'gy');");
181 }
182
183
184
185
186 @Test
187 @Alerts({"gy", "true", "false", "false", "true", "false"})
188 public void globalSticky() throws Exception {
189 testEvaluateProperties("/foo/gy;");
190 }
191
192
193
194
195 @Test
196 @Alerts({"gim", "true", "true", "true", "false", "false"})
197 public void globalMultilineIgnoreCaseCtor() throws Exception {
198 testEvaluateProperties("new RegExp('foo', 'mig');");
199 }
200
201
202
203
204 @Test
205 @Alerts({"gim", "true", "true", "true", "false", "false"})
206 public void globalMultilineIgnoreCase() throws Exception {
207 testEvaluateProperties("/foo/gmi;");
208 }
209
210
211
212
213 @Test
214 @Alerts({"giy", "true", "true", "false", "true", "false"})
215 public void globalIgnoreCaseStickyCtor() throws Exception {
216 testEvaluateProperties("new RegExp('foo', 'yig');");
217 }
218
219
220
221
222 @Test
223 @Alerts({"giy", "true", "true", "false", "true", "false"})
224 public void globalIgnoreCaseSticky() throws Exception {
225 testEvaluateProperties("/foo/ygi;");
226 }
227
228
229
230
231 @Test
232 @Alerts({"gmy", "true", "false", "true", "true", "false"})
233 public void globalMultilineStickyCtor() throws Exception {
234 testEvaluateProperties("new RegExp('foo', 'gmy');");
235 }
236
237
238
239
240 @Test
241 @Alerts({"gmy", "true", "false", "true", "true", "false"})
242 public void globalMultilineSticky() throws Exception {
243 testEvaluateProperties("/foo/gmy;");
244 }
245
246
247
248
249 @Test
250 @Alerts({"im", "false", "true", "true", "false", "false"})
251 public void ignoreCaseMultilineCtor() throws Exception {
252 testEvaluateProperties("new RegExp('foo', 'im');");
253 }
254
255
256
257
258 @Test
259 @Alerts({"im", "false", "true", "true", "false", "false"})
260 public void ignoreCaseMultiline() throws Exception {
261 testEvaluateProperties("/foo/mi;");
262 }
263
264
265
266
267 @Test
268 @Alerts({"iy", "false", "true", "false", "true", "false"})
269 public void ignoreCaseStickyCtor() throws Exception {
270 testEvaluateProperties("new RegExp('foo', 'yi');");
271 }
272
273
274
275
276 @Test
277 @Alerts({"iy", "false", "true", "false", "true", "false"})
278 public void ignoreCaseSticky() throws Exception {
279 testEvaluateProperties("/foo/iy;");
280 }
281
282
283
284
285 @Test
286 @Alerts({"my", "false", "false", "true", "true", "false"})
287 public void multilineStickyCtor() throws Exception {
288 testEvaluateProperties("new RegExp('foo', 'my');");
289 }
290
291
292
293
294 @Test
295 @Alerts({"my", "false", "false", "true", "true", "false"})
296 public void multilineSticky() throws Exception {
297 testEvaluateProperties("/foo/my;");
298 }
299
300 private void testEvaluateProperties(final String script) throws Exception {
301 final String html =
302 "<html>\n"
303 + "<head>\n"
304 + "<script>\n"
305 + LOG_TEXTAREA_FUNCTION
306 + "function test() {\n"
307 + " var regex = " + script + "\n"
308 + " log(regex.flags);\n"
309 + " log(regex.global);\n"
310 + " log(regex.ignoreCase);\n"
311 + " log(regex.multiline);\n"
312 + " log(regex.sticky);\n"
313 + " log(regex.unicode);\n"
314 + "}\n"
315 + "</script>\n"
316 + "</head>\n"
317 + "<body onload='test()'>\n"
318 + LOG_TEXTAREA
319 + "</body></html>";
320
321 loadPageVerifyTextArea2(html);
322 }
323
324
325
326
327 @Test
328 @Alerts("false")
329 public void stickyStartOfLine() throws Exception {
330 final String script =
331 "var regex = /^foo/y;\n"
332 + "regex.lastIndex = 2;\n"
333 + "log(regex.test('..foo'));";
334 testEvaluate(script);
335 }
336
337
338
339
340 @Test
341 @Alerts({"false", "true"})
342 public void stickyStartOfLineMultiline() throws Exception {
343 final String script =
344 "var regex = /^foo/my;\n"
345 + "regex.lastIndex = 2;\n"
346 + "log(regex.test('..foo'))\n"
347 + "regex.lastIndex = 2;\n"
348 + "log(regex.test('.\\nfoo'));";
349 testEvaluate(script);
350 }
351
352
353
354
355 @Test
356 @Alerts({"2", "a", "a"})
357 public void stickyAndGlobal() throws Exception {
358 final String script =
359 "var result = 'aaba'.match(/a/yg);\n"
360 + "log(result.length);\n"
361 + "log(result[0]);\n"
362 + "log(result[1]);\n";
363 testEvaluate(script);
364 }
365
366
367
368
369 @Test
370 @Alerts({"1", "a\na"})
371 public void dotAll() throws Exception {
372 final String script =
373 "var result = 'a\\naba'.match(/a.a/s);\n"
374 + "log(result.length);\n"
375 + "log(result[0]);\n";
376 testEvaluate(script);
377 }
378
379
380
381
382 @Test
383 @Alerts({"1", "a\na"})
384 public void dotAllAndGlobal() throws Exception {
385 final String script =
386 "var result = 'a\\naba'.match(/a.a/sg);\n"
387 + "log(result.length);\n"
388 + "log(result[0]);\n";
389 testEvaluate(script);
390 }
391
392
393
394
395 @Test
396 @Alerts({"2", "3f", "3f"})
397 public void unicode() throws Exception {
398 final String script =
399 "var result = 'Angle α measures π radians.'.match(/[Α-Ωα-ω]/g);\n"
400 + "log(result.length);\n"
401 + "log(result[0].charCodeAt(0).toString(16));\n"
402 + "log(result[1].charCodeAt(0).toString(16));";
403 testEvaluate(script);
404 }
405
406
407
408
409 @Test
410 @Alerts({"0", "undefined", "true", "false", "undefined"})
411 @HtmlUnitNYI(CHROME = {"get undefined", "", "false", "false", "false"},
412 EDGE = {"get undefined", "", "false", "false", "false"},
413 FF = {"get undefined", "", "false", "false", "false"},
414 FF_ESR = {"get undefined", "", "false", "false", "false"})
415 public void flagsProperty() throws Exception {
416 testProperty("flags");
417 }
418
419
420
421
422 @Test
423 @Alerts({"0", "undefined", "true", "false", "undefined"})
424 @HtmlUnitNYI(CHROME = {"get undefined", "false", "false", "false", "false"},
425 EDGE = {"get undefined", "false", "false", "false", "false"},
426 FF = {"get undefined", "false", "false", "false", "false"},
427 FF_ESR = {"get undefined", "false", "false", "false", "false"})
428 public void globalProperty() throws Exception {
429 testProperty("global");
430 }
431
432
433
434
435 @Test
436 @Alerts({"0", "undefined", "true", "false", "undefined"})
437 @HtmlUnitNYI(CHROME = {"get undefined", "false", "false", "false", "false"},
438 EDGE = {"get undefined", "false", "false", "false", "false"},
439 FF = {"get undefined", "false", "false", "false", "false"},
440 FF_ESR = {"get undefined", "false", "false", "false", "false"})
441 public void ignoreCaseProperty() throws Exception {
442 testProperty("ignoreCase");
443 }
444
445
446
447
448 @Test
449 @Alerts({"0", "undefined", "true", "false", "undefined"})
450 @HtmlUnitNYI(CHROME = {"get undefined", "false", "false", "false", "false"},
451 EDGE = {"get undefined", "false", "false", "false", "false"},
452 FF = {"get undefined", "false", "false", "false", "false"},
453 FF_ESR = {"get undefined", "false", "false", "false", "false"})
454 public void multilineProperty() throws Exception {
455 testProperty("multiline");
456 }
457
458
459
460
461 @Test
462 @Alerts({"0", "undefined", "true", "false", "undefined"})
463 @HtmlUnitNYI(CHROME = {"get undefined", "false", "false", "false", "false"},
464 EDGE = {"get undefined", "false", "false", "false", "false"},
465 FF = {"get undefined", "false", "false", "false", "false"},
466 FF_ESR = {"get undefined", "false", "false", "false", "false"})
467 public void stickyProperty() throws Exception {
468 testProperty("sticky");
469 }
470
471
472
473
474 @Test
475 @Alerts({"0", "undefined", "true", "false", "undefined"})
476 @HtmlUnitNYI(CHROME = {"get undefined", "false", "false", "false", "false"},
477 EDGE = {"get undefined", "false", "false", "false", "false"},
478 FF = {"get undefined", "false", "false", "false", "false"},
479 FF_ESR = {"get undefined", "false", "false", "false", "false"})
480 public void dotAllProperty() throws Exception {
481 testProperty("dotAll");
482 }
483
484
485
486
487
488 @Test
489 @Alerts({"0", "undefined", "true", "false", "undefined"})
490 @HtmlUnitNYI(CHROME = {"get undefined", "false", "false", "false", "false"},
491 EDGE = {"get undefined", "false", "false", "false", "false"},
492 FF = {"get undefined", "false", "false", "false", "false"},
493 FF_ESR = {"get undefined", "false", "false", "false", "false"})
494 public void unicodeProperty() throws Exception {
495 testProperty("unicode");
496 }
497
498
499
500
501
502 @Test
503 @Alerts({"0", "undefined", "true", "false", "undefined"})
504 @HtmlUnitNYI(CHROME = {"get undefined", "", "false", "false", "false"},
505 EDGE = {"get undefined", "", "false", "false", "false"},
506 FF = {"get undefined", "", "false", "false", "false"},
507 FF_ESR = {"get undefined", "", "false", "false", "false"})
508 public void sourceProperty() throws Exception {
509 testProperty("source");
510 }
511
512 private void testProperty(final String property) throws Exception {
513 final String script =
514 "var get = Object.getOwnPropertyDescriptor(RegExp.prototype, '" + property + "');\n"
515 + "log(get.get == undefined ? 'get undefined' : get.get.length);\n"
516 + "log(get.value);\n"
517 + "log(get.configurable);\n"
518 + "log(get.enumerable);\n"
519 + "log(get.writable);\n";
520
521 testEvaluate(script);
522 }
523
524
525
526
527 @Test
528 public void stringReplace() throws Exception {
529 testEvaluate("xyz", "''.replace('', 'xyz')");
530 testEvaluate("1", "'121'.replace('21', '')");
531 testEvaluate("xyz121", "'121'.replace('', 'xyz')");
532 testEvaluate("a$c21", "'121'.replace('1', 'a$c')");
533 testEvaluate("a121", "'121'.replace('1', 'a$&')");
534 testEvaluate("a$c21", "'121'.replace('1', 'a$$c')");
535 testEvaluate("abaabe", "'abcde'.replace('cd', 'a$`')");
536 testEvaluate("a21", "'121'.replace('1', 'a$`')");
537 testEvaluate("abaee", "'abcde'.replace('cd', \"a$'\")");
538 testEvaluate("aba", "'abcd'.replace('cd', \"a$'\")");
539 testEvaluate("aba$0", "'abcd'.replace('cd', 'a$0')");
540 testEvaluate("aba$1", "'abcd'.replace('cd', 'a$1')");
541 testEvaluate("abCD", "'abcd'.replace('cd', function (matched) { return matched.toUpperCase() })");
542 testEvaluate("", "'123456'.replace(/\\d+/, '')");
543 testEvaluate("123ABCD321abcd",
544 "'123abcd321abcd'.replace(/[a-z]+/, function (matched) { return matched.toUpperCase() })");
545 }
546
547
548
549
550 @Test
551 public void stringReplaceAll() throws Exception {
552 testEvaluate("xyz", "''.replaceAll('', 'xyz')");
553 testEvaluate("1", "'12121'.replaceAll('21', '')");
554 testEvaluate("xyz1xyz2xyz1xyz", "'121'.replaceAll('', 'xyz')");
555 testEvaluate("a$c2a$c", "'121'.replaceAll('1', 'a$c')");
556 testEvaluate("a12a1", "'121'.replaceAll('1', 'a$&')");
557 testEvaluate("a$c2a$c", "'121'.replaceAll('1', 'a$$c')");
558 testEvaluate("aaadaaabcda", "'abcdabc'.replaceAll('bc', 'a$`')");
559 testEvaluate("a2a12", "'121'.replaceAll('1', 'a$`')");
560 testEvaluate("aadabcdaa", "'abcdabc'.replaceAll('bc', \"a$'\")");
561 testEvaluate("aadabcdaa", "'abcdabc'.replaceAll('bc', \"a$'\")");
562 testEvaluate("aa$0daa$0", "'abcdabc'.replaceAll('bc', 'a$0')");
563 testEvaluate("aa$1daa$1", "'abcdabc'.replaceAll('bc', 'a$1')");
564 testEvaluate("", "'123456'.replaceAll(/\\d+/g, '')");
565 testEvaluate("123456", "'123456'.replaceAll(undefined, '')");
566 testEvaluate("afoobarb", "'afoob'.replaceAll(/(foo)/g, '$1bar')");
567 testEvaluate("foobarb", "'foob'.replaceAll(/(foo)/gy, '$1bar')");
568 testEvaluate("hllo", "'hello'.replaceAll(/(h)e/gy, '$1')");
569 testEvaluate("$1llo", "'hello'.replaceAll(/he/g, '$1')");
570 testEvaluate("I$want$these$periods$to$be$$s", "'I.want.these.periods.to.be.$s'.replaceAll(/\\./g, '$')");
571 testEvaluate("food bar", "'foo bar'.replaceAll(/foo/g, '$&d')");
572 testEvaluate("foo foo ", "'foo bar'.replaceAll(/bar/g, '$`')");
573 testEvaluate(" bar bar", "'foo bar'.replaceAll(/foo/g, '$\\'')");
574 testEvaluate("$' bar", "'foo bar'.replaceAll(/foo/g, '$$\\'')");
575 testEvaluate("123FOOBAR321BARFOO123",
576 "'123foobar321barfoo123'.replace(/[a-z]+/g, function (matched) { return matched.toUpperCase() })");
577
578 testEvaluate(
579 "TypeError: replaceAll must be called with a global RegExp",
580 "'hello'.replaceAll(/he/i, 'x')");
581 }
582
583
584
585
586 @Test
587 @Alerts({"ad$0db", "ad$0db", "ad$0dbd$0dc"})
588 public void stringReplaceAllBrowserSpecific() throws Exception {
589 testEvaluate(getExpectedAlerts()[0], "'afoob'.replaceAll(/(foo)/g, 'd$0d')");
590 testEvaluate(getExpectedAlerts()[1], "'afkxxxkob'.replace(/(f)k(.*)k(o)/g, 'd$0d')");
591 testEvaluate(getExpectedAlerts()[2], "'afoobfuoc'.replaceAll(/(f.o)/g, 'd$0d')");
592 }
593
594 private void testEvaluate(final String expected, final String script) throws Exception {
595 final String html =
596 "<html>\n"
597 + "<head>\n"
598 + "<script>\n"
599 + LOG_TEXTAREA_FUNCTION
600 + "function test() {\n"
601 + " try {\n"
602 + " log(" + script + ");\n"
603 + " } catch(e) { log(e); }\n"
604 + "}\n"
605 + "</script>\n"
606 + "</head>\n"
607 + "<body onload='test()'>\n"
608 + LOG_TEXTAREA
609 + "</body></html>";
610
611 final WebDriver driver = loadPage2(html);
612 verifyTextArea2(driver, expected);
613 }
614
615 private void testEvaluate(final String script) throws Exception {
616 final String html =
617 "<html>\n"
618 + "<head>\n"
619 + "<script>\n"
620 + LOG_TEXTAREA_FUNCTION
621 + "function test() {\n"
622 + script
623 + "}\n"
624 + "</script>\n"
625 + "</head>\n"
626 + "<body onload='test()'>\n"
627 + LOG_TEXTAREA
628 + "</body></html>";
629
630 loadPageVerifyTextArea2(html);
631 }
632 }