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