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.html;
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.htmlunit.util.MimeType;
22  import org.junit.Test;
23  import org.junit.runner.RunWith;
24  
25  /**
26   * Tests for {@link HTMLAudioElement}.
27   *
28   * @author Ahmed Ashour
29   * @author Ronald Brill
30   */
31  @RunWith(BrowserRunner.class)
32  public class HTMLAudioElementTest extends WebDriverTestCase {
33  
34      /**
35       * @throws Exception if the test fails
36       */
37      @Test
38      @Alerts("false")
39      public void prototype() throws Exception {
40          final String html = DOCTYPE_HTML
41              + "<html><body>\n"
42              + "<script>\n"
43              + LOG_TITLE_FUNCTION
44              + "try {\n"
45              + "log(HTMLAudioElement.prototype == null);\n"
46              + "} catch(e) { logEx(e); }\n"
47              + "</script>\n"
48              + "</body></html>";
49  
50          loadPageVerifyTitle2(html);
51      }
52  
53  
54      /**
55       * @throws Exception if the test fails
56       */
57      @Test
58      @Alerts({"[object HTMLAudioElement]", "function HTMLAudioElement() { [native code] }"})
59      public void type() throws Exception {
60          final String html = DOCTYPE_HTML
61              + "<html><head>\n"
62              + "<script>\n"
63              + LOG_TITLE_FUNCTION
64              + "  function test() {\n"
65              + "    var elem = document.getElementById('a1');\n"
66              + "    try {\n"
67              + "      log(elem);\n"
68              + "      log(HTMLAudioElement);\n"
69              + "    } catch(e) { logEx(e); }\n"
70              + "  }\n"
71              + "</script>\n"
72              + "</head>\n"
73              + "<body onload='test()'>\n"
74              + "  <audio id='a1'/>\n"
75              + "</body></html>";
76  
77          loadPageVerifyTitle2(html);
78      }
79  
80      /**
81       * @throws Exception if the test fails
82       */
83      @Test
84      @Alerts({"1", "AUDIO"})
85      public void nodeTypeName() throws Exception {
86          final String html = DOCTYPE_HTML
87              + "<html><body>\n"
88              + "<audio id='a' src='horse.mp3'></audio>"
89              + "<script>\n"
90              + LOG_TITLE_FUNCTION
91              + "try {\n"
92              + "  var audio = document.getElementById('a');\n"
93              + "  log(audio.nodeType);"
94              + "  log(audio.nodeName);"
95              + "} catch(e) { logEx(e); }\n"
96              + "</script>\n"
97              + "</body></html>";
98  
99          loadPageVerifyTitle2(html);
100     }
101 
102     /**
103      * @throws Exception if the test fails
104      */
105     @Test
106     @Alerts({"[object HTMLAudioElement]", "[object Promise]", "done"})
107     public void audio() throws Exception {
108         final String html = DOCTYPE_HTML
109             + "<html><head>\n"
110             + "<script>\n"
111             + LOG_TITLE_FUNCTION
112             + "  function test() {\n"
113             + "    var a = new Audio('1.mp3');\n"
114             + "    log(a);\n"
115             + "    log(a.play());\n"
116             + "    log('done');\n"
117             + "  }\n"
118             + "</script>\n"
119             + "</head>\n"
120             + "<body onload='test()'>\n"
121             + "</body></html>";
122 
123         getMockWebConnection().setDefaultResponse("Error: not found", 404, "Not Found", MimeType.TEXT_HTML);
124 
125         loadPageVerifyTitle2(html);
126     }
127 
128     /**
129      * Checks whether the specific {@code parent} is an actual parent of the given {@code child}.
130      *
131      * @param parent the parent host name
132      * @param child the child host name
133      * @throws Exception if an error occurs
134      */
135     protected void parentOf(final String parent, final String child) throws Exception {
136         final String html = DOCTYPE_HTML
137             + "<html><head>\n"
138             + "<title>New Tab</title>\n"
139             + "<script>\n"
140             + LOG_TEXTAREA_FUNCTION
141             + "  function test() {\n"
142             + "    try {\n"
143             + "      log(isParentOf(" + parent + ", " + child + "));\n"
144             + "    } catch(e) { log('false'); }\n"
145             + "  }\n"
146 
147             + "  /*\n"
148             + "   * Returns true if o1 prototype is parent/grandparent of o2 prototype\n"
149             + "   */\n"
150             + "  function isParentOf(o1, o2) {\n"
151             + "    o1.prototype.myCustomFunction = function() {};\n"
152             + "    return o2.prototype.myCustomFunction != undefined;\n"
153             + "  }\n"
154             + "</script></head>\n"
155             + "<body onload='test()'>\n"
156             + LOG_TEXTAREA
157             + "</body></html>";
158 
159         loadPageVerifyTextArea2(html);
160     }
161 
162     /**
163      * @throws Exception if the test fails
164      */
165     @Test
166     @Alerts("true")
167     @HtmlUnitNYI(CHROME = "false",
168             EDGE = "false",
169             FF = "false",
170             FF_ESR = "false")
171     public void Audio_HTMLAudioElement() throws Exception {
172         parentOf("Audio", "HTMLAudioElement");
173     }
174 
175     /**
176      * @throws Exception if the test fails
177      */
178     @Test
179     @Alerts("true")
180     public void HTMLAudioElement_Audio() throws Exception {
181         parentOf("HTMLAudioElement", "Audio");
182     }
183 
184     /**
185      * @throws Exception if the test fails
186      */
187     @Test
188     public void doNotRetrieveStream() throws Exception {
189         final String html = DOCTYPE_HTML
190             + "<html><head>\n"
191             + "</head>\n"
192             + "<body>\n"
193             + "  <audio controls>\n"
194             + "    <source src='horse.ogg' type='audio/ogg'>\n"
195             + "    <source src='horse.mp3' type='audio/mpeg'>\n"
196             + "    Your browser does not support the audio element.\n"
197             + "  </audio>\n"
198             + "</body></html>";
199 
200         loadPage2(html);
201         assertEquals(1, getMockWebConnection().getRequestCount());
202     }
203 
204     /**
205      * @throws Exception if the test fails
206      */
207     @Test
208     @Alerts({"[object HTMLAudioElement]", "maybe", "done"})
209     public void nullConstructor() throws Exception {
210         final String html = DOCTYPE_HTML
211             + "<html><head>\n"
212             + "<script>\n"
213             + LOG_TITLE_FUNCTION
214             + "  function test() {\n"
215             + "    var a = new Audio(null);\n"
216             + "    log(a);\n"
217             + "    log(a.canPlayType('audio/ogg'));\n"
218             + "    log('done');\n"
219             + "  }\n"
220             + "</script>\n"
221             + "</head>\n"
222             + "<body onload='test()'>\n"
223             + "</body></html>";
224 
225         getMockWebConnection().setDefaultResponse("Error: not found", 404, "Not Found", MimeType.TEXT_HTML);
226 
227         loadPageVerifyTitle2(html);
228     }
229 
230     /**
231      * @throws Exception if the test fails
232      */
233     @Test
234     @Alerts("true")
235     public void canPlayType() throws Exception {
236         final String html = DOCTYPE_HTML
237             + "<html><head>\n"
238             + "<script>\n"
239             + LOG_TITLE_FUNCTION
240             + "  function test() {\n"
241             + "    var elem = document.getElementById('a1');\n"
242             + "    log(typeof elem.canPlayType === 'function');\n"
243             + "  }\n"
244             + "</script>\n"
245             + "</head>\n"
246             + "<body onload='test()'>\n"
247             + "  <audio id='a1'/>\n"
248             + "</body></html>";
249 
250         loadPageVerifyTitle2(html);
251     }
252 
253     /**
254      * @throws Exception if the test fails
255      */
256     @Test
257     @Alerts("maybe")
258     public void canPlayType_AudioOgg() throws Exception {
259         canPlayType("audio/ogg");
260     }
261 
262     /**
263      * @throws Exception if the test fails
264      */
265     @Test
266     @Alerts("maybe")
267     public void canPlayType_VideoOgg() throws Exception {
268         canPlayType("video/ogg");
269     }
270 
271     /**
272      * @throws Exception if the test fails
273      */
274     @Test
275     @Alerts("maybe")
276     public void canPlayType_ApplicationOgg() throws Exception {
277         canPlayType("application/ogg");
278     }
279 
280     /**
281      * @throws Exception if the test fails
282      */
283     @Test
284     @Alerts("maybe")
285     public void canPlayType_Mp4() throws Exception {
286         canPlayType("video/mp4");
287     }
288 
289     /**
290      * @throws Exception if the test fails
291      */
292     @Test
293     @Alerts(DEFAULT = "",
294             FF = "maybe",
295             FF_ESR = "maybe")
296     @HtmlUnitNYI(CHROME = "maybe",
297             EDGE = "maybe")
298     public void canPlayType_AudioWave() throws Exception {
299         canPlayType("audio/wave");
300     }
301 
302     /**
303      * @throws Exception if the test fails
304      */
305     @Test
306     @Alerts("maybe")
307     public void canPlayType_AudioWav() throws Exception {
308         canPlayType("audio/wav");
309     }
310 
311     /**
312      * @throws Exception if the test fails
313      */
314     @Test
315     @Alerts("maybe")
316     public void canPlayType_AudioXWav() throws Exception {
317         canPlayType("audio/x-wav");
318     }
319 
320     /**
321      * @throws Exception if the test fails
322      */
323     @Test
324     @Alerts(DEFAULT = "",
325             FF = "maybe",
326             FF_ESR = "maybe")
327     @HtmlUnitNYI(CHROME = "maybe",
328             EDGE = "maybe")
329     public void canPlayType_AudioPnWav() throws Exception {
330         canPlayType("audio/x-pn-wav");
331     }
332 
333     /**
334      * @throws Exception if the test fails
335      */
336     @Test
337     @Alerts("maybe")
338     public void canPlayType_AudioWebm() throws Exception {
339         canPlayType("audio/webm");
340     }
341 
342     /**
343      * @throws Exception if the test fails
344      */
345     @Test
346     @Alerts("maybe")
347     public void canPlayType_VideoWebm() throws Exception {
348         canPlayType("video/webm");
349     }
350 
351     /**
352      * @throws Exception if the test fails
353      */
354     @Test
355     @Alerts(DEFAULT = "maybe",
356             CHROME = "probably",
357             EDGE = "probably")
358     @HtmlUnitNYI(CHROME = "maybe",
359             EDGE = "maybe")
360     public void canPlayType_AudioMpeg() throws Exception {
361         canPlayType("audio/mpeg");
362     }
363 
364     /**
365      * @throws Exception if the test fails
366      */
367     @Test
368     @Alerts(DEFAULT = "probably",
369             FF = "maybe",
370             FF_ESR = "maybe")
371     @HtmlUnitNYI(CHROME = "maybe",
372             EDGE = "maybe")
373     public void canPlayType_AudioFlac() throws Exception {
374         canPlayType("audio/flac");
375     }
376 
377     /**
378      * @throws Exception if the test fails
379      */
380     @Test
381     @Alerts(DEFAULT = "",
382             FF = "maybe",
383             FF_ESR = "maybe")
384     @HtmlUnitNYI(CHROME = "maybe",
385             EDGE = "maybe")
386     public void canPlayType_AudioXFlac() throws Exception {
387         canPlayType("audio/x-flac");
388     }
389 
390     /**
391      * @throws Exception if the test fails
392      */
393     private void canPlayType(final String mimeType) throws Exception {
394         final String html = DOCTYPE_HTML
395             + "<html><head>\n"
396             + "<script>\n"
397             + LOG_TITLE_FUNCTION
398             + "  function test() {\n"
399             + "    var elem = document.getElementById('a1');\n"
400             + "    log(elem.canPlayType('" + mimeType + "'));\n"
401             + "  }\n"
402             + "</script>\n"
403             + "</head>\n"
404             + "<body onload='test()'>\n"
405             + "  <audio id='a1'/>\n"
406             + "</body></html>";
407 
408         loadPageVerifyTitle2(html);
409     }
410 
411     /**
412      * @throws Exception if the test fails
413      */
414     @Test
415     @Alerts({"[object HTMLAudioElement]", "1"})
416     public void newAudioNodeType() throws Exception {
417         final String html = DOCTYPE_HTML
418             + "<html><head>\n"
419             + "<script>\n"
420             + LOG_TITLE_FUNCTION
421             + "  function test() {\n"
422             + "    var a = new Audio();\n"
423             + "    log(a);\n"
424             + "    log(a.nodeType);\n"
425             + "  }\n"
426             + "</script>\n"
427             + "</head>\n"
428             + "<body onload='test()'>\n"
429             + "</body></html>";
430 
431         loadPageVerifyTitle2(html);
432     }
433 
434     /**
435      * @throws Exception if the test fails
436      */
437     @Test
438     @Alerts({"[object HTMLAudioElement]", "AUDIO"})
439     public void newAudioNodeName() throws Exception {
440         final String html = DOCTYPE_HTML
441             + "<html><head>\n"
442             + "<script>\n"
443             + LOG_TITLE_FUNCTION
444             + "  function test() {\n"
445             + "    var a = new Audio();\n"
446             + "    log(a);\n"
447             + "    log(a.nodeName);\n"
448             + "  }\n"
449             + "</script>\n"
450             + "</head>\n"
451             + "<body onload='test()'>\n"
452             + "</body></html>";
453 
454         loadPageVerifyTitle2(html);
455     }
456 
457     /**
458      * @throws Exception if the test fails
459      */
460     @Test
461     @Alerts({"string", "§§URL§§horse.mp3", "§§URL§§cow.mp3",
462              "<audio id=\"a\" src=\"cow.mp3\"></audio>"})
463     public void src() throws Exception {
464         final String html = DOCTYPE_HTML
465             + "<html><body>\n"
466             + "<audio id='a' src='horse.mp3'></audio>"
467             + "<script>\n"
468             + LOG_TITLE_FUNCTION
469             + "try {\n"
470             + "  var audio = document.getElementById('a');\n"
471             + "  var src = audio.src;\n"
472             + "  log(typeof src);"
473             + "  log(src);"
474             + "  audio.src = 'cow.mp3';\n"
475             + "  log(audio.src);"
476             + "  log(audio.outerHTML);"
477             + "} catch(e) { logEx(e); }\n"
478             + "</script>\n"
479             + "</body></html>";
480 
481         expandExpectedAlertsVariables(URL_FIRST);
482         loadPageVerifyTitle2(html);
483     }
484 
485     /**
486      * @throws Exception if the test fails
487      */
488     @Test
489     @Alerts({"string", "", "§§URL§§cow.mp3",
490              "<audio id=\"a\" src=\"cow.mp3\"><source src=\"horse.mp3\" type=\"audio/mpeg\"></audio>"})
491     public void srcChild() throws Exception {
492         final String html = DOCTYPE_HTML
493             + "<html><body>\n"
494             + "<audio id='a'><source src='horse.mp3' type='audio/mpeg'></audio>"
495             + "<script>\n"
496             + LOG_TITLE_FUNCTION
497             + "try {\n"
498             + "  var audio = document.getElementById('a');\n"
499             + "  var src = audio.src;\n"
500             + "  log(typeof src);"
501             + "  log(src);"
502             + "  audio.src = 'cow.mp3';\n"
503             + "  log(audio.src);"
504             + "  log(audio.outerHTML);"
505             + "} catch(e) { logEx(e); }\n"
506             + "</script>\n"
507             + "</body></html>";
508 
509         expandExpectedAlertsVariables(URL_FIRST);
510         loadPageVerifyTitle2(html);
511     }
512 
513     /**
514      * @throws Exception if the test fails
515      */
516     @Test
517     @Alerts({"string", ""})
518     public void srcNotDefined() throws Exception {
519         final String html = DOCTYPE_HTML
520             + "<html><body>\n"
521             + "<audio id='a'></audio>"
522             + "<script>\n"
523             + LOG_TITLE_FUNCTION
524             + "try {\n"
525             + "  var src = document.getElementById('a').src;\n"
526             + "  log(typeof src);"
527             + "  log(src);"
528             + "} catch(e) { logEx(e); }\n"
529             + "</script>\n"
530             + "</body></html>";
531 
532         loadPageVerifyTitle2(html);
533     }
534 
535     /**
536      * @throws Exception if the test fails
537      */
538     @Test
539     @Alerts({"string", ""})
540     public void currentSrc() throws Exception {
541         final String html = DOCTYPE_HTML
542             + "<html><body>\n"
543             + "<audio id='a' src='horse.mp3'></audio>"
544             + "<script>\n"
545             + LOG_TITLE_FUNCTION
546             + "try {\n"
547             + "  var currentSrc = document.getElementById('a').currentSrc;\n"
548             + "  log(typeof currentSrc);"
549             + "  log(currentSrc);"
550             + "} catch(e) { logEx(e); }\n"
551             + "</script>\n"
552             + "</body></html>";
553 
554         expandExpectedAlertsVariables(URL_FIRST);
555         loadPageVerifyTitle2(html);
556     }
557 
558     /**
559      * @throws Exception if the test fails
560      */
561     @Test
562     @Alerts({"string", ""})
563     public void currentSrcChild() throws Exception {
564         final String html = DOCTYPE_HTML
565             + "<html><body>\n"
566             + "<audio id='a'><source src='horse.mp3' type='audio/mpeg'></audio>"
567             + "<script>\n"
568             + LOG_TITLE_FUNCTION
569             + "try {\n"
570             + "  var currentSrc = document.getElementById('a').currentSrc;\n"
571             + "  log(typeof currentSrc);"
572             + "  log(currentSrc);"
573             + "} catch(e) { logEx(e); }\n"
574             + "</script>\n"
575             + "</body></html>";
576 
577         expandExpectedAlertsVariables(URL_FIRST);
578         loadPageVerifyTitle2(html);
579     }
580 
581     /**
582      * @throws Exception if the test fails
583      */
584     @Test
585     @Alerts({"string", ""})
586     public void currentSrcNotDefined() throws Exception {
587         final String html = DOCTYPE_HTML
588             + "<html><body>\n"
589             + "<audio id='a'></audio>"
590             + "<script>\n"
591             + LOG_TITLE_FUNCTION
592             + "try {\n"
593             + "  var currentSrc = document.getElementById('a').currentSrc;\n"
594             + "  log(typeof currentSrc);"
595             + "  log(currentSrc);"
596             + "} catch(e) { logEx(e); }\n"
597             + "</script>\n"
598             + "</body></html>";
599 
600         loadPageVerifyTitle2(html);
601     }
602 }