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.file;
16  
17  import org.htmlunit.WebDriverTestCase;
18  import org.htmlunit.junit.BrowserRunner;
19  import org.htmlunit.junit.annotation.Alerts;
20  import org.htmlunit.util.MimeType;
21  import org.junit.Test;
22  import org.junit.runner.RunWith;
23  
24  /**
25   * Tests for {@link org.htmlunit.javascript.host.file.Blob}.
26   *
27   * @author Ronald Brill
28   * @author Lai Quang Duong
29   */
30  @RunWith(BrowserRunner.class)
31  public class BlobTest extends WebDriverTestCase {
32  
33      /**
34       * @throws Exception if the test fails
35       */
36      @Test
37      @Alerts({"3", MimeType.TEXT_HTML})
38      public void properties() throws Exception {
39          final String html = DOCTYPE_HTML
40              + "<html>\n"
41              + "<head>\n"
42              + "<script>\n"
43              + LOG_TITLE_FUNCTION
44              + "function test() {\n"
45              + "  var blob = new Blob(['abc'], {type : 'text/html'});\n"
46  
47              + "  log(blob.size);\n"
48              + "  log(blob.type);\n"
49              + "}\n"
50              + "</script>\n"
51              + "</head>\n"
52              + "<body onload='test()'>\n"
53              + "</body>\n"
54              + "</html>";
55  
56          loadPageVerifyTitle2(html);
57      }
58  
59      /**
60       * @throws Exception if the test fails
61       */
62      @Test
63      @Alerts({"function", "Hello HtmlUnit"})
64      public void text() throws Exception {
65          final String html = DOCTYPE_HTML
66                  + "<html>\n"
67                  + "<head>\n"
68                  + "<script>\n"
69                  + LOG_TITLE_FUNCTION
70                  + "function test() {\n"
71                  + "  var blob = new Blob(['Hello HtmlUnit'], {type : 'text/html'});\n"
72  
73                  + "  log(typeof blob.text);\n"
74                  + "  try {\n"
75                  + "    blob.text().then(function(text) { log(text); });\n"
76                  + "  } catch(e) { log('TypeError ' + (e instanceof TypeError)); }\n"
77                  + "}\n"
78                  + "</script>\n"
79                  + "</head>\n"
80                  + "<body onload='test()'>\n"
81                  + "</body>\n"
82                  + "</html>";
83  
84          loadPage2(html);
85          verifyTitle2(DEFAULT_WAIT_TIME, getWebDriver(), getExpectedAlerts());
86      }
87  
88      /**
89       * @throws Exception if the test fails
90       */
91      @Test
92      @Alerts("text/plain")
93      public void typeTxt() throws Exception {
94          type(MimeType.TEXT_PLAIN);
95      }
96  
97      /**
98       * @throws Exception if the test fails
99       */
100     @Test
101     @Alerts("htmlunit")
102     public void typeHtmlUnit() throws Exception {
103         type("htmlunit");
104     }
105 
106     /**
107      * @throws Exception if the test fails
108      */
109     @Test
110     @Alerts("")
111     public void typeEmpty() throws Exception {
112         type("");
113     }
114 
115     private void type(final String type) throws Exception {
116         final String html = DOCTYPE_HTML
117             + "<html>\n"
118             + "<head>\n"
119             + "<script>\n"
120             + LOG_TITLE_FUNCTION
121             + "function test() {\n"
122             + "  var blob = new Blob(['Hello HtmlUnit'], {type : '" + type + "'});\n"
123             + "  log(blob.type);\n"
124             + "}\n"
125             + "</script>\n"
126             + "</head>\n"
127             + "<body onload='test()'>\n"
128             + "</body>\n"
129             + "</html>";
130 
131         loadPageVerifyTitle2(html);
132     }
133 
134     /**
135      * @throws Exception if the test fails
136      */
137     @Test
138     @Alerts("")
139     public void typeDefault() throws Exception {
140         final String html = DOCTYPE_HTML
141             + "<html>\n"
142             + "<head>\n"
143             + "<script>\n"
144             + LOG_TITLE_FUNCTION
145             + "function test() {\n"
146             + "  var blob = new Blob(['Hello HtmlUnit']);\n"
147             + "  log(blob.type);\n"
148             + "}\n"
149             + "</script>\n"
150             + "</head>\n"
151             + "<body onload='test()'>\n"
152             + "</body>\n"
153             + "</html>";
154 
155         loadPageVerifyTitle2(html);
156     }
157 
158     /**
159      * @throws Exception if the test fails
160      */
161     @Test
162     @Alerts({"0", "", ""})
163     public void ctorNoArgs() throws Exception {
164         final String html = DOCTYPE_HTML
165                 + "<html>\n"
166                 + "<head>\n"
167                 + "<script>\n"
168                 + LOG_TITLE_FUNCTION
169                 + "  function test() {\n"
170                 + "    var blob = new Blob();\n"
171 
172                 + "    log(blob.size);\n"
173                 + "    log(blob.type);\n"
174                 + "    try {\n"
175                 + "      blob.text().then(function(text) { log(text); });\n"
176                 + "    } catch(e) { log('TypeError ' + (e instanceof TypeError)); }\n"
177                 + "  }\n"
178                 + "</script>\n"
179                 + "</head>\n"
180                 + "<body onload='test()'>\n"
181                 + "</body>\n"
182                 + "</html>";
183 
184         loadPage2(html);
185         verifyTitle2(DEFAULT_WAIT_TIME, getWebDriver(), getExpectedAlerts());
186     }
187 
188     /**
189      * @throws Exception if the test fails
190      */
191     @Test
192     @Alerts({"0", "", ""})
193     public void ctorEmpty() throws Exception {
194         final String html = DOCTYPE_HTML
195                 + "<html>\n"
196                 + "<head>\n"
197                 + "<script>\n"
198                 + LOG_TITLE_FUNCTION
199                 + "  function test() {\n"
200                 + "    var blob = new Blob([]);\n"
201 
202                 + "    log(blob.size);\n"
203                 + "    log(blob.type);\n"
204                 + "    try {\n"
205                 + "      blob.text().then(function(text) { log(text); });\n"
206                 + "    } catch(e) { log('TypeError ' + (e instanceof TypeError)); }\n"
207                 + "  }\n"
208                 + "</script>\n"
209                 + "</head>\n"
210                 + "<body onload='test()'>\n"
211                 + "</body>\n"
212                 + "</html>";
213 
214         loadPage2(html);
215         verifyTitle2(DEFAULT_WAIT_TIME, getWebDriver(), getExpectedAlerts());
216     }
217 
218     /**
219      * @throws Exception if the test fails
220      */
221     @Test
222     @Alerts({"8", "", "HtmlUnit"})
223     public void ctorString() throws Exception {
224         final String html = DOCTYPE_HTML
225                 + "<html>\n"
226                 + "<head>\n"
227                 + "<script>\n"
228                 + LOG_TITLE_FUNCTION
229                 + "  function test() {\n"
230                 + "    var blob = new Blob(['HtmlUnit']);\n"
231 
232                 + "    log(blob.size);\n"
233                 + "    log(blob.type);\n"
234                 + "    try {\n"
235                 + "      blob.text().then(function(text) { log(text); });\n"
236                 + "    } catch(e) { log('TypeError ' + (e instanceof TypeError)); }\n"
237                 + "  }\n"
238                 + "</script>\n"
239                 + "</head>\n"
240                 + "<body onload='test()'>\n"
241                 + "</body>\n"
242                 + "</html>";
243 
244         loadPage2(html);
245         verifyTitle2(DEFAULT_WAIT_TIME, getWebDriver(), getExpectedAlerts());
246     }
247 
248     /**
249      * @throws Exception if the test fails
250      */
251     @Test
252     @Alerts({"8", "application/octet-stream", "HtmlUnit"})
253     public void ctorStringWithOptions() throws Exception {
254         final String html = DOCTYPE_HTML
255                 + "<html>\n"
256                 + "<head>\n"
257                 + "<script>\n"
258                 + LOG_TITLE_FUNCTION
259                 + "  function test() {\n"
260                 + "    var blob = new Blob(['Html', 'Unit'], {type: 'application/octet-stream'});\n"
261 
262                 + "    log(blob.size);\n"
263                 + "    log(blob.type);\n"
264                 + "    try {\n"
265                 + "      blob.text().then(function(text) { log(text); });\n"
266                 + "    } catch(e) { log('TypeError ' + (e instanceof TypeError)); }\n"
267                 + "  }\n"
268                 + "</script>\n"
269                 + "</head>\n"
270                 + "<body onload='test()'>\n"
271                 + "</body>\n"
272                 + "</html>";
273 
274         loadPage2(html);
275         verifyTitle2(DEFAULT_WAIT_TIME, getWebDriver(), getExpectedAlerts());
276     }
277 
278     /**
279      * @throws Exception if the test fails
280      */
281     @Test
282     @Alerts({"16", "", "HtmlUnitis great"})
283     public void ctorStrings() throws Exception {
284         final String html = DOCTYPE_HTML
285                 + "<html>\n"
286                 + "<head>\n"
287                 + "<script>\n"
288                 + LOG_TITLE_FUNCTION
289                 + "  function test() {\n"
290                 + "    var blob = new Blob(['Html', 'Unit', 'is great']);\n"
291 
292                 + "    log(blob.size);\n"
293                 + "    log(blob.type);\n"
294                 + "    try {\n"
295                 + "      blob.text().then(function(text) { log(text); });\n"
296                 + "    } catch(e) { log('TypeError ' + (e instanceof TypeError)); }\n"
297                 + "  }\n"
298                 + "</script>\n"
299                 + "</head>\n"
300                 + "<body onload='test()'>\n"
301                 + "</body>\n"
302                 + "</html>";
303 
304         loadPage2(html);
305         verifyTitle2(DEFAULT_WAIT_TIME, getWebDriver(), getExpectedAlerts());
306     }
307 
308     /**
309      * @throws Exception if the test fails
310      */
311     @Test
312     @Alerts({"12", "", "HtmlUnitMMMK"})
313     public void ctorMixed() throws Exception {
314         final String html = DOCTYPE_HTML
315                 + "<html>\n"
316                 + "<head>\n"
317                 + "<script>\n"
318                 + LOG_TITLE_FUNCTION
319                 + "  function test() {\n"
320                 + "    var nab = new ArrayBuffer(2);\n"
321                 + "    var nabv = new Uint8Array(nab, 0, 2);\n"
322                 + "    nabv.set([77, 77], 0);\n"
323                 + "    var blob = new Blob(['HtmlUnit',"
324                                         + "nab, new Int8Array([77,75])]);\n"
325 
326                 + "    log(blob.size);\n"
327                 + "    log(blob.type);\n"
328                 + "    try {\n"
329                 + "      blob.text().then(function(text) { log(text); });\n"
330                 + "    } catch(e) { log('TypeError ' + (e instanceof TypeError)); }\n"
331                 + "  }\n"
332                 + "</script>\n"
333                 + "</head>\n"
334                 + "<body onload='test()'>\n"
335                 + "</body>\n"
336                 + "</html>";
337 
338         loadPage2(html);
339         verifyTitle2(DEFAULT_WAIT_TIME, getWebDriver(), getExpectedAlerts());
340     }
341 
342     /**
343      * @throws Exception if the test fails
344      */
345     @Test
346     @Alerts({"34", "", "HtmlUnitHtmlUnitMMMKMKHtmlUnitMMMK"})
347     public void ctorMixedBlobs() throws Exception {
348         final String html = DOCTYPE_HTML
349                 + "<html>\n"
350                 + "<head>\n"
351                 + "<script>\n"
352                 + LOG_TITLE_FUNCTION
353                 + "  function test() {\n"
354                 + "    var nab = new ArrayBuffer(2);\n"
355                 + "    var nabv = new Uint8Array(nab, 0, 2);\n"
356                 + "    nabv.set([77, 77], 0);\n"
357                 + "    var blob = new Blob(['HtmlUnit',"
358                                         + "nab, new Int8Array([77,75])]);\n"
359                 + "    blob = new Blob(['HtmlUnit',"
360                                     + "blob, new Int8Array([77,75]), blob]);\n"
361                 + "    log(blob.size);\n"
362                 + "    log(blob.type);\n"
363                 + "    try {\n"
364                 + "      blob.text().then(function(text) { log(text); });\n"
365                 + "    } catch(e) { log('TypeError ' + (e instanceof TypeError)); }\n"
366                 + "  }\n"
367                 + "</script>\n"
368                 + "</head>\n"
369                 + "<body onload='test()'>\n"
370                 + "</body>\n"
371                 + "</html>";
372 
373         loadPage2(html);
374         verifyTitle2(DEFAULT_WAIT_TIME, getWebDriver(), getExpectedAlerts());
375     }
376 
377     /**
378      * @throws Exception if the test fails
379      */
380     @Test
381     @Alerts({"function", "Hello HtmlUnit"})
382     public void arrayBuffer() throws Exception {
383         final String html = DOCTYPE_HTML
384                 + "<html>\n"
385                 + "<head>\n"
386                 + "<script>\n"
387                 + LOG_TITLE_FUNCTION
388                 + "function test() {\n"
389                 + "  var blob = new Blob(['Hello HtmlUnit'], {type : 'text/html'});\n"
390                 + "  log(typeof blob.arrayBuffer);\n"
391                 + "  try {\n"
392                 + "    blob.arrayBuffer().then(function(buf) {\n"
393                 + "      var arr = new Uint8Array(buf);\n"
394                 + "      log(String.fromCharCode.apply(String, arr));\n"
395                 + "    })\n"
396                 + "  } catch(e) { log('TypeError ' + (e instanceof TypeError)); }\n"
397                 + "}\n"
398                 + "</script>\n"
399                 + "</head>\n"
400                 + "<body onload='test()'>\n"
401                 + "</body>\n"
402                 + "</html>";
403 
404         loadPage2(html);
405         verifyTitle2(DEFAULT_WAIT_TIME, getWebDriver(), getExpectedAlerts());
406     }
407 
408     /**
409      * @throws Exception if the test fails
410      */
411     @Test
412     @Alerts({"12", "", "function", "3", "", "tml"})
413     public void slice() throws Exception {
414         final String html = DOCTYPE_HTML
415                 + "<html>\n"
416                 + "<head>\n"
417                 + "<script>\n"
418                 + LOG_TITLE_FUNCTION
419                 + "  function test() {\n"
420                 + "    var nab = new ArrayBuffer(2);\n"
421                 + "    var nabv = new Uint8Array(nab, 0, 2);\n"
422                 + "    nabv.set([77, 77], 0);\n"
423                 + "    var blob = new Blob(['HtmlUnit',"
424                                         + "nab, new Int8Array([77,75])]);\n"
425 
426                 + "    log(blob.size);\n"
427                 + "    log(blob.type);\n"
428 
429                 + "    log(typeof blob.slice);\n"
430 
431                 + "    var sliced = blob.slice(1,4);\n"
432                 + "    log(sliced.size);\n"
433                 + "    log(sliced.type);\n"
434 
435                 + "    try {\n"
436                 + "      sliced.text().then(function(text) { log(text); });\n"
437                 + "    } catch(e) { log('TypeError ' + (e instanceof TypeError)); }\n"
438                 + "  }\n"
439                 + "</script>\n"
440                 + "</head>\n"
441                 + "<body onload='test()'>\n"
442                 + "</body>\n"
443                 + "</html>";
444 
445         loadPage2(html);
446         verifyTitle2(DEFAULT_WAIT_TIME, getWebDriver(), getExpectedAlerts());
447     }
448 
449     /**
450      * @throws Exception if the test fails
451      */
452     @Test
453     @Alerts({"12", "", "12", "", "HtmlUnitMMMK"})
454     public void sliceWhole() throws Exception {
455         slice("blob.slice();");
456     }
457 
458     /**
459      * @throws Exception if the test fails
460      */
461     @Test
462     @Alerts({"12", "", "9", "", "lUnitMMMK"})
463     public void sliceStartOnly() throws Exception {
464         slice("blob.slice(3);");
465     }
466 
467     /**
468      * @throws Exception if the test fails
469      */
470     @Test
471     @Alerts({"12", "", "7", "", "nitMMMK"})
472     public void sliceStartOnlyNegative() throws Exception {
473         slice("blob.slice(-7);");
474     }
475 
476     /**
477      * @throws Exception if the test fails
478      */
479     @Test
480     @Alerts({"12", "", "12", "", "HtmlUnitMMMK"})
481     public void sliceStartOnlyNegativeOutside() throws Exception {
482         slice("blob.slice(-123);");
483     }
484 
485     /**
486      * @throws Exception if the test fails
487      */
488     @Test
489     @Alerts({"12", "", "3", "", "mlU"})
490     public void sliceEndNegative() throws Exception {
491         slice("blob.slice(2, -7);");
492     }
493 
494     /**
495      * @throws Exception if the test fails
496      */
497     @Test
498     @Alerts({"12", "", "10", "", "mlUnitMMMK"})
499     public void sliceEndOutside() throws Exception {
500         slice("blob.slice(2, 1234);");
501     }
502 
503     /**
504      * @throws Exception if the test fails
505      */
506     @Test
507     @Alerts({"12", "", "0", "", ""})
508     public void sliceBothOutside() throws Exception {
509         slice("blob.slice(123, 1234);");
510     }
511 
512     /**
513      * @throws Exception if the test fails
514      */
515     @Test
516     @Alerts({"12", "", "0", "", ""})
517     public void sliceNoIntersection() throws Exception {
518         slice("blob.slice(5, 4);");
519     }
520 
521     /**
522      * @throws Exception if the test fails
523      */
524     @Test
525     @Alerts({"12", "", "1", "", "U"})
526     public void sliceEmptyIntersection() throws Exception {
527         slice("blob.slice(4, 5);");
528     }
529 
530     /**
531      * @throws Exception if the test fails
532      */
533     @Test
534     @Alerts({"12", "", "12", "", "HtmlUnitMMMK"})
535     public void sliceWrongStart() throws Exception {
536         slice("blob.slice('four');");
537     }
538 
539     /**
540      * @throws Exception if the test fails
541      */
542     @Test
543     @Alerts({"12", "", "0", "", ""})
544     public void sliceWrongEnd() throws Exception {
545         slice("blob.slice(1, 'four');");
546     }
547 
548     /**
549      * @throws Exception if the test fails
550      */
551     @Test
552     @Alerts({"12", "", "1", "type", "t"})
553     public void sliceContentType() throws Exception {
554         slice("blob.slice(1, 2, 'tyPE');");
555     }
556 
557     /**
558      * @throws Exception if the test fails
559      */
560     @Test
561     @Alerts({"12", "", "1", "7", "t"})
562     public void sliceContentTypeNotString() throws Exception {
563         slice("blob.slice(1, 2, 7);");
564     }
565 
566     private void slice(final String slice) throws Exception {
567         final String html = DOCTYPE_HTML
568                 + "<html>\n"
569                 + "<head>\n"
570                 + "<script>\n"
571                 + LOG_TITLE_FUNCTION
572                 + "  function test() {\n"
573                 + "    var nab = new ArrayBuffer(2);\n"
574                 + "    var nabv = new Uint8Array(nab, 0, 2);\n"
575                 + "    nabv.set([77, 77], 0);\n"
576                 + "    var blob = new Blob(['HtmlUnit',"
577                                         + "nab, new Int8Array([77,75])]);\n"
578 
579                 + "    log(blob.size);\n"
580                 + "    log(blob.type);\n"
581 
582                 + "    var sliced = " + slice + "\n"
583                 + "    log(sliced.size);\n"
584                 + "    log(sliced.type);\n"
585 
586                 + "    try {\n"
587                 + "      sliced.text().then(function(text) { log(text); });\n"
588                 + "    } catch(e) { log('TypeError ' + (e instanceof TypeError)); }\n"
589                 + "  }\n"
590                 + "</script>\n"
591                 + "</head>\n"
592                 + "<body onload='test()'>\n"
593                 + "</body>\n"
594                 + "</html>";
595 
596         loadPage2(html);
597         verifyTitle2(DEFAULT_WAIT_TIME, getWebDriver(), getExpectedAlerts());
598     }
599 }