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.htmlunit.junit.annotation.HtmlUnitNYI;
21  import org.junit.Test;
22  import org.junit.runner.RunWith;
23  import org.openqa.selenium.WebDriverException;
24  
25  /**
26   * Tests for Functions.
27   *
28   * @author Ronald Brill
29   */
30  @RunWith(BrowserRunner.class)
31  public class FunctionsTest extends WebDriverTestCase {
32  
33      /**
34       * @throws Exception if the test fails
35       */
36      @Test
37      @Alerts("function\\sfoo()\\s{\\s\\s\\s\\sreturn\\s\\t'a'\\s+\\s'b'\\s}")
38      public void function_toString() throws Exception {
39          final String html = DOCTYPE_HTML
40              + "<html><head>\n"
41              + "<script>\n"
42              + LOG_TITLE_FUNCTION_NORMALIZE
43              + "function test() {\n"
44              + "  function foo() {    return \t'a' + 'b' };\n"
45              + "  log(foo.toString());\n"
46              + "}\n"
47              + "</script></head>\n"
48              + "<body onload='test()'>\n"
49              + "</body></html>";
50  
51          loadPageVerifyTitle2(html);
52      }
53  
54      /**
55       * @throws Exception if the test fails
56       */
57      @Test
58      @Alerts("function\\sfoo()\\s\\n{\\s\\n\\sreturn\\s\\t'x'\\s\\n\\n}")
59      public void function_toStringNewLines() throws Exception {
60          final String html = DOCTYPE_HTML
61              + "<html><head>\n"
62              + "<script>\n"
63              + LOG_TITLE_FUNCTION_NORMALIZE
64              + "function test() {\n"
65              + "  function foo() \n{ \r\n return \t'x' \n\n};\n"
66              + "  log(foo.toString());\n"
67              + "}\n"
68              + "</script></head>\n"
69              + "<body onload='test()'>\n"
70              + "</body></html>";
71  
72          loadPageVerifyTitle2(html);
73      }
74  
75      /**
76       * @throws Exception if the test fails
77       */
78      @Test
79      @Alerts("()\\s=>\\s{\\s\\nreturn\\s\\s'=>'\\s\\s\\s}")
80      public void arrowFunction_toString() throws Exception {
81          final String html = DOCTYPE_HTML
82              + "<html><head>\n"
83              + "<script>\n"
84              + LOG_TITLE_FUNCTION_NORMALIZE
85              + "function test() {\n"
86              + "  var foo = () => { \nreturn  '=>'   };"
87              + "  log(foo.toString());\n"
88              + "}\n"
89              + "</script></head>\n"
90              + "<body onload='test()'>\n"
91              + "</body></html>";
92  
93          loadPageVerifyTitle2(html);
94      }
95  
96      /**
97       * @throws Exception if the test fails
98       */
99      @Test
100     @Alerts({"function()\\s{\\n\\s\\s\\s\\s\\s\\sreturn\\s'X';\\n\\s\\s\\s\\s}",
101              "function()\\s{\\n\\s\\s\\s\\s\\s\\sreturn\\s'X';\\n\\s\\s\\s\\s}"})
102     public void boundFunction_toString() throws Exception {
103         final String html = DOCTYPE_HTML
104             + "<html><head>\n"
105             + "<script>\n"
106             + LOG_TITLE_FUNCTION_NORMALIZE
107             + "function test() {\n"
108             + "  var oobj = {\n"
109             + "    getX: function() {\n"
110             + "      return 'X';\n"
111             + "    }\n"
112             + "  };\n"
113 
114             + "  log(oobj.getX.toString());\n"
115 
116             + "  var boundGetX = oobj.getX.bind(oobj);"
117             + "  log(oobj.getX.toString());\n"
118             + "}\n"
119             + "</script></head>\n"
120             + "<body onload='test()'>\n"
121             + "</body></html>";
122 
123         loadPageVerifyTitle2(html);
124     }
125 
126     /**
127      * @throws Exception if the test fails
128      */
129     @Test
130     @Alerts({"foo = undefined", "1"})
131     @HtmlUnitNYI(CHROME = "org.htmlunit.ScriptException: ReferenceError: \"foo\" is not defined.",
132             EDGE = "org.htmlunit.ScriptException: ReferenceError: \"foo\" is not defined.",
133             FF = "org.htmlunit.ScriptException: ReferenceError: \"foo\" is not defined.",
134             FF_ESR = "org.htmlunit.ScriptException: ReferenceError: \"foo\" is not defined.")
135     public void conditionallyCreatedFunction() throws Exception {
136         final String html = DOCTYPE_HTML
137             + "<html><head></head>\n"
138             + "<body>\n"
139             + "<script>\n"
140             + LOG_TITLE_FUNCTION
141             + "  log('foo = ' + foo);\n"
142             + "  if (true) {\n"
143             + "    log(foo());\n"
144             + "    function foo() { return 1; }\n"
145             + "  }\n"
146             + "</script>\n"
147             + "</body></html>";
148 
149         try {
150             loadPageVerifyTitle2(html);
151         }
152         catch (final WebDriverException e) {
153             assertTrue(e.getMessage(), e.getMessage().startsWith(getExpectedAlerts()[0]));
154         }
155     }
156 
157     /**
158      * @throws Exception if the test fails
159      */
160     @Test
161     @Alerts({"ReferenceError", "1"})
162     public void conditionallyCreatedFunctionStrict() throws Exception {
163         final String html = DOCTYPE_HTML
164             + "<html><head></head>\n"
165             + "<body>\n"
166             + "<script>\n"
167             + "  'use strict';\n"
168             + LOG_TITLE_FUNCTION
169             + "  try {\n"
170             + "    log('foo = ' + foo);\n"
171             + "  } catch(e) { logEx(e); }\n"
172             + "  if (true) {\n"
173             + "    log(foo());\n"
174             + "    function foo() { return 1; }\n"
175             + "  }\n"
176             + "</script>\n"
177             + "</body></html>";
178 
179         loadPageVerifyTitle2(html);
180     }
181 }