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.host.worker;
16  
17  import java.net.URL;
18  
19  import org.htmlunit.WebDriverTestCase;
20  import org.htmlunit.junit.BrowserRunner;
21  import org.htmlunit.junit.annotation.Alerts;
22  import org.htmlunit.util.MimeType;
23  import org.junit.Test;
24  import org.junit.runner.RunWith;
25  
26  /**
27   * Unit tests for {@code DedicatedWorkerGlobalScope}.
28   *
29   * @author Ronald Brill
30   * @author Rural Hunter
31   */
32  @RunWith(BrowserRunner.class)
33  public class DedicatedWorkerGlobalScopeTest extends WebDriverTestCase {
34  
35      /**
36       * @throws Exception if the test fails
37       */
38      @Test
39      @Alerts("Received: Result = 15")
40      public void onmessage() throws Exception {
41          final String html = DOCTYPE_HTML
42              + "<html><body>"
43              + "<script>\n"
44              + LOG_TITLE_FUNCTION
45              + "try {\n"
46              + "  var myWorker = new Worker('worker.js');\n"
47              + "  myWorker.onmessage = function(e) {\n"
48              + "    log('Received: ' + e.data);\n"
49              + "  };\n"
50              + "  setTimeout(function() { myWorker.postMessage([5, 3]);}, 10);\n"
51              + "} catch(e) { logEx(e); }\n"
52              + "</script></body></html>\n";
53  
54          final String workerJs = "onmessage = function(e) {\n"
55                  + "  var workerResult = 'Result = ' + (e.data[0] * e.data[1]);\n"
56                  + "  postMessage(workerResult);\n"
57                  + "}\n";
58  
59          getMockWebConnection().setResponse(new URL(URL_FIRST, "worker.js"), workerJs, MimeType.TEXT_JAVASCRIPT);
60  
61          loadPage2(html);
62          verifyTitle2(DEFAULT_WAIT_TIME, getWebDriver(), getExpectedAlerts());
63      }
64  
65      /**
66       * @throws Exception if the test fails
67       */
68      @Test
69      @Alerts("Received: Result = 15")
70      public void selfOnmessage() throws Exception {
71          final String html = DOCTYPE_HTML
72              + "<html><body><script>\n"
73              + LOG_TITLE_FUNCTION
74              + "try {\n"
75              + "  var myWorker = new Worker('worker.js');\n"
76              + "  myWorker.onmessage = function(e) {\n"
77              + "    log('Received: ' + e.data);\n"
78              + "  };\n"
79              + "  setTimeout(function() { myWorker.postMessage([5, 3]);}, 10);\n"
80              + "} catch(e) { logEx(e); }\n"
81              + "</script></body></html>\n";
82  
83          final String workerJs = "self.onmessage = function(e) {\n"
84                  + "  var workerResult = 'Result = ' + (e.data[0] * e.data[1]);\n"
85                  + "  postMessage(workerResult);\n"
86                  + "}\n";
87  
88          getMockWebConnection().setResponse(new URL(URL_FIRST, "worker.js"), workerJs, MimeType.TEXT_JAVASCRIPT);
89  
90          loadPage2(html);
91          verifyTitle2(DEFAULT_WAIT_TIME, getWebDriver(), getExpectedAlerts());
92      }
93  
94      /**
95       * @throws Exception if the test fails
96       */
97      @Test
98      @Alerts("Received: Result = 15")
99      public void selfAddEventListener() throws Exception {
100         final String html = DOCTYPE_HTML
101             + "<html><body><script>\n"
102             + LOG_TITLE_FUNCTION
103             + "try {\n"
104             + "  var myWorker = new Worker('worker.js');\n"
105             + "  myWorker.onmessage = function(e) {\n"
106             + "    log('Received: ' + e.data);\n"
107             + "  };\n"
108             + "  setTimeout(function() { myWorker.postMessage([5, 3]);}, 10);\n"
109             + "} catch(e) { logEx(e); }\n"
110             + "</script></body></html>\n";
111 
112         final String workerJs = "self.addEventListener('message', (e) => {\n"
113                 + "  var workerResult = 'Result = ' + (e.data[0] * e.data[1]);\n"
114                 + "  postMessage(workerResult);\n"
115                 + "});\n";
116 
117         getMockWebConnection().setResponse(new URL(URL_FIRST, "worker.js"), workerJs, MimeType.TEXT_JAVASCRIPT);
118 
119         loadPage2(html);
120         verifyTitle2(DEFAULT_WAIT_TIME, getWebDriver(), getExpectedAlerts());
121     }
122 
123     /**
124      * @throws Exception if the test fails
125      */
126     @Test
127     @Alerts("Received: timeout")
128     public void selfSetTimeout() throws Exception {
129         final String html = DOCTYPE_HTML
130             + "<html><body><script>\n"
131             + LOG_TITLE_FUNCTION
132             + "try {\n"
133             + "  var myWorker = new Worker('worker.js');\n"
134             + "  myWorker.onmessage = function(e) {\n"
135             + "    log('Received: ' + e.data);\n"
136             + "  };\n"
137             + "} catch(e) { logEx(e); }\n"
138             + "</script></body></html>\n";
139 
140         final String workerJs = "self.setTimeout(function() {\n"
141                 + "  postMessage('timeout');\n"
142                 + "}, 10);\n";
143 
144         getMockWebConnection().setResponse(new URL(URL_FIRST, "worker.js"), workerJs, MimeType.TEXT_JAVASCRIPT);
145 
146         loadPage2(html);
147         verifyTitle2(DEFAULT_WAIT_TIME, getWebDriver(), getExpectedAlerts());
148     }
149 
150     /**
151      * @throws Exception if the test fails
152      */
153     @Test
154     @Alerts("Received: interval")
155     public void selfSetInterval() throws Exception {
156         final String html = DOCTYPE_HTML
157             + "<html><body><script>\n"
158             + LOG_TITLE_FUNCTION
159             + "try {\n"
160             + "  var myWorker = new Worker('worker.js');\n"
161             + "  myWorker.onmessage = function(e) {\n"
162             + "    log('Received: ' + e.data);\n"
163             + "  };\n"
164             + "} catch(e) { logEx(e); }\n"
165             + "</script></body></html>\n";
166 
167         final String workerJs = "var id = self.setInterval(function() {\n"
168                 + "  postMessage('interval');\n"
169                 + "  clearInterval(id);\n"
170                 + "}, 10);\n";
171 
172         getMockWebConnection().setResponse(new URL(URL_FIRST, "worker.js"), workerJs, MimeType.TEXT_JAVASCRIPT);
173 
174         loadPage2(html);
175         verifyTitle2(DEFAULT_WAIT_TIME, getWebDriver(), getExpectedAlerts());
176     }
177 
178     /**
179      * @throws Exception if an error occurs
180      */
181     @Test
182     @Alerts("Received: func=function addEventListener() { [native code] }")
183     public void functionDefaultValue() throws Exception {
184         final String html = DOCTYPE_HTML
185             + "<html><body><script>\n"
186             + LOG_TITLE_FUNCTION
187             + "try {\n"
188             + "  var myWorker = new Worker('worker.js');\n"
189             + "  myWorker.onmessage = function(e) {\n"
190             + "    log('Received: ' + e.data);\n"
191             + "  };\n"
192             + "} catch(e) { logEx(e); }\n"
193             + "</script></body></html>\n";
194 
195         final String workerJs = "postMessage('func='+self.addEventListener);";
196 
197         getMockWebConnection().setResponse(new URL(URL_FIRST, "worker.js"), workerJs, MimeType.TEXT_JAVASCRIPT);
198 
199         loadPage2(html);
200         verifyTitle2(DEFAULT_WAIT_TIME, getWebDriver(), getExpectedAlerts());
201     }
202 
203     /**
204      * @throws Exception if the test fails
205      */
206     @Test
207     @Alerts(DEFAULT = "Received: Result = 15",
208             FF = {},
209             FF_ESR = {})
210     public void workerCodeWithWrongMimeType() throws Exception {
211         final String html = DOCTYPE_HTML
212             + "<html><body>"
213             + "<script>\n"
214             + LOG_TITLE_FUNCTION
215             + "try {\n"
216             + "  var myWorker = new Worker('worker.js');\n"
217             + "  myWorker.onmessage = function(e) {\n"
218             + "    log('Received: ' + e.data);\n"
219             + "  };\n"
220             + "  setTimeout(function() { myWorker.postMessage([5, 3]);}, 10);\n"
221             + "} catch(e) { logEx(e); }\n"
222             + "</script></body></html>\n";
223 
224         final String workerJs = "onmessage = function(e) {\n"
225                 + "  var workerResult = 'Result = ' + (e.data[0] * e.data[1]);\n"
226                 + "  postMessage(workerResult);\n"
227                 + "}\n";
228 
229         getMockWebConnection().setResponse(new URL(URL_FIRST, "worker.js"), workerJs, MimeType.TEXT_HTML);
230 
231         loadPage2(html);
232         verifyTitle2(DEFAULT_WAIT_TIME, getWebDriver(), getExpectedAlerts());
233     }
234 
235     /**
236      * @throws Exception if the test fails
237      */
238     @Test
239     @Alerts("Received: Bob [GSCE] [undefined]")
240     public void workerName() throws Exception {
241         final String html = DOCTYPE_HTML
242             + "<html><body>"
243             + "<script>\n"
244             + LOG_TITLE_FUNCTION
245             + "try {\n"
246             + "  var myWorker = new Worker('worker.js', { name: 'Bob'});\n"
247             + "  myWorker.onmessage = function(e) {\n"
248             + "    log('Received: ' + e.data);\n"
249             + "  };\n"
250             + "  setTimeout(function() { myWorker.postMessage('Heho');}, 10);\n"
251             + "} catch(e) { logEx(e); }\n"
252             + "</script></body></html>\n";
253 
254         final String workerJs = "onmessage = function(e) {\n"
255                 + "  let desc = Object.getOwnPropertyDescriptor(this, 'name');\n"
256                 + "  property = name + ' [';\n"
257                 + "  if (desc.get != undefined) property += 'G';\n"
258                 + "  if (desc.set != undefined) property += 'S';\n"
259                 + "  if (desc.writable) property += 'W';\n"
260                 + "  if (desc.configurable) property += 'C';\n"
261                 + "  if (desc.enumerable) property += 'E';\n"
262                 + "  property += ']'\n"
263 
264                 + "  desc = Object.getOwnPropertyDescriptor(this.constructor.prototype, 'name');\n"
265                 + "  property += ' [' + desc + ']';\n"
266 
267                 + "  postMessage(property);\n"
268                 + "}\n";
269 
270         getMockWebConnection().setResponse(new URL(URL_FIRST, "worker.js"), workerJs, MimeType.TEXT_JAVASCRIPT);
271 
272         loadPage2(html);
273         verifyTitle2(DEFAULT_WAIT_TIME, getWebDriver(), getExpectedAlerts());
274     }
275 
276     /**
277      * @throws Exception if the test fails
278      */
279     @Test
280     @Alerts("Received: Bob the builder")
281     public void workerNameSet() throws Exception {
282         final String html = DOCTYPE_HTML
283             + "<html><body>"
284             + "<script>\n"
285             + LOG_TITLE_FUNCTION
286             + "try {\n"
287             + "  var myWorker = new Worker('worker.js', { name: 'Bob'});\n"
288             + "  myWorker.onmessage = function(e) {\n"
289             + "    log('Received: ' + e.data);\n"
290             + "  };\n"
291             + "  setTimeout(function() { myWorker.postMessage('Heho');}, 10);\n"
292             + "} catch(e) { logEx(e); }\n"
293             + "</script></body></html>\n";
294 
295         final String workerJs = "onmessage = function(e) {\n"
296                 + "  name = name + ' the builder';\n"
297                 + "  postMessage(name);\n"
298                 + "}\n";
299 
300         getMockWebConnection().setResponse(new URL(URL_FIRST, "worker.js"), workerJs, MimeType.TEXT_JAVASCRIPT);
301 
302         loadPage2(html);
303         verifyTitle2(DEFAULT_WAIT_TIME, getWebDriver(), getExpectedAlerts());
304     }
305 
306     /**
307      * @throws Exception if the test fails
308      */
309     @Test
310     @Alerts("Received: working")
311     public void workerOptionsUndefined() throws Exception {
312         final String html = DOCTYPE_HTML
313             + "<html><body>"
314             + "<script>\n"
315             + LOG_TITLE_FUNCTION
316             + "try {\n"
317             + "  var myWorker = new Worker('worker.js', undefined);\n"
318             + "  myWorker.onmessage = function(e) {\n"
319             + "    log('Received: ' + e.data);\n"
320             + "  };\n"
321             + "  setTimeout(function() { myWorker.postMessage('Heho');}, 10);\n"
322             + "} catch(e) { logEx(e); }\n"
323             + "</script></body></html>\n";
324 
325         final String workerJs = "onmessage = function(e) {\n"
326                 + "  postMessage('working');\n"
327                 + "}\n";
328 
329         getMockWebConnection().setResponse(new URL(URL_FIRST, "worker.js"), workerJs, MimeType.TEXT_JAVASCRIPT);
330 
331         loadPage2(html);
332         verifyTitle2(DEFAULT_WAIT_TIME, getWebDriver(), getExpectedAlerts());
333     }
334 
335     /**
336      * @throws Exception if the test fails
337      */
338     @Test
339     @Alerts("Received: working")
340     public void workerOptionsNull() throws Exception {
341         final String html = DOCTYPE_HTML
342             + "<html><body>"
343             + "<script>\n"
344             + LOG_TITLE_FUNCTION
345             + "try {\n"
346             + "  var myWorker = new Worker('worker.js', null);\n"
347             + "  myWorker.onmessage = function(e) {\n"
348             + "    log('Received: ' + e.data);\n"
349             + "  };\n"
350             + "  setTimeout(function() { myWorker.postMessage('Heho');}, 10);\n"
351             + "} catch(e) { logEx(e); }\n"
352             + "</script></body></html>\n";
353 
354         final String workerJs = "onmessage = function(e) {\n"
355                 + "  postMessage('working');\n"
356                 + "}\n";
357 
358         getMockWebConnection().setResponse(new URL(URL_FIRST, "worker.js"), workerJs, MimeType.TEXT_JAVASCRIPT);
359 
360         loadPage2(html);
361         verifyTitle2(DEFAULT_WAIT_TIME, getWebDriver(), getExpectedAlerts());
362     }
363 }