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