summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/html/semantics/embedded-content/media-elements
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/html/semantics/embedded-content/media-elements')
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/audio_controls_present-manual.html14
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/audio_loop_base.html42
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/audio_loop_seek_to_eos.html29
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/audio_muted_overriding_volume-manual.html21
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/audio_muted_present-manual.html20
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/audio_volume_check.html58
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/audio_volume_loudest-manual.html21
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/audio_volume_silent-manual.html21
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html35
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-allowed-by-feature-policy-attribute.https.sub.html34
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-allowed-by-feature-policy.https.sub.html39
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-allowed-by-feature-policy.https.sub.html.headers1
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-default-feature-policy.https.sub.html39
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-disabled-by-feature-policy.https.sub.html39
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-disabled-by-feature-policy.https.sub.html.headers1
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-supported-by-feature-policy.html11
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-with-broken-track.html34
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/controlsList.tentative.html32
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/error-codes/error.html40
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_canplay.html40
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_canplay_noautoplay.html34
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_canplaythrough.html40
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_canplaythrough_noautoplay.html34
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_loadeddata.html40
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_loadeddata_noautoplay.html34
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_loadedmetadata.html40
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_loadedmetadata_noautoplay.html34
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_loadstart.html38
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_loadstart_noautoplay.html36
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_order_canplay_canplaythrough.html50
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_order_canplay_playing.html50
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_order_loadedmetadata_loadeddata.html50
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_order_loadstart_progress.html50
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_pause.html40
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_pause_noautoplay.html42
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_play.html40
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_play_noautoplay.html40
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_playing.html40
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_playing_noautoplay.html40
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_progress.html40
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_progress_noautoplay.html34
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_timeupdate.html34
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_timeupdate_noautoplay.html42
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_volumechange.html72
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/historical.html56
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/addTextTrack.html116
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/crossOrigin.html60
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/textTracks.html13
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/default.html55
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/kind.html146
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/label.html83
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/readyState.html18
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/src.html43
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/srclang.html82
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/track.html12
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/activeCues.html101
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/addCue.html68
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/constants.html23
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/cues.html100
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/kind.html31
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/label.html29
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/language.html29
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/mode.html55
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/oncuechange.html33
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/removeCue.html50
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/constructor.html23
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/endTime.html40
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/id.html39
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/onenter.html36
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/onexit.html36
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/pauseOnExit.html40
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/startTime.html39
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/track.html38
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCueList/getCueById.html53
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCueList/getter.html49
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCueList/length.html22
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/getTrackById.html16
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/getter.html32
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/length.html18
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/onaddtrack.html33
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/onremovetrack.html33
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TrackEvent/constructor.html25
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TrackEvent/createEvent.html15
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/autoplay-overrides-preload.html29
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/load-events-networkState.html91
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/load-removes-queued-error-event.html44
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-insert-before.html29
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-moved.html21
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-remove-addEventListener.html26
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-remove-no-listener.html26
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-remove-onerror.html26
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-currentSrc.html93
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-audio-constructor-no-src.html13
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-audio-constructor.html12
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-in-sync-event.html30
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-fragment-into-document.html22
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-into-document.html12
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-into-iframe.html23
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-parent-into-document.html19
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-in-div.html14
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-in-namespace.html14
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-networkState.html38
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-not-in-document.html13
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source.html14
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-load.html20
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-pause-networkState.html28
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-pause.html20
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-play.html20
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-from-document-networkState.html29
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-from-document.html15
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-src.html22
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-in-namespace.html14
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-networkState.html16
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-not-in-document.html13
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src.html14
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-control.html26
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-insert-br.html33
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-insert-source.html44
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-insert-text.html33
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-remove-source-after.html56
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-remove-source.html43
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-remove-text.html33
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-remove-source.html24
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-remove-src.html22
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-resumes-onload.html18
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-source-media-env-change.html24
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-source-media.html14
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resources/delayed-broken-video.py5
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resources/media-min-width.html31
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/stable-state-beforeunload-manual.html30
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/stable-state-dialogs-manual.html18
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/stable-state-print-manual.html22
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/location-of-the-media-resource/currentSrc.html48
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/media_fragment_seek.html49
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/mime-types/canPlayType.html123
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/networkState_during_loadstart.html42
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/networkState_during_progress.html42
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/networkState_initial.html33
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/offsets-into-the-media-resource/currentTime.html32
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/offsets-into-the-media-resource/duration.html11
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/paused_false_during_play.html42
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/paused_true_during_pause.html48
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/pitch-detector.js58
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/loop-from-ended.tentative.html57
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-move-to-other-document.html25
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-move-within-document.html25
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-remove-from-document-different-load.html44
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-remove-from-document-networkState.html27
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-remove-from-document.html37
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/play-in-detached-document.html24
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/playbackRate.html53
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/preload_reflects_none_autoplay.html31
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/preserves-pitch.html132
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/ready-states/autoplay-hidden.optional.html37
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/ready-states/autoplay-with-slow-text-tracks.html46
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/ready-states/autoplay.html73
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/readyState_during_canplay.html42
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/readyState_during_canplaythrough.html42
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/readyState_during_loadeddata.html42
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/readyState_during_loadedmetadata.html42
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/readyState_during_playing.html42
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/readyState_initial.html33
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/seeking/seek-to-currentTime.html34
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/seeking/seek-to-max-value.htm23
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/seeking/seek-to-negative-time.htm23
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/src_object_blob.html26
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/src_reflects_attribute_not_source_elements.html33
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cloneNode.html87
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/003.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/004.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/005.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/006.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/007.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/008.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/009.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/010.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/011.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/012.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/013.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/014.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/015.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/016.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/017.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/018.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/019.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/020.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/021.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/022.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/023.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/024.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/025.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/026.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/027.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/028.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/029.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/030.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/031.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/032.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/033.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/034.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/035.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/036.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/037.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/038.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/039.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/040.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/041.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/042.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/043.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/044.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/045.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/046.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/support/common.js144
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/support/cors-tester.py50
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/support/remove-cookie.html6
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/support/set-cookie.html6
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/crashtests/track-element-src-aborted-load-onerror-crash.html21
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/no-cuechange-before-play.html27
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/align-positioning-bad.vtt20
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/align-positioning.vtt20
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/align-text-line-position-bad.vtt21
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/align-text-line-position.vtt28
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/alignment-bad.vtt22
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/alignment-ltr.vtt22
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/alignment.vtt22
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/bom.vtt10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/captions-fast.vtt13
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/captions-gaps.vtt18
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/captions-html.vtt18
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/captions.vtt18
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/class-bad.vtt17
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/class.vtt14
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-id-error.vtt14
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-id.vtt18
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-no-id-error.vtt14
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-no-id.vtt11
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-recovery-cuetext.vtt6
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-recovery-header.vtt6
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-recovery-note.vtt9
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size-align-bad.vtt18
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size-align.vtt19
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size-bad.vtt17
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size.vtt19
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cues-chrono-order.vtt14
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cues-no-separation.vtt11
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cues-overlapping.vtt14
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cues.vtt17
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/default-styles.vtt19
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/degenerate-cues.vtt5
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/empty-cue.vtt11
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/entities-wrong.vtt15
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/entities.vtt30
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/interspersed-non-cue.vtt9
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/iso2022jp3.vtt10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/large-timestamp.vtt5
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/line-position-bad.vtt30
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/line-position.vtt37
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/markup-bad.vtt22
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/markup.vtt22
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/metadata-area.vtt14
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/metadata.vtt38
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/missed-cues.vtt31
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/no-newline-at-eof.vtt6
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/no-timings.vtt13
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/no-webvtt.vtt10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/positioning-bad.vtt39
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/positioning-ltr.vtt21
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/positioning.vtt21
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/settings-bad-separation.vtt20
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/settings.vtt18
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/simple-captions.vtt17
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/sorted-dispatch.vtt34
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timestamp-bad.vtt17
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timestamp.vtt14
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-hour-error.vtt22
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-hour.vtt14
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-no-hour-errors.vtt22
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-no-hour.vtt18
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-whitespace.vtt51
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/track.de.vtt4
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/track.en.vtt4
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/track.fr.vtt4
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/track.vtt4
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/unsupported-markup.vtt23
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/utf8.vtt10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/valign-bad.vtt17
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/valign-ltr.vtt20
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/valign.vtt20
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/voice-bad.vtt17
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/voice.vtt15
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/vp8-vorbis-webvtt.webmbin0 -> 143662 bytes
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/webvtt-file.vtt9
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/webvtt-rubbish.vtt10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/src-clear-cues.html52
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/src-empty-string.html21
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-active-cues.html42
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-add-remove-cue.html92
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-add-track.html34
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-addtrack-kind.html25
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-api-texttracks.html36
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-change-event.html21
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-css-cue-pseudo-class.html12
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-empty.html19
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-inline.html16
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-mutable-fragment.html85
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-mutable.html99
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-negative-duration.html30
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-negative-timestamp-events.html32
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-negative-timestamp.html42
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-order.html83
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-after-controls-added-ref.html31
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-after-controls-added.html37
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-after-controls-removed-ref.html29
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-after-controls-removed.html34
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-empty-cue.html16
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-line-doesnt-fit-ref.html32
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-line-doesnt-fit.html32
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-transformed-video-ref.html35
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-transformed-video.html28
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-cuechange-dynamically-created-track-element.html28
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-cuechange.html41
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-enter-exit.html44
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-enter-seeking.html38
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-missed.html59
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-pause-on-exit.html35
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-seeking.html31
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-sorted-before-dispatch.html48
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-data-url.html30
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-default-attribute.html26
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-delete-during-setup.html29
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-disabled-addcue.html33
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-disabled.html28
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-element-dom-change.html16
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-aborted-load.html19
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change-error.html86
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change.html55
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-helpers.js83
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-id.html25
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-insert-after-load.html14
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-large-timestamp.html19
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-load-error-readyState.html15
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-load-from-element-readyState.html15
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-load-from-src-readyState.html20
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-mode-disabled.html34
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-mode-not-changed-by-new-track.html74
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-mode-triggers-loading.html37
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-mode.html76
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-node-add-remove.html36
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-active-cue.html35
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-by-setting-innerHTML.html31
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-insert-ready-state.html38
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-quickly.html14
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-track-inband.html79
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-track.html39
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-selection-metadata.html33
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-selection-task-order.html36
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-text-track-cue-list.html29
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-texttracks.html44
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-align-positioning.html52
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-align-text-line-position.html54
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-alignment.html31
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-blank-lines.html26
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-bom.html34
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-class-markup.html56
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-identifiers.html27
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-no-id.html19
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-recovery.html19
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-size-align.html26
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-size.html26
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-degenerate-cues.html16
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-empty-cue.html10
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-entities.html42
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-header-comment.html50
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-interspersed-non-cue.html15
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-line-position.html58
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-magic-header.html57
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-markup.html90
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-newlines.html26
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-no-timings.html17
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-non-snap-to-lines-ref.html29
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-non-snap-to-lines.html24
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-positioning.html35
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-settings.html28
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timestamp.html36
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-hour.html61
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-no-hours.html67
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-whitespace.html25
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-two-cue-layout-after-first-end-ref.html25
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-two-cue-layout-after-first-end.html26
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-unsupported-markup.html37
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-utf8.html57
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-valign.html28
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-voice.html54
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/vtt-cue-float-precision.html28
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/user-interface/muted.html169
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/video_controls_present-manual.html14
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/video_loop_base.html40
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/video_muted_overriding_volume-manual.html21
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/video_muted_present-manual.html20
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/video_volume_check.html58
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/video_volume_loudest-manual.html21
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/video_volume_silent-manual.html21
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/volume_nonfinite.html18
403 files changed, 12415 insertions, 0 deletions
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/audio_controls_present-manual.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/audio_controls_present-manual.html
new file mode 100644
index 0000000000..38faa4d00a
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/audio_controls_present-manual.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Audio Test: audio_controls_present.html</title>
+ <link rel="author" title="Intel" href="http://www.intel.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-media-controls" />
+ <meta name="flags" content="" />
+ <meta name="assert" content="Check if the controls attribute is present in the audio element that expecting the user agent exposes a controller user interface" />
+ </head>
+ <body>
+ <p>Test passes if a controller user interface appears below and the text 'The user agent doesn't support media element.' does not appear anywhere on this page</p>
+ <audio id="m" controls>The user agent doesn't support media element.</audio>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/audio_loop_base.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/audio_loop_base.html
new file mode 100644
index 0000000000..418e1b19c3
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/audio_loop_base.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Audio Test: audio_loop_base</title>
+ <link rel="author" title="Intel" href="http://www.intel.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-media-loop" />
+ <meta name="flags" content="" />
+ <meta name="assert" content="Check if audio.loop is set to true that expecting the seeking event is fired more than once" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <audio id="m" controls>The user agent doesn't support media element.</audio>
+ <script type="text/javascript">
+ var media = document.getElementById("m");
+ var name = document.getElementsByName("assert")[0].content;
+ var t = async_test(name);
+
+ var looped = false;
+
+ function startTest() {
+ if (looped) {
+ t.step(function() {
+ assert_true(true, "looped");
+ });
+ t.done();
+ media.pause();
+ }
+
+ looped = true;
+ }
+
+ media.addEventListener("error", t.unreached_func());
+ media.addEventListener("seeking", startTest, false);
+ media.loop = true;
+ media.src = getAudioURI("/media/sound_0") + "?" + new Date() + Math.random();
+ media.play();
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/audio_loop_seek_to_eos.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/audio_loop_seek_to_eos.html
new file mode 100644
index 0000000000..01a2d4bea9
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/audio_loop_seek_to_eos.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Seeking to the end of looping audio</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<audio id="a" controls loop></audio>
+<script type="text/javascript">
+
+promise_test(async t => {
+ const a = document.getElementById("a");
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+ await a.play();
+
+ // Seek to the end of audio (EOS). However, as audio is looping, it should
+ // keep playing after seeking.
+ a.currentTime = a.duration;
+ await new Promise(r => a.onseeked = r);
+ await new Promise(r => a.ontimeupdate = r);
+ assert_false(a.paused);
+} , "seeking to the end of looping audio");
+
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/audio_muted_overriding_volume-manual.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/audio_muted_overriding_volume-manual.html
new file mode 100644
index 0000000000..cc1892ce89
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/audio_muted_overriding_volume-manual.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Audio Test: audio_muted_overriding_volume</title>
+ <link rel="author" title="Intel" href="http://www.intel.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-media-muted" />
+ <meta name="flags" content="" />
+ <meta name="assert" content="Check if the muted attribute is present in the audio element with volume is set to loudest that expecting the user hears no sound" />
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p>Test passes if the audio is playing without sound output and the text 'The user agent doesn't support media element.' does not appear anywhere on this page</p>
+ <audio id="m" controls muted>The user agent doesn't support media element.</audio>
+ <script type="text/javascript">
+ var media = document.getElementById("m");
+ media.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+ media.volume = 1.0;
+ media.play();
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/audio_muted_present-manual.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/audio_muted_present-manual.html
new file mode 100644
index 0000000000..16d6f07eed
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/audio_muted_present-manual.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Audio Test: audio_muted_present</title>
+ <link rel="author" title="Intel" href="http://www.intel.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-media-muted" />
+ <meta name="flags" content="" />
+ <meta name="assert" content="Check if the muted attribute is present in the audio element that expecting the user hears no sound" />
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p>Test passes if the audio is playing without sound output and the text 'The user agent doesn't support media element.' does not appear anywhere on this page</p>
+ <audio id="m" controls muted>The user agent doesn't support media element.</audio>
+ <script type="text/javascript">
+ var media = document.getElementById("m");
+ media.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+ media.play();
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/audio_volume_check.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/audio_volume_check.html
new file mode 100644
index 0000000000..b467c702a7
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/audio_volume_check.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Audio Test: audio_volume_check</title>
+ <link rel="author" title="Intel" href="http://www.intel.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-media-volume" />
+ <meta name="flags" content="" />
+ <meta name="assert" content="Check that audio.volume returns the value of the muted content attribute" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <audio id="m">The user agent doesn't support media element.</audio>
+ <script type="text/javascript">
+ var media = document.getElementById("m");
+ var VOLUME = {
+ 'SILENT' : 0.0,
+ 'NORMAL' : 0.5,
+ 'LOUDEST' : 1.0,
+ 'LOWER' : -1.1,
+ 'UPPER' : 1.1,
+ };
+
+ test(function() {
+ assert_false(media.volume < VOLUME.SILENT || media.volume > VOLUME.LOUDEST, "media.volume outside the range 0.0 to 1.0 inclusive");
+ }, "Check if the intial value of the audio.volume is in the range 0.0 to 1.0 inclusive");
+
+ function volume_setting(vol, name)
+ {
+ if (vol < VOLUME.SILENT || vol > VOLUME.LOUDEST) {
+ try {
+ media.volume = vol;
+ test(function() {
+ assert_true(false, "media.volume setting exception");
+ }, name);
+ } catch(e) {
+ test(function() {
+ // 1 should be e.IndexSizeError or e.INDEX_SIZE_ERR in previous spec
+ assert_equals(e.code, 1, "media.volume setting exception");
+ }, name);
+ }
+ } else {
+ media.volume = vol;
+ test(function() {
+ assert_equals(media.volume, vol, "media.volume new value");
+ }, name);
+ }
+ }
+
+ volume_setting(VOLUME.NORMAL, "Check if audio.volume is able to set to new value in the range 0.0 to 1.0");
+ volume_setting(VOLUME.SILENT, "Check if media.volume is able to set to new value 0.0 as silent");
+ volume_setting(VOLUME.LOUDEST, "Check if media.volume is able to set to new value 1.0 as loudest");
+ volume_setting(VOLUME.LOWER, "Check if media.volume is set to new value less than 0.0 that expecting an IndexSizeError exception is to be thrown");
+ volume_setting(VOLUME.UPPER, "Check if audio.volume is set to new value greater than 1.0 that expecting an IndexSizeError exception is to be thrown");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/audio_volume_loudest-manual.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/audio_volume_loudest-manual.html
new file mode 100644
index 0000000000..a623e8f5c2
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/audio_volume_loudest-manual.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Audio Test: audio_volume_loudest</title>
+ <link rel="author" title="Intel" href="http://www.intel.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-media-volume" />
+ <meta name="flags" content="" />
+ <meta name="assert" content="Check if the volume attribute is set to 1.0 as loudest in the audio element that expecting the user hears sound loudly" />
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p>Test passes if the audio is playing with sound heard and the text 'The user agent doesn't support media element.' does not appear anywhere on this page</p>
+ <audio id="m" controls>The user agent doesn't support media element.</audio>
+ <script type="text/javascript">
+ var media = document.getElementById("m");
+ media.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+ media.volume = 1.0;
+ media.play();
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/audio_volume_silent-manual.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/audio_volume_silent-manual.html
new file mode 100644
index 0000000000..257bd46289
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/audio_volume_silent-manual.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Audio Test: audio_volume_silent</title>
+ <link rel="author" title="Intel" href="http://www.intel.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-media-volume" />
+ <meta name="flags" content="" />
+ <meta name="assert" content="Check if the volume attribute is set to 0.0 as silent in the audio element that expecting the user hears no sound" />
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p>Test passes if the audio is playing without sound heard and the text 'The user agent doesn't support media element.' does not appear anywhere on this page</p>
+ <audio id="m" controls volume=0.0>The user agent doesn't support media element.</audio>
+ <script type="text/javascript">
+ var media = document.getElementById("m");
+ media.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+ media.volume = 0.0;
+ media.play();
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html
new file mode 100644
index 0000000000..6f11f8995b
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<body>
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src=/resources/testdriver.js></script>
+ <script src=/resources/testdriver-vendor.js></script>
+ <script src=/common/media.js></script>
+ <script src=/feature-policy/resources/featurepolicy.js></script>
+ <script src=/feature-policy/resources/autoplay.js></script>
+ <script>
+ 'use strict';
+ const relative_path = '/feature-policy/resources/feature-policy-autoplay.html';
+ const base_src = '/feature-policy/resources/redirect-on-load.html#';
+ const same_origin_src = base_src + relative_path;
+ const cross_origin_src = base_src + 'https://{{domains[www]}}:{{ports[https][0]}}' +
+ relative_path;
+ const header = 'Feature-Policy allow="autoplay"';
+
+ async_test(t => {
+ simulateGesture(t, () => {
+ test_feature_availability(
+ 'autoplay', t, same_origin_src,
+ expect_feature_available_default, 'autoplay');
+ });
+ }, header + ' allows same-origin navigation in an iframe.');
+
+ async_test(t => {
+ simulateGesture(t, () => {
+ test_feature_availability(
+ 'autoplay', t, cross_origin_src,
+ expect_feature_unavailable_default, 'autoplay');
+ });
+ }, header + ' disallows cross-origin navigation in an iframe.');
+ </script>
+</body>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-allowed-by-feature-policy-attribute.https.sub.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-allowed-by-feature-policy-attribute.https.sub.html
new file mode 100644
index 0000000000..59b33d7c4d
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-allowed-by-feature-policy-attribute.https.sub.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<body>
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src=/resources/testdriver.js></script>
+ <script src=/resources/testdriver-vendor.js></script>
+ <script src=/common/media.js></script>
+ <script src=/feature-policy/resources/featurepolicy.js></script>
+ <script src=/feature-policy/resources/autoplay.js></script>
+ <script>
+ 'use strict';
+ const same_origin_src = '/feature-policy/resources/feature-policy-autoplay.html';
+ const cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' +
+ same_origin_src;
+ const feature_name = 'Feature policy "autoplay"';
+ const header = 'allow="autoplay" attribute';
+
+ async_test(t => {
+ simulateGesture(t, () => {
+ test_feature_availability(
+ 'autoplay', t, same_origin_src,
+ expect_feature_available_default, 'autoplay');
+ });
+ }, feature_name + ' can be enabled in same-origin iframe using ' + header);
+
+ async_test(t => {
+ simulateGesture(t, () => {
+ test_feature_availability(
+ 'autoplay', t, cross_origin_src,
+ expect_feature_available_default, 'autoplay');
+ });
+ }, feature_name + ' can be enabled in cross-origin iframe using ' + header);
+ </script>
+</body>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-allowed-by-feature-policy.https.sub.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-allowed-by-feature-policy.https.sub.html
new file mode 100644
index 0000000000..63479c0cb6
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-allowed-by-feature-policy.https.sub.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<body>
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src=/resources/testdriver.js></script>
+ <script src=/resources/testdriver-vendor.js></script>
+ <script src=/common/media.js></script>
+ <script src=/feature-policy/resources/featurepolicy.js></script>
+ <script src=/feature-policy/resources/autoplay.js></script>
+ <script>
+ 'use strict';
+ const same_origin_src = '/feature-policy/resources/feature-policy-autoplay.html';
+ const cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' +
+ same_origin_src;
+ const header = 'Feature-Policy header: autoplay *';
+
+ async_test(t => {
+ simulateGesture(t, () => {
+ isAutoplayAllowed().then(t.step_func_done((result) => {
+ assert_true(result);
+ }));
+ });
+ }, header + ' allows the top-level document.');
+
+ async_test(t => {
+ simulateGesture(t, () => {
+ test_feature_availability('autoplay', t, same_origin_src,
+ expect_feature_available_default);
+ });
+ }, header + ' allows same-origin iframes.');
+
+ async_test(t => {
+ simulateGesture(t, () => {
+ test_feature_availability('autoplay', t, cross_origin_src,
+ expect_feature_available_default);
+ });
+ }, header + ' allows cross-origin iframes.');
+ </script>
+</body>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-allowed-by-feature-policy.https.sub.html.headers b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-allowed-by-feature-policy.https.sub.html.headers
new file mode 100644
index 0000000000..08461fadc2
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-allowed-by-feature-policy.https.sub.html.headers
@@ -0,0 +1 @@
+Feature-Policy: autoplay *
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-default-feature-policy.https.sub.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-default-feature-policy.https.sub.html
new file mode 100644
index 0000000000..763073e437
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-default-feature-policy.https.sub.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<body>
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src=/resources/testdriver.js></script>
+ <script src=/resources/testdriver-vendor.js></script>
+ <script src=/common/media.js></script>
+ <script src=/feature-policy/resources/featurepolicy.js></script>
+ <script src=/feature-policy/resources/autoplay.js></script>
+ <script>
+ 'use strict';
+ const same_origin_src = '/feature-policy/resources/feature-policy-autoplay.html';
+ const cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' +
+ same_origin_src;
+ const header = 'Default "autoplay" feature policy ["self"]';
+
+ async_test(t => {
+ simulateGesture(t, () => {
+ isAutoplayAllowed().then(t.step_func_done((result) => {
+ assert_true(result);
+ }));
+ });
+ }, header + ' allows the top-level document.');
+
+ async_test(t => {
+ simulateGesture(t, () => {
+ test_feature_availability('autoplay', t, same_origin_src,
+ expect_feature_available_default);
+ });
+ }, header + ' allows same-origin iframes.');
+
+ async_test(t => {
+ simulateGesture(t, () => {
+ test_feature_availability('autoplay', t, cross_origin_src,
+ expect_feature_unavailable_default,);
+ });
+ }, header + ' disallows cross-origin iframes.');
+ </script>
+</body>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-disabled-by-feature-policy.https.sub.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-disabled-by-feature-policy.https.sub.html
new file mode 100644
index 0000000000..3dd3afbf77
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-disabled-by-feature-policy.https.sub.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<body>
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src=/resources/testdriver.js></script>
+ <script src=/resources/testdriver-vendor.js></script>
+ <script src=/common/media.js></script>
+ <script src=/feature-policy/resources/featurepolicy.js></script>
+ <script src=/feature-policy/resources/autoplay.js></script>
+ <script>
+ 'use strict';
+ const same_origin_src = '/feature-policy/resources/feature-policy-autoplay.html';
+ const cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' +
+ same_origin_src;
+ const header = 'Feature-Policy header: autoplay "none"';
+
+ async_test(t => {
+ simulateGesture(t, () => {
+ isAutoplayAllowed().then(t.step_func_done((result) => {
+ assert_true(result);
+ }));
+ });
+ }, header + ' has no effect on the top level document.');
+
+ async_test(t => {
+ simulateGesture(t, () => {
+ test_feature_availability('autoplay', t, same_origin_src,
+ expect_feature_unavailable_default);
+ });
+ }, header + ' disallows same-origin iframes.');
+
+ async_test(t => {
+ simulateGesture(t, () => {
+ test_feature_availability('autoplay', t, cross_origin_src,
+ expect_feature_unavailable_default,);
+ });
+ }, header + ' disallows cross-origin iframes.');
+ </script>
+</body>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-disabled-by-feature-policy.https.sub.html.headers b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-disabled-by-feature-policy.https.sub.html.headers
new file mode 100644
index 0000000000..69ce436270
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-disabled-by-feature-policy.https.sub.html.headers
@@ -0,0 +1 @@
+Feature-Policy: autoplay 'none'
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-supported-by-feature-policy.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-supported-by-feature-policy.html
new file mode 100644
index 0000000000..af4de6bf89
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-supported-by-feature-policy.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<title>Test that autoplay is advertised in the feature list</title>
+<link rel="help" href="https://w3c.github.io/webappsec-feature-policy/#dom-featurepolicy-features">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/infrastructure.html#policy-controlled-features">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(() => {
+ assert_in_array('autoplay', document.featurePolicy.features());
+}, 'document.featurePolicy.features should advertise autoplay.');
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-with-broken-track.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-with-broken-track.html
new file mode 100644
index 0000000000..f687edf198
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/autoplay-with-broken-track.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/media.html#text-track-model">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<div id="log"></div>
+<script>
+// Media elements have a "list of pending text tracks" which should be populated
+// with text tracks with readyState "loading". When the text track src is
+// invalid or points to a non-existent resource, it shouldn't be possible to
+// block the media element's readyState indefinitely.
+function t(trackSrc) {
+ const track = document.createElement('track');
+ track.src = trackSrc;
+ track.default = true;
+ async_test(t => {
+ const video = document.createElement('video');
+ video.autoplay = true;
+ video.controls = true; // for visual inspection, not part of test
+ video.src = getVideoURI('/media/movie_5');
+ video.appendChild(track);
+ document.body.appendChild(video);
+ // The playing event isn't used because it's fired in Safari even when the
+ // playback doesn't actually start.
+ video.ontimeupdate = t.step_func(() => {
+ if (video.currentTime > 0)
+ t.done();
+ });
+ }, `<video autoplay> with ${track.outerHTML} child`);
+}
+t("invalid://url");
+t("404");
+t("");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/controlsList.tentative.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/controlsList.tentative.html
new file mode 100644
index 0000000000..11144839ee
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/controlsList.tentative.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<title>Test controlsList attribute</title>
+<link rel="help" href="https://github.com/whatwg/html/pull/6715">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+const allowedValues = [
+ "nodownload",
+ "nofullscreen",
+ "noplaybackrate",
+ "noremoteplayback",
+];
+
+function testControlsList(tagName) {
+ const element = document.createElement(tagName);
+
+ // Test that supports() is returning true for allowed values.
+ for (const value of allowedValues) {
+ assert_true(
+ element.controlsList.supports(value),
+ `tag = ${element.tagName}, value = ${value} must be supported`
+ );
+ }
+}
+
+["audio", "video"].forEach((tagName) => {
+ test(
+ () => testControlsList(tagName),
+ `Test controlsList allowed values for <${tagName}>`
+ );
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/error-codes/error.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/error-codes/error.html
new file mode 100644
index 0000000000..42d86e49b0
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/error-codes/error.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<title>error</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<div id="log"></div>
+<script>
+function error_test(tagName, src) {
+ test(function() {
+ assert_equals(document.createElement(tagName).error, null);
+ }, tagName + '.error initial value');
+
+ async_test(function(t) {
+ var e = document.createElement(tagName);
+ e.src = src;
+ e.onerror = t.unreached_func();
+ e.onloadeddata = t.step_func(function() {
+ assert_equals(e.error, null);
+ t.done();
+ });
+ }, tagName + '.error after successful load');
+
+ // TODO: MEDIA_ERR_ABORTED, MEDIA_ERR_NETWORK, MEDIA_ERR_DECODE
+
+ async_test(function(t) {
+ var e = document.createElement(tagName);
+ e.src = '';
+ e.onerror = t.step_func(function() {
+ assert_true(e.error instanceof MediaError);
+ assert_equals(e.error.code, 4);
+ assert_equals(e.error.code, e.error.MEDIA_ERR_SRC_NOT_SUPPORTED);
+ assert_equals(typeof e.error.message, 'string', 'error.message type');
+ t.done();
+ });
+ }, tagName + '.error after setting src to the empty string');
+}
+
+error_test('audio', getAudioURI('/media/sound_5'));
+error_test('video', getVideoURI('/media/movie_5'));
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_canplay.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_canplay.html
new file mode 100644
index 0000000000..e5c632bc17
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_canplay.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - canplay</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("setting src attribute on autoplay audio should trigger canplay event");
+ var a = document.getElementById("a");
+ a.addEventListener("error", t.unreached_func());
+ a.addEventListener("canplay", t.step_func(function() {
+ t.done();
+ a.pause();
+ }), false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - canplay");
+
+test(function() {
+ var t = async_test("setting src attribute on autoplay video should trigger canplay event");
+ var v = document.getElementById("v");
+ v.addEventListener("error", t.unreached_func());
+ v.addEventListener("canplay", t.step_func(function() {
+ t.done();
+ v.pause();
+ }), false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - canplay");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_canplay_noautoplay.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_canplay_noautoplay.html
new file mode 100644
index 0000000000..b43f8d052a
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_canplay_noautoplay.html
@@ -0,0 +1,34 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - canplay</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" controls>
+ </audio>
+ <video id="v" controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function () {
+ var t = async_test("setting src attribute on non-autoplay audio should trigger canplay event");
+ var a = document.getElementById("a");
+ a.addEventListener("error", t.unreached_func());
+ a.addEventListener("canplay", t.step_func_done(), false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - canplay");
+
+test(function () {
+ var t = async_test("setting src attribute on non-autoplay video should trigger canplay event");
+ var v = document.getElementById("v");
+ v.addEventListener("error", t.unreached_func());
+ v.addEventListener("canplay", t.step_func_done(), false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - canplay");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_canplaythrough.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_canplaythrough.html
new file mode 100644
index 0000000000..b0895a97c2
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_canplaythrough.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - canplaythrough</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("setting src attribute on autoplay audio should trigger canplaythrough event");
+ var a = document.getElementById("a");
+ a.addEventListener("error", t.unreached_func());
+ a.addEventListener("canplaythrough", t.step_func(function() {
+ t.done();
+ a.pause();
+ }), false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - canplaythrough");
+
+test(function() {
+ var t = async_test("setting src attribute on autoplay video should trigger canplaythrough event");
+ var v = document.getElementById("v");
+ v.addEventListener("error", t.unreached_func());
+ v.addEventListener("canplaythrough", t.step_func(function() {
+ t.done();
+ v.pause();
+ }), false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - canplaythrough");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_canplaythrough_noautoplay.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_canplaythrough_noautoplay.html
new file mode 100644
index 0000000000..195b464f01
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_canplaythrough_noautoplay.html
@@ -0,0 +1,34 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - canplaythrough</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" controls>
+ </audio>
+ <video id="v" controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("setting src attribute on non-autoplay audio should trigger canplaythrough event");
+ var a = document.getElementById("a");
+ a.addEventListener("error", t.unreached_func());
+ a.addEventListener("canplaythrough", t.step_func_done(), false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - canplaythrough");
+
+test(function() {
+ var t = async_test("setting src attribute on non-autoplay video should trigger canplaythrough event");
+ var v = document.getElementById("v");
+ v.addEventListener("error", t.unreached_func());
+ v.addEventListener("canplaythrough", t.step_func_done(), false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - canplaythrough");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_loadeddata.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_loadeddata.html
new file mode 100644
index 0000000000..f502c595e6
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_loadeddata.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - loadeddata</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("setting src attribute on autoplay audio should trigger loadeddata event");
+ var a = document.getElementById("a");
+ a.addEventListener("error", t.unreached_func());
+ a.addEventListener("loadeddata", t.step_func(function() {
+ t.done();
+ a.pause();
+ }), false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - loadeddata");
+
+test(function() {
+ var t = async_test("setting src attribute on autoplay video should trigger loadeddata event");
+ var v = document.getElementById("v");
+ v.addEventListener("error", t.unreached_func());
+ v.addEventListener("loadeddata", t.step_func(function() {
+ t.done();
+ v.pause();
+ }), false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - loadeddata");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_loadeddata_noautoplay.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_loadeddata_noautoplay.html
new file mode 100644
index 0000000000..08b2f2f86e
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_loadeddata_noautoplay.html
@@ -0,0 +1,34 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - loadeddata</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" controls>
+ </audio>
+ <video id="v" controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("setting src attribute on non-autoplay audio should trigger loadeddata event");
+ var a = document.getElementById("a");
+ a.addEventListener("error", t.unreached_func());
+ a.addEventListener("loadeddata", t.step_func_done(), false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - loadeddata");
+
+test(function() {
+ var t = async_test("setting src attribute on non-autoplay video should trigger loadeddata event");
+ var v = document.getElementById("v");
+ v.addEventListener("error", t.unreached_func());
+ v.addEventListener("loadeddata", t.step_func_done(), false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - loadeddata");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_loadedmetadata.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_loadedmetadata.html
new file mode 100644
index 0000000000..5a0731e811
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_loadedmetadata.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - loadedmetadata</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("setting src attribute on autoplay audio should trigger loadedmetadata event");
+ var a = document.getElementById("a");
+ a.addEventListener("error", t.unreached_func());
+ a.addEventListener("loadedmetadata", t.step_func(function() {
+ t.done();
+ a.pause();
+ }));
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - loadedmetadata");
+
+test(function() {
+ var t = async_test("setting src attribute on autoplay video should trigger loadedmetadata event");
+ var v = document.getElementById("v");
+ v.addEventListener("error", t.unreached_func());
+ v.addEventListener("loadedmetadata", t.step_func(function() {
+ t.done();
+ v.pause();
+ }));
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - loadedmetadata");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_loadedmetadata_noautoplay.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_loadedmetadata_noautoplay.html
new file mode 100644
index 0000000000..b460317f8c
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_loadedmetadata_noautoplay.html
@@ -0,0 +1,34 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - loadedmetadata</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" controls>
+ </audio>
+ <video id="v" controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("setting src attribute on non-autoplay audio should trigger loadedmetadata event");
+ var a = document.getElementById("a");
+ a.addEventListener("error", t.unreached_func());
+ a.addEventListener("loadedmetadata", t.step_func_done(), false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - loadedmetadata");
+
+test(function() {
+ var t = async_test("setting src attribute on non-autoplay video should trigger loadedmetadata event");
+ var v = document.getElementById("v");
+ v.addEventListener("error", t.unreached_func());
+ v.addEventListener("loadedmetadata", t.step_func_done(), false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events, loadedmetadata");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_loadstart.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_loadstart.html
new file mode 100644
index 0000000000..192821a961
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_loadstart.html
@@ -0,0 +1,38 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - loadstart</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("setting src attribute on autoplay audio should trigger loadstart event");
+ var a = document.getElementById("a");
+ a.addEventListener("loadstart", function() {
+ t.done();
+ a.pause();
+ }, false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - loadstart");
+
+test(function() {
+ var t = async_test("setting src attribute on autoplay video should trigger loadstart event");
+ var v = document.getElementById("v");
+ v.addEventListener("loadstart", function() {
+ t.done();
+ v.pause();
+ }, false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - loadstart");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_loadstart_noautoplay.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_loadstart_noautoplay.html
new file mode 100644
index 0000000000..10af32afcb
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_loadstart_noautoplay.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - loadstart</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" controls>
+ </audio>
+ <video id="v" controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("setting src attribute on non-autoplay audio should trigger loadstart event");
+ var a = document.getElementById("a");
+ a.addEventListener("loadstart", function() {
+ t.done();
+ }, false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - loadstart");
+
+test(function() {
+ var t = async_test("setting src attribute on non-autoplay video should trigger loadstart event");
+ var v = document.getElementById("v");
+ v.addEventListener("loadstart", function() {
+ t.done();
+ }, false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - loadstart");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_order_canplay_canplaythrough.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_order_canplay_canplaythrough.html
new file mode 100644
index 0000000000..e1bae90ed0
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_order_canplay_canplaythrough.html
@@ -0,0 +1,50 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - canplay, then canplaythrough</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("setting src attribute on autoplay audio should trigger canplay then canplaythrough event");
+ var a = document.getElementById("a");
+ var found_canplay = false;
+ a.addEventListener("error", t.unreached_func());
+ a.addEventListener("canplay", t.step_func(function() {
+ found_canplay = true;
+ }));
+ a.addEventListener("canplaythrough", t.step_func(function() {
+ assert_true(found_canplay);
+ t.done();
+ a.pause();
+ }), false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - canplay, then canplaythrough");
+
+test(function() {
+ var t = async_test("setting src attribute on autoplay video should trigger canplay then canplaythrough event");
+ var v = document.getElementById("v");
+ var found_canplay = false;
+ v.addEventListener("error", t.unreached_func());
+ v.addEventListener("canplay", t.step_func(function() {
+ found_canplay = true;
+ }));
+ v.addEventListener("canplaythrough", t.step_func(function() {
+ assert_true(found_canplay);
+ t.done();
+ v.pause();
+ }), false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - canplay, then canplaythrough");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_order_canplay_playing.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_order_canplay_playing.html
new file mode 100644
index 0000000000..3571e5151c
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_order_canplay_playing.html
@@ -0,0 +1,50 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - canplay, then playing</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("setting src attribute on autoplay audio should trigger canplay then playing event");
+ var a = document.getElementById("a");
+ var found_canplay = false;
+ a.addEventListener("error", t.unreached_func());
+ a.addEventListener("canplay", t.step_func(function() {
+ found_canplay = true;
+ }));
+ a.addEventListener("playing", t.step_func(function() {
+ assert_true(found_canplay);
+ t.done();
+ a.pause();
+ }), false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - canplay, then playing");
+
+test(function() {
+ var t = async_test("setting src attribute on autoplay video should trigger canplay then playing event");
+ var v = document.getElementById("v");
+ var found_canplay = false;
+ v.addEventListener("error", t.unreached_func());
+ v.addEventListener("canplay", t.step_func(function() {
+ found_canplay = true;
+ }));
+ v.addEventListener("playing", t.step_func(function() {
+ assert_true(found_canplay);
+ t.done();
+ v.pause();
+ }), false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - canplay, then playing");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_order_loadedmetadata_loadeddata.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_order_loadedmetadata_loadeddata.html
new file mode 100644
index 0000000000..71aeca50c1
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_order_loadedmetadata_loadeddata.html
@@ -0,0 +1,50 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - loadedmetadata, then loadeddata</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("setting src attribute on autoplay audio should trigger loadedmetadata then loadeddata event");
+ var a = document.getElementById("a");
+ var found_loadedmetadata = false;
+ a.addEventListener("error", t.unreached_func());
+ a.addEventListener("loadedmetadata", t.step_func(function() {
+ found_loadedmetadata = true;
+ }));
+ a.addEventListener("loadeddata", t.step_func(function() {
+ assert_true(found_loadedmetadata);
+ t.done();
+ a.pause();
+ }), false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - loadedmetadata, then loadeddata");
+
+test(function() {
+ var t = async_test("setting src attribute on autoplay video should trigger loadedmetadata then loadeddata event");
+ var v = document.getElementById("v");
+ var found_loadedmetadata = false;
+ v.addEventListener("error", t.unreached_func());
+ v.addEventListener("loadedmetadata", t.step_func(function() {
+ found_loadedmetadata = true;
+ }));
+ v.addEventListener("loadeddata", t.step_func(function() {
+ assert_true(found_loadedmetadata);
+ t.done();
+ v.pause();
+ }), false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - loadedmetadata, then loadeddata");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_order_loadstart_progress.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_order_loadstart_progress.html
new file mode 100644
index 0000000000..c6e1dbe07a
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_order_loadstart_progress.html
@@ -0,0 +1,50 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - loadstart, then progress</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("setting src attribute on autoplay audio should trigger loadstart then progress event");
+ var a = document.getElementById("a");
+ var found_loadstart = false;
+ a.addEventListener("error", t.unreached_func());
+ a.addEventListener("loadstart", t.step_func(function() {
+ found_loadstart = true;
+ }));
+ a.addEventListener("progress", t.step_func(function() {
+ assert_true(found_loadstart);
+ t.done();
+ a.pause();
+ }), false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - loadstart, then progress");
+
+test(function() {
+ var t = async_test("setting src attribute on autoplay video should trigger loadstart then progress event");
+ var v = document.getElementById("v");
+ var found_loadstart = false;
+ v.addEventListener("error", t.unreached_func());
+ v.addEventListener("loadstart", t.step_func(function() {
+ found_loadstart = true;
+ }));
+ v.addEventListener("progress", t.step_func(function() {
+ assert_true(found_loadstart);
+ t.done();
+ v.pause();
+ }), false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - loadstart, then progress");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_pause.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_pause.html
new file mode 100644
index 0000000000..841e124d5b
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_pause.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - pause</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("calling pause() on autoplay audio should trigger pause event");
+ var a = document.getElementById("a");
+ a.addEventListener("error", t.unreached_func());
+ a.addEventListener("pause", t.step_func_done(), false);
+ a.addEventListener("play", t.step_func(function() {
+ a.pause(); // pause right after play
+ }));
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - pause");
+
+test(function() {
+ var t = async_test("calling pause() on autoplay video should trigger pause event");
+ var v = document.getElementById("v");
+ v.addEventListener("error", t.unreached_func());
+ v.addEventListener("pause", t.step_func_done(), false);
+ v.addEventListener("play", t.step_func(function() {
+ v.pause(); // pause right after play
+ }));
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - pause");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_pause_noautoplay.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_pause_noautoplay.html
new file mode 100644
index 0000000000..c6d9d5920b
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_pause_noautoplay.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - pause</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" controls>
+ </audio>
+ <video id="v" controls>
+ </video>
+ <div id="log"></div>
+ <script>
+promise_test(function(t) {
+ var async_t = async_test("calling play() then pause() on non-autoplay audio should trigger pause event");
+ var a = document.getElementById("a");
+ a.addEventListener("pause", function() {
+ async_t.done();
+ }, false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+ var play_promise = a.play();
+ a.pause();
+ return promise_rejects_dom(t, "AbortError", play_promise, "pause() should reject all pending play Promises");
+}, "audio events - pause");
+
+promise_test(function(t) {
+ var async_t = async_test("calling play() then pause() on non-autoplay video should trigger pause event");
+ var v = document.getElementById("v");
+ v.addEventListener("pause", function() {
+ async_t.done();
+ }, false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+ var play_promise = v.play()
+ v.pause();
+ return promise_rejects_dom(t, "AbortError", play_promise, "pause() should reject all pending play Promises");
+}, "video events - pause");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_play.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_play.html
new file mode 100644
index 0000000000..f96c35113b
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_play.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - play</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("setting src attribute on autoplay audio should trigger play event");
+ var a = document.getElementById("a");
+ a.addEventListener("error", t.unreached_func());
+ a.addEventListener("play", t.step_func(function() {
+ t.done();
+ a.pause();
+ }), false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - play");
+
+test(function() {
+ var t = async_test("setting src attribute on autoplay video should trigger play event");
+ var v = document.getElementById("v");
+ v.addEventListener("error", t.unreached_func());
+ v.addEventListener("play", t.step_func(function() {
+ t.done();
+ v.pause();
+ }), false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - play");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_play_noautoplay.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_play_noautoplay.html
new file mode 100644
index 0000000000..0dff37c800
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_play_noautoplay.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - play</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" controls>
+ </audio>
+ <video id="v" controls>
+ </video>
+ <div id="log"></div>
+ <script>
+promise_test(function(t) {
+ var async_t = async_test("calling play() on audio should trigger play event");
+ var a = document.getElementById("a");
+ a.addEventListener("play", async_t.step_func(function() {
+ a.pause();
+ async_t.done();
+ }), false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+ return promise_rejects_dom(t, "AbortError", a.play(), "pause() should reject all pending play Promises");
+}, "audio events - play");
+
+promise_test(function(t) {
+ var async_t = async_test("calling play() on video should trigger play event");
+ var v = document.getElementById("v");
+ v.addEventListener("play", async_t.step_func(function() {
+ v.pause();
+ async_t.done();
+ }), false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+ return promise_rejects_dom(t, "AbortError", v.play(), "pause() should reject all pending play Promises");
+}, "video events - play");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_playing.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_playing.html
new file mode 100644
index 0000000000..18204c457a
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_playing.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - playing</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("setting src attribute on autoplay audio should trigger playing event");
+ var a = document.getElementById("a");
+ a.addEventListener("error", t.unreached_func());
+ a.addEventListener("playing", t.step_func(function() {
+ t.done();
+ a.pause();
+ }), false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - playing");
+
+test(function() {
+ var t = async_test("setting src attribute on autoplay video should trigger playing event");
+ var v = document.getElementById("v");
+ v.addEventListener("error", t.unreached_func());
+ v.addEventListener("playing", t.step_func(function() {
+ t.done();
+ v.pause();
+ }), false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - playing");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_playing_noautoplay.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_playing_noautoplay.html
new file mode 100644
index 0000000000..e9714d7ec5
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_playing_noautoplay.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - playing</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" controls>
+ </audio>
+ <video id="v" controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("calling play() on audio should trigger playing event");
+ var a = document.getElementById("a");
+ a.addEventListener("playing", function() {
+ t.done();
+ a.pause();
+ });
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+ a.play();
+}, "audio events - playing");
+
+test(function() {
+ var t = async_test("calling play() on video should trigger playing event");
+ var v = document.getElementById("v");
+ v.addEventListener("playing", function() {
+ t.done();
+ v.pause();
+ });
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+ v.play();
+}, "video events - playing");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_progress.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_progress.html
new file mode 100644
index 0000000000..ae4496c99f
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_progress.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - progress</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("setting src attribute on autoplay audio should trigger progress event");
+ var a = document.getElementById("a");
+ a.addEventListener("error", t.unreached_func());
+ a.addEventListener("progress", t.step_func(function() {
+ t.done();
+ a.pause();
+ }), false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - progress");
+
+test(function() {
+ var t = async_test("setting src attribute on autoplay video should trigger progress event");
+ var v = document.getElementById("v");
+ v.addEventListener("error", t.unreached_func());
+ v.addEventListener("progress", t.step_func(function() {
+ t.done();
+ v.pause();
+ }), false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - progress");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_progress_noautoplay.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_progress_noautoplay.html
new file mode 100644
index 0000000000..8b32448b9f
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_progress_noautoplay.html
@@ -0,0 +1,34 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - progress</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" controls>
+ </audio>
+ <video id="v" controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("setting src attribute on non-autoplay audio should trigger progress event");
+ var a = document.getElementById("a");
+ a.addEventListener("error", t.unreached_func());
+ a.addEventListener("progress", t.step_func_done(), false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - progress");
+
+test(function() {
+ var t = async_test("setting src attribute on non-autoplay video should trigger progress event");
+ var v = document.getElementById("v");
+ v.addEventListener("error", t.unreached_func());
+ v.addEventListener("progress", t.step_func_done(), false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - progress");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_timeupdate.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_timeupdate.html
new file mode 100644
index 0000000000..0909c864e3
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_timeupdate.html
@@ -0,0 +1,34 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - timeupdate</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+var ta = async_test("setting src attribute on a sufficiently long autoplay audio should trigger timeupdate event");
+var a = document.getElementById("a");
+a.addEventListener("timeupdate", function() {
+ ta.done();
+ a.pause();
+}, false);
+a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+
+var tv = async_test("setting src attribute on a sufficiently long autoplay video should trigger timeupdate event");
+var v = document.getElementById("v");
+v.addEventListener("timeupdate", function() {
+ tv.done();
+ v.pause();
+}, false);
+v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_timeupdate_noautoplay.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_timeupdate_noautoplay.html
new file mode 100644
index 0000000000..2738a3b4ac
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_timeupdate_noautoplay.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - timeupdate</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" controls>
+ </audio>
+ <video id="v" controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("calling play() on a sufficiently long audio should trigger timeupdate event");
+ var a = document.getElementById("a");
+ a.addEventListener("error", t.unreached_func());
+ a.addEventListener("timeupdate", t.step_func(function() {
+ t.done();
+ a.pause();
+ }), false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+ a.play();
+}, "audio events - timeupdate");
+
+test(function() {
+ var t = async_test("calling play() on a sufficiently long video should trigger timeupdate event");
+ var v = document.getElementById("v");
+ v.addEventListener("error", t.unreached_func());
+ v.addEventListener("timeupdate", t.step_func(function() {
+ t.done();
+ v.pause();
+ }), false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+ v.play();
+}, "video events - timeupdate");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_volumechange.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_volumechange.html
new file mode 100644
index 0000000000..3481947e87
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/event_volumechange.html
@@ -0,0 +1,72 @@
+<!doctype html>
+<title>volumechange event</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+function volumechange_test(tagName) {
+ async_test(function(t) {
+ var e = document.createElement(tagName);
+ assert_equals(e.volume, 1);
+ e.volume = 0.5;
+ assert_equals(e.volume, 0.5);
+ e.onvolumechange = t.step_func(function() {
+ assert_equals(e.volume, 0.5);
+ e.volume = 1;
+ assert_equals(e.volume, 1);
+ e.onvolumechange = t.step_func(function() {
+ assert_equals(e.volume, 1);
+ t.done();
+ });
+ });
+ }, "setting " + tagName + ".volume fires volumechange");
+
+ async_test(function(t) {
+ var e = document.createElement(tagName);
+ assert_false(e.muted);
+ e.muted = true;
+ assert_true(e.muted);
+ e.onvolumechange = t.step_func(function() {
+ assert_true(e.muted);
+ e.muted = false;
+ assert_false(e.muted);
+ e.onvolumechange = t.step_func(function() {
+ assert_false(e.muted);
+ t.done();
+ });
+ });
+ }, "setting " + tagName + ".muted fires volumechange");
+
+ async_test(function(t) {
+ var e = document.createElement(tagName);
+ e.volume = e.volume;
+ e.muted = e.muted;
+ e.onvolumechange = t.step_func(function() {
+ assert_unreached();
+ });
+ var e2 = document.createElement(tagName);
+ e2.muted = !e2.muted;
+ e2.onvolumechange = t.step_func(function() {
+ t.done();
+ });
+ }, "setting " + tagName + ".volume/muted to the same value does not fire volumechange");
+
+ async_test(function(t) {
+ var e = document.createElement(tagName);
+ e.muted = !e.muted;
+ e.volume = 1 - e.volume;
+ e.muted = !e.muted;
+ e.volume = 1 - e.volume;
+ var volumechange_count = 0;
+ e.onvolumechange = t.step_func(function() {
+ volumechange_count++;
+ if (volumechange_count == 4) {
+ t.done();
+ }
+ });
+ }, "setting " + tagName + ".volume/muted repeatedly fires volumechange repeatedly");
+}
+
+volumechange_test("audio");
+volumechange_test("video");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/historical.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/historical.html
new file mode 100644
index 0000000000..d7395632eb
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/historical.html
@@ -0,0 +1,56 @@
+<!doctype html>
+<title>Historical media element features should not be supported</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+function t(property, tagName) {
+ var tagNames = tagName ? [tagName] : ['audio', 'video'];
+ tagNames.forEach(function(tagName) {
+ test(function() {
+ assert_false(property in document.createElement(tagName));
+ }, tagName + '.' + property + ' should not be supported');
+ });
+}
+
+t('bufferingRate'); // added in r678, removed in r2872.
+t('start'); // added in r692, removed in r2401.
+t('end'); // added in r692, removed in r2401.
+t('loopStart'); // added in r692, removed in r2401.
+t('loopEnd'); // added in r692, removed in r2401.
+t('loopCount'); // added in r692, replaced with playCount in r1105.
+t('currentLoop'); // added in r692, removed in r2401.
+t('addCuePoint'); // added in r721, replaced with addCueRange in r1106.
+t('removeCuePoint'); // added in r721, replaced with removeCueRanges in r1106.
+t('playCount'); // added in r1105, removed in r2401.
+t('addCueRange'); // added in r1106, removed in r5070.
+t('removeCueRanges'); // added in r1106, removed in r5070.
+t('pixelratio', 'source'); // added in r1629, removed in r2493.
+t('bufferedBytes'); // added in r1630, removed in r2405.
+t('totalBytes'); // added in r1630, removed in r2405.
+t('bufferingThrottled'); // added in r1632, removed in r2872.
+t('autobuffer'); // added in r2855, replaced with preload in r4811.
+t('startTime'); // added in r3035, replaced with initialTime in r5310.
+t('startOffsetTime'); // added in r5310, replaced with startDate in r7045.
+t('initialTime'); // added in r5310, removed in r7046.
+t('audio', 'video'); // added in r5636, replaced with muted in r5991.
+t('startDate'); // added in r7045, replaced with getStartDate() in r8113.
+t('mozSrcObject'); // never in the spec
+t('mozPreservesPitch'); // prefixed version should be removed.
+t('webkitPreservesPitch'); // prefixed version should be removed.
+
+// TextTrackCue constructor: added in r5723, removed in r7742.
+test(function() {
+ assert_throws_js(TypeError, function() {
+ new TextTrackCue(0, 0, '');
+ });
+}, 'TextTrackCue constructor should not be supported');
+
+// added in https://github.com/whatwg/html/commit/66c5b32240c202c74f475872e7ea2cd163777b4a
+// removed in https://github.com/whatwg/html/commit/634698e70ea4586d58c989fa7d2cbfcad20d33e6
+t('mediaGroup');
+t('controller');
+test(function() {
+ assert_false('MediaController' in window);
+}, 'MediaController constructor should not be supported');
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/addTextTrack.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/addTextTrack.html
new file mode 100644
index 0000000000..0e1a48f78a
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/addTextTrack.html
@@ -0,0 +1,116 @@
+<!doctype html>
+<title>HTMLMediaElement.addTextTrack</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+var video = document.createElement('video');
+test(function(){
+ assert_throws_js(TypeError, function(){
+ video.addTextTrack('foo');
+ });
+ assert_throws_js(TypeError, function(){
+ video.addTextTrack(undefined);
+ });
+ assert_throws_js(TypeError, function(){
+ video.addTextTrack(null);
+ });
+}, document.title + ' bogus first arg');
+
+test(function(){
+ assert_throws_js(TypeError, function(){
+ video.addTextTrack('SUBTITLES');
+ });
+}, document.title + ' uppercase first arg');
+
+test(function(){
+ var t = video.addTextTrack('subtitles');
+ assert_equals(t.kind, 'subtitles');
+ assert_equals(t.label, '');
+ assert_equals(t.language, '');
+ assert_equals(t.mode, 'hidden');
+ assert_true(t.cues instanceof TextTrackCueList);
+ assert_equals(t.cues.length, 0);
+}, document.title + ' subtitles first arg');
+
+test(function(){
+ var t = video.addTextTrack('captions');
+ assert_equals(t.kind, 'captions');
+ assert_equals(t.label, '');
+ assert_equals(t.language, '');
+ assert_equals(t.mode, 'hidden');
+ assert_true(t.cues instanceof TextTrackCueList);
+ assert_equals(t.cues.length, 0);
+}, document.title + ' captions first arg');
+
+test(function(){
+ var t = video.addTextTrack('descriptions');
+ assert_equals(t.kind, 'descriptions');
+ assert_equals(t.label, '');
+ assert_equals(t.language, '');
+ assert_equals(t.mode, 'hidden');
+ assert_true(t.cues instanceof TextTrackCueList);
+ assert_equals(t.cues.length, 0);
+}, document.title + ' descriptions first arg');
+
+test(function(){
+ var t = video.addTextTrack('chapters');
+ assert_equals(t.kind, 'chapters');
+ assert_equals(t.label, '');
+ assert_equals(t.language, '');
+ assert_equals(t.mode, 'hidden');
+ assert_true(t.cues instanceof TextTrackCueList);
+ assert_equals(t.cues.length, 0);
+}, document.title + ' chapters first arg');
+
+test(function(){
+ var t = video.addTextTrack('metadata');
+ assert_equals(t.kind, 'metadata');
+ assert_equals(t.label, '');
+ assert_equals(t.language, '');
+ assert_equals(t.mode, 'hidden');
+ assert_true(t.cues instanceof TextTrackCueList);
+ assert_equals(t.cues.length, 0);
+}, document.title + ' metadata first arg');
+
+test(function(){
+ var t = video.addTextTrack('subtitles', undefined, undefined);
+ assert_equals(t.kind, 'subtitles');
+ assert_equals(t.label, '');
+ assert_equals(t.language, '');
+ assert_equals(t.mode, 'hidden');
+ assert_true(t.cues instanceof TextTrackCueList);
+ assert_equals(t.cues.length, 0);
+}, document.title + ' undefined second and third arg');
+
+test(function(){
+ var t = video.addTextTrack('subtitles', null, null);
+ assert_equals(t.kind, 'subtitles');
+ assert_equals(t.label, 'null');
+ assert_equals(t.language, 'null');
+ assert_equals(t.mode, 'hidden');
+ assert_true(t.cues instanceof TextTrackCueList);
+ assert_equals(t.cues.length, 0);
+}, document.title + ' null second and third arg');
+
+test(function(){
+ var t = video.addTextTrack('subtitles', 'foo', 'bar');
+ assert_equals(t.kind, 'subtitles');
+ assert_equals(t.label, 'foo');
+ assert_equals(t.language, 'bar');
+ assert_equals(t.mode, 'hidden');
+ assert_true(t.cues instanceof TextTrackCueList);
+ assert_equals(t.cues.length, 0);
+}, document.title + ' foo and bar second and third arg');
+
+test(function(){
+ var t = video.addTextTrack('subtitles', 'foo');
+ assert_equals(t.kind, 'subtitles');
+ assert_equals(t.label, 'foo');
+ assert_equals(t.language, '');
+ assert_equals(t.mode, 'hidden');
+ assert_true(t.cues instanceof TextTrackCueList);
+ assert_equals(t.cues.length, 0);
+}, document.title + ' foo second arg, third arg omitted');
+
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/crossOrigin.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/crossOrigin.html
new file mode 100644
index 0000000000..e29f2b0fbc
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/crossOrigin.html
@@ -0,0 +1,60 @@
+<!doctype html>
+<title>HTMLMediaElement.crossOrigin</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function(){
+ var video = document.createElement('video');
+ assert_true('crossOrigin' in video);
+});
+test(function(){
+ var video = document.createElement('video');
+ assert_equals(video.crossOrigin, null);
+}, document.title+', content attribute missing');
+test(function(){
+ var video = document.createElement('video');
+ video.setAttribute('crossorigin', 'foo');
+ assert_equals(video.crossOrigin, 'anonymous');
+}, document.title+', content attribute invalid value');
+test(function(){
+ var video = document.createElement('video');
+ video.setAttribute('crossorigin', '');
+ assert_equals(video.crossOrigin, 'anonymous');
+}, document.title+', content attribute empty string');
+test(function(){
+ var video = document.createElement('video');
+ video.setAttribute('crossorigin', 'ANONYMOUS');
+ assert_equals(video.crossOrigin, 'anonymous');
+}, document.title+', content attribute uppercase ANONYMOUS');
+test(function(){
+ var video = document.createElement('video');
+ video.setAttribute('crossorigin', 'use-credentials');
+ assert_equals(video.crossOrigin, 'use-credentials');
+}, document.title+', content attribute use-credentials');
+test(function(){
+ var video = document.createElement('video');
+ video.crossOrigin = '';
+ assert_equals(video.getAttribute('crossorigin'), '');
+}, document.title+', setting to empty string');
+test(function(){
+ var video = document.createElement('video');
+ video.crossOrigin = null;
+ assert_false(video.hasAttribute('crossorigin'));
+}, document.title+', setting to null');
+test(function(){
+ var video = document.createElement('video');
+ video.crossOrigin = 'foo';
+ assert_equals(video.getAttribute('crossorigin'), 'foo');
+}, document.title+', setting to invalid value');
+test(function(){
+ var video = document.createElement('video');
+ video.crossOrigin = 'ANONYMOUS';
+ assert_equals(video.getAttribute('crossorigin'), 'ANONYMOUS');
+}, document.title+', setting to uppercase ANONYMOUS');
+test(function(){
+ var video = document.createElement('video');
+ video.crossOrigin = 'use-credentials';
+ assert_equals(video.getAttribute('crossorigin'), 'use-credentials');
+}, document.title+', setting to use-credentials');
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/textTracks.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/textTracks.html
new file mode 100644
index 0000000000..0f183b7e15
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/textTracks.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<title>HTMLMediaElement.textTracks</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+var video = document.createElement('video');
+test(function(){
+ assert_equals(video.textTracks, video.textTracks);
+ assert_equals(video.textTracks.length, 0);
+});
+
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/default.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/default.html
new file mode 100644
index 0000000000..05fd0f7f7d
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/default.html
@@ -0,0 +1,55 @@
+<!doctype html>
+<title>HTMLTrackElement.default</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function(){
+ var track = document.createElement('track');
+ assert_equals(track['default'], false);
+ assert_equals(track.getAttribute('default'), null);
+}, document.title + ' missing value');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('default', '');
+ assert_equals(track['default'], true);
+ assert_equals(track.getAttribute('default'), '');
+}, document.title + ' empty string content attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track['default'] = '';
+ assert_equals(track['default'], false);
+ assert_equals(track.getAttribute('default'), null);
+}, document.title + ' empty string IDL attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('default', 'foo');
+ assert_equals(track['default'], true);
+ assert_equals(track.getAttribute('default'), 'foo');
+}, document.title + ' foo in content attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track['default'] = 'foo';
+ assert_equals(track['default'], true);
+ assert_equals(track.getAttribute('default'), '');
+}, document.title + ' foo in IDL attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track['default'] = true;
+ assert_equals(track['default'], true);
+ assert_equals(track.getAttribute('default'), '');
+}, document.title + ' true in IDL attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('default', '');
+ track['default'] = false;
+ assert_equals(track['default'], false);
+ assert_equals(track.getAttribute('default'), null);
+}, document.title + ' false in IDL attribute');
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/kind.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/kind.html
new file mode 100644
index 0000000000..78c3bff51a
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/kind.html
@@ -0,0 +1,146 @@
+<!doctype html>
+<title>HTMLTrackElement.kind</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function(){
+ var track = document.createElement('track');
+ assert_equals(track.kind, 'subtitles');
+ assert_equals(track.getAttribute('kind'), null);
+}, document.title + ' missing value');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('kind', 'invalid');
+ assert_equals(track.kind, 'metadata');
+ assert_equals(track.getAttribute('kind'), 'invalid');
+}, document.title + ' invalid value in content attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('kind', 'CAPTIONS');
+ assert_equals(track.kind, 'captions');
+ assert_equals(track.getAttribute('kind'), 'CAPTIONS');
+}, document.title + ' content attribute uppercase');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('kind', 'CAPT\u0130ONS');
+ assert_equals(track.kind, 'metadata');
+ assert_equals(track.getAttribute('kind'), 'CAPT\u0130ONS');
+}, document.title + ' content attribute with uppercase turkish I (with dot)');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('kind', 'capt\u0131ons');
+ assert_equals(track.kind, 'metadata');
+ assert_equals(track.getAttribute('kind'), 'capt\u0131ons');
+}, document.title + ' content attribute with lowercase turkish i (dotless)');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('kind', 'subtitles');
+ assert_equals(track.kind, 'subtitles');
+ assert_equals(track.getAttribute('kind'), 'subtitles');
+}, document.title + ' content attribute "subtitles"');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('kind', 'captions');
+ assert_equals(track.kind, 'captions');
+ assert_equals(track.getAttribute('kind'), 'captions');
+}, document.title + ' content attribute "captions"');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('kind', 'descriptions');
+ assert_equals(track.kind, 'descriptions');
+ assert_equals(track.getAttribute('kind'), 'descriptions');
+}, document.title + ' content attribute "descriptions"');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('kind', 'chapters');
+ assert_equals(track.kind, 'chapters');
+ assert_equals(track.getAttribute('kind'), 'chapters');
+}, document.title + ' content attribute "chapters"');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('kind', 'metadata');
+ assert_equals(track.kind, 'metadata');
+ assert_equals(track.getAttribute('kind'), 'metadata');
+}, document.title + ' content attribute "metadata"');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('kind', 'captions\u0000');
+ assert_equals(track.kind, 'metadata');
+ assert_equals(track.getAttribute('kind'), 'captions\u0000');
+}, document.title + ' content attribute "captions\\u0000"');
+
+test(function(){
+ var track = document.createElement('track');
+ track.kind = 'subtitles';
+ assert_equals(track.getAttribute('kind'), 'subtitles');
+ assert_equals(track.kind, 'subtitles');
+}, document.title + ' setting IDL attribute to "subtitles"');
+
+test(function(){
+ var track = document.createElement('track');
+ track.kind = 'captions';
+ assert_equals(track.getAttribute('kind'), 'captions');
+ assert_equals(track.kind, 'captions');
+}, document.title + ' setting IDL attribute to "captions"');
+
+test(function(){
+ var track = document.createElement('track');
+ track.kind = 'descriptions';
+ assert_equals(track.getAttribute('kind'), 'descriptions');
+ assert_equals(track.kind, 'descriptions');
+}, document.title + ' setting IDL attribute to "descriptions"');
+
+test(function(){
+ var track = document.createElement('track');
+ track.kind = 'chapters';
+ assert_equals(track.getAttribute('kind'), 'chapters');
+ assert_equals(track.kind, 'chapters');
+}, document.title + ' setting IDL attribute to "chapters"');
+
+test(function(){
+ var track = document.createElement('track');
+ track.kind = 'metadata';
+ assert_equals(track.getAttribute('kind'), 'metadata');
+ assert_equals(track.kind, 'metadata');
+}, document.title + ' setting IDL attribute to "metadata"');
+
+test(function(){
+ var track = document.createElement('track');
+ track.kind = 'CAPTIONS';
+ assert_equals(track.getAttribute('kind'), 'CAPTIONS');
+ assert_equals(track.kind, 'captions');
+}, document.title + ' setting IDL attribute to "CAPTIONS"');
+
+test(function(){
+ var track = document.createElement('track');
+ track.kind = 'CAPT\u0130ONS';
+ assert_equals(track.getAttribute('kind'), 'CAPT\u0130ONS');
+ assert_equals(track.kind, 'metadata');
+}, document.title + ' setting IDL attribute with uppercase turkish I (with dot)');
+
+test(function(){
+ var track = document.createElement('track');
+ track.kind = 'capt\u0131ons';
+ assert_equals(track.getAttribute('kind'), 'capt\u0131ons');
+ assert_equals(track.kind, 'metadata');
+}, document.title + ' setting IDL attribute with lowercase turkish I (dotless)');
+
+test(function(){
+ var track = document.createElement('track');
+ track.kind = 'captions\u0000';
+ assert_equals(track.getAttribute('kind'), 'captions\u0000');
+ assert_equals(track.kind, 'metadata');
+}, document.title + ' setting IDL attribute with \\u0000');
+
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/label.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/label.html
new file mode 100644
index 0000000000..b2360315cf
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/label.html
@@ -0,0 +1,83 @@
+<!doctype html>
+<title>HTMLTrackElement.label</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function(){
+ var track = document.createElement('track');
+ assert_equals(track.label, '');
+ assert_equals(track.getAttribute('label'), null);
+}, document.title + ' missing value');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('label', '');
+ assert_equals(track.label, '');
+ assert_equals(track.getAttribute('label'), '');
+}, document.title + ' empty string content attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.label = '';
+ assert_equals(track.label, '');
+ assert_equals(track.getAttribute('label'), '');
+}, document.title + ' empty string IDL attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('label', 'foo');
+ assert_equals(track.label, 'foo');
+ assert_equals(track.getAttribute('label'), 'foo');
+}, document.title + ' lowercase content attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('label', 'FOO');
+ assert_equals(track.label, 'FOO');
+ assert_equals(track.getAttribute('label'), 'FOO');
+}, document.title + ' uppercase content attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('label', '\u0000');
+ assert_equals(track.label, '\u0000');
+ assert_equals(track.getAttribute('label'), '\u0000');
+}, document.title + '\\u0000 in content attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.label = 'foo';
+ assert_equals(track.label, 'foo');
+ assert_equals(track.getAttribute('label'), 'foo');
+}, document.title + ' lowercase IDL attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.label = 'FOO';
+ assert_equals(track.label, 'FOO');
+ assert_equals(track.getAttribute('label'), 'FOO');
+}, document.title + ' uppercase IDL attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('label', ' foo \n');
+ assert_equals(track.label, ' foo \n');
+ assert_equals(track.getAttribute('label'), ' foo \n');
+}, document.title + ' whitespace in content attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.label = ' foo \n';
+ assert_equals(track.label, ' foo \n');
+ assert_equals(track.getAttribute('label'), ' foo \n');
+}, document.title + ' whitespace in IDL attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.label = '\u0000';
+ assert_equals(track.label, '\u0000');
+ assert_equals(track.getAttribute('label'), '\u0000');
+}, document.title + ' \\u0000 in IDL attribute');
+
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/readyState.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/readyState.html
new file mode 100644
index 0000000000..cde21e694e
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/readyState.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>HTMLTrackElement.readyState</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function(){
+ var track = document.createElement('track');
+ assert_equals(track.readyState, 0);
+}, document.title + ' default value');
+
+test(function(){
+ assert_equals(HTMLTrackElement.NONE, 0);
+ assert_equals(HTMLTrackElement.LOADING, 1);
+ assert_equals(HTMLTrackElement.LOADED, 2);
+ assert_equals(HTMLTrackElement.ERROR, 3);
+}, document.title + ' values');
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/src.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/src.html
new file mode 100644
index 0000000000..4089913cbd
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/src.html
@@ -0,0 +1,43 @@
+<!doctype html>
+<title>HTMLTrackElement.src</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function(){
+ var track = document.createElement('track');
+ assert_equals(track.src, '');
+ assert_equals(track.getAttribute('src'), null);
+}, document.title + ' missing value');
+
+function resolve(url) {
+ var link = document.createElement('a');
+ link.setAttribute('href', url);
+ return link.href;
+}
+
+var tests = [
+ {input:'', expectedIDL:resolve(''), desc:'empty string'},
+ {input:'http://foo bar', expectedIDL:'http://foo bar', desc:'unresolvable value'},
+ {input:'test', expectedIDL:resolve('test'), desc:'resolvable value'},
+ // Leading and trailing C0 controls and space is stripped per url spec.
+ {input:'\u0000', expectedIDL:resolve(''), desc:'\\u0000'},
+ {input:'foo\u0000bar', expectedIDL:resolve('foo%00bar'), desc:'foo\\u0000bar'},
+];
+
+tests.forEach(function(t) {
+ test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('src', t.input);
+ assert_equals(track.src, t.expectedIDL);
+ assert_equals(track.getAttribute('src'), t.input);
+ }, [document.title, t.desc, 'in content attribute'].join(' '));
+
+ test(function(){
+ var track = document.createElement('track');
+ track.src = t.input;
+ assert_equals(track.src, t.expectedIDL);
+ assert_equals(track.getAttribute('src'), t.input);
+ }, [document.title, 'assigning', t.desc, 'to IDL attribute'].join(' '));
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/srclang.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/srclang.html
new file mode 100644
index 0000000000..b5071e0c36
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/srclang.html
@@ -0,0 +1,82 @@
+<!doctype html>
+<title>HTMLTrackElement.srclang</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function(){
+ var track = document.createElement('track');
+ assert_equals(track.srclang, '');
+ assert_equals(track.getAttribute('srclang'), null);
+}, document.title + ' missing value');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('srclang', '');
+ assert_equals(track.srclang, '');
+ assert_equals(track.getAttribute('srclang'), '');
+}, document.title + ' empty string content attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.srclang = '';
+ assert_equals(track.srclang, '');
+ assert_equals(track.getAttribute('srclang'), '');
+}, document.title + ' empty string IDL attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('srclang', 'foo');
+ assert_equals(track.srclang, 'foo');
+ assert_equals(track.getAttribute('srclang'), 'foo');
+}, document.title + ' lowercase content attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('srclang', 'FOO');
+ assert_equals(track.srclang, 'FOO');
+ assert_equals(track.getAttribute('srclang'), 'FOO');
+}, document.title + ' uppercase content attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('srclang', '\u0000');
+ assert_equals(track.srclang, '\u0000');
+ assert_equals(track.getAttribute('srclang'), '\u0000');
+}, document.title + ' \\u0000 content attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.srclang = 'foo';
+ assert_equals(track.srclang, 'foo');
+ assert_equals(track.getAttribute('srclang'), 'foo');
+}, document.title + ' lowercase IDL attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.srclang = 'FOO';
+ assert_equals(track.srclang, 'FOO');
+ assert_equals(track.getAttribute('srclang'), 'FOO');
+}, document.title + ' uppercase IDL attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('srclang', ' foo \n');
+ assert_equals(track.srclang, ' foo \n');
+ assert_equals(track.getAttribute('srclang'), ' foo \n');
+}, document.title + ' whitespace in content attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.srclang = ' foo \n';
+ assert_equals(track.srclang, ' foo \n');
+ assert_equals(track.getAttribute('srclang'), ' foo \n');
+}, document.title + ' whitespace in IDL attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.srclang = '\u0000';
+ assert_equals(track.srclang, '\u0000');
+ assert_equals(track.getAttribute('srclang'), '\u0000');
+}, document.title + ' \\u0000 in IDL attribute');
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/track.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/track.html
new file mode 100644
index 0000000000..1de0a88046
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/track.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<title>HTMLTrackElement.track</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function(){
+ var track = document.createElement('track');
+ assert_equals(track.track, track.track, 'same object should be returned');
+ assert_true(track.track instanceof TextTrack, 'returned object should be a TextTrack');
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/activeCues.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/activeCues.html
new file mode 100644
index 0000000000..7a57826f30
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/activeCues.html
@@ -0,0 +1,101 @@
+<!doctype html>
+<title>TextTrack.activeCues</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/common/media.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.video = document.createElement('video');
+ window.t1 = video.addTextTrack('subtitles');
+ window.track = document.createElement('track');
+ track['default'] = true;
+ video.appendChild(track);
+ window.t2 = track.track;
+ t2.mode = 'showing';
+ window.t1_cues = t1.activeCues;
+ window.t2_cues = t2.activeCues;
+ document.body.appendChild(video);
+ if (!t1)
+ throw new Error('t1 was undefined')
+});
+function smoke_test() {
+ assert_true('HTMLTrackElement' in window, 'track not supported');
+}
+
+test(function(){
+ smoke_test();
+ assert_equals(t1.activeCues, t1_cues, 't1.activeCues should return same object');
+ assert_equals(t2.activeCues, t2_cues, 't2.activeCues should return same object');
+ assert_not_equals(t1.activeCues, t2.activeCues, 't1.activeCues and t2.activeCues should be different objects');
+ assert_not_equals(t1.activeCues, null, 't1.activeCues should not be null');
+ assert_not_equals(t2.activeCues, null, 't2.activeCues should not be null');
+ assert_equals(t1.activeCues.length, 0, 't1.activeCues should have length 0');
+ assert_equals(t2.activeCues.length, 0, 't2.activeCues should have length 0');
+}, document.title+', empty list');
+test(function(){
+ smoke_test();
+ var c = new VTTCue(0, 1, "text");
+ t1.addCue(c);
+ assert_equals(t1.activeCues, t1_cues, "t1.activeCues should return same object");
+ assert_equals(t1.activeCues.length, 0, "t1.activeCues.length");
+ var c2 = new VTTCue(1, 2, "text2");
+ t1.addCue(c2);
+ assert_equals(t1.activeCues, t1_cues, "t1.activeCues should return the same object after adding a second cue");
+ assert_equals(t1.activeCues.length, 0, "t1.activeCues.length after adding a second cue");
+}, document.title+', after addCue()');
+test(function(){
+ smoke_test();
+ t1.mode = 'showing';
+ assert_equals(t1.activeCues, t1_cues, "t1.activeCues should return the same object after setting mode to showing");
+ t1.mode = 'hidden';
+ assert_equals(t1.activeCues, t1_cues, "t1.activeCues should return the same object after setting mode to hidden");
+ t1.mode = 'disabled';
+ assert_equals(t1.activeCues, null, "t1.activeCues should be null when mode is disabled");
+ assert_equals(t1_cues.length, 0, "t1_cues should still be intact after setting mode to disabled");
+}, document.title+', different modes');
+
+// ok now let's load in a video
+var test1 = async_test(document.title+', video loading');
+var test2 = async_test(document.title+', video playing');
+var test3 = async_test(document.title+', adding cue during playback');
+test1.step(smoke_test);
+test2.step(smoke_test);
+test3.step(smoke_test);
+test1.step(function(){
+ t1.mode = 'showing';
+ video.onloadeddata = test1.step_func(function(e) {
+ video.onplaying = test2.step_func(function(e) {
+ try {
+ assert_equals(t1.activeCues, t1_cues, "t1.activeCues should return the same object after playing a video");
+ assert_equals(t1.activeCues.length, 1, "t1.activeCues.length after the video has started playing");
+ } catch(ex) {
+ test2.step(function() { throw ex; });
+ test3.step(function() { assert_unreached(); });
+ return;
+ }
+ test3.step(function(){
+ var c3 = new VTTCue(0, 2, "text3");
+ t1.addCue(c3);
+ assert_equals(t1.activeCues.length, 2, "t1.activeCues.length should be changed immediately");
+ test3.done();
+ });
+ test2.done();
+ });
+ try {
+ assert_equals(t1.activeCues, t1_cues, "t1.activeCues should return the same object after loading a video");
+ assert_equals(t2.activeCues, t2_cues, "t2.activeCues should return the same object after loading a video");
+ assert_equals(t1.activeCues.length, 0, "t1.activeCues.length before the video has started playing");
+ assert_equals(t2.activeCues.length, 0, "t1.activeCues.length before the video has started playing");
+ } catch(ex) {
+ test1.step(function() { throw ex; });
+ test2.step(function() { assert_unreached(); });
+ test3.step(function() { assert_unreached(); });
+ return;
+ }
+ video.play();
+ test1.done();
+ });
+ video.src = getVideoURI("/media/movie_5");
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/addCue.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/addCue.html
new file mode 100644
index 0000000000..622ec4abfd
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/addCue.html
@@ -0,0 +1,68 @@
+<!doctype html>
+<title>TextTrack.addCue()</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.video = document.createElement('video');
+ document.body.appendChild(video);
+});
+test(function() {
+ var t1 = video.addTextTrack('subtitles');
+ var t2 = video.addTextTrack('subtitles');
+ var c1 = new VTTCue(0, 1, 'text1');
+ t1.addCue(c1);
+ t2.addCue(c1);
+ assert_equals(c1.track, t2);
+}, document.title+', adding a cue to two different tracks');
+test(function() {
+ var t1 = video.addTextTrack('subtitles');
+ var c1 = new VTTCue(0, 1, 'text1');
+ t1.addCue(c1);
+ assert_equals(c1.track, t1);
+ t1.addCue(c1);
+ assert_equals(c1.track, t1);
+}, document.title+', adding a cue to a track twice');
+test(function() {
+ var t1 = video.addTextTrack('subtitles');
+ var t2 = video.addTextTrack('subtitles');
+ var c1 = new VTTCue(0, 1, 'text1');
+ t1.addCue(c1);
+ assert_equals(c1.track, t1);
+ t1.removeCue(c1);
+ assert_equals(c1.track, null);
+ t2.addCue(c1);
+ assert_equals(c1.track, t2);
+}, document.title+', adding a removed cue to a different track');
+test(function() {
+ var t1 = video.addTextTrack('subtitles');
+ var c1 = new VTTCue(0, 1, 'text1');
+ t1.addCue(c1);
+ assert_equals(t1.cues.length, 1, 't1.cues.length after first addition');
+ t1.removeCue(c1);
+ assert_equals(t1.cues.length, 0, 't1.cues.length after removal');
+ t1.addCue(c1);
+ assert_equals(t1.cues.length, 1, 't1.cues.length after second addition');
+}, document.title+', adding an associated but removed cue to the same track');
+
+var t = async_test(document.title+', adding a cue associated with a track element to other track');
+t.step(function(){
+ var t1 = video.addTextTrack('subtitles');
+ var track = document.createElement('track');
+ track.onload = t.step_func(function(){
+ var cue = track.track.cues[0];
+ track.track.removeCue(cue);
+ t1.addCue(cue);
+ assert_equals(cue.track, t1);
+ t.done();
+ });
+ track.onerror = t.step_func(function() {
+ assert_unreached('got error event');
+ });
+ track.src= 'data:text/vtt,'+encodeURIComponent('WEBVTT\n\n00:00:00.000 --> 00:00:01.000\ntest\n');
+ track.kind = 'subtitles';
+ track.track.mode = 'hidden';
+ video.appendChild(track);
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/constants.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/constants.html
new file mode 100644
index 0000000000..3c8046cdc4
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/constants.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<title>TextTrack constants</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.video = document.createElement('video');
+ window.t1 = video.addTextTrack('subtitles');
+});
+test(function(){
+ assert_equals(t1.DISABLED, undefined, "t1.DISABLED");
+ assert_equals(t1.HIDDEN, undefined, "t1.HIDDEN");
+ assert_equals(t1.SHOWING, undefined, "t1.SHOWING");
+ assert_equals(TextTrack.prototype.DISABLED, undefined, "TextTrack.prototype.DISABLED");
+ assert_equals(TextTrack.prototype.HIDDEN, undefined, "TextTrack.prototype.HIDDEN");
+ assert_equals(TextTrack.prototype.SHOWING, undefined, "TextTrack.prototype.SHOWING");
+ assert_equals(TextTrack.DISABLED, undefined, "TextTrack.DISABLED");
+ assert_equals(TextTrack.HIDDEN, undefined, "TextTrack.HIDDEN");
+ assert_equals(TextTrack.SHOWING, undefined, "TextTrack.SHOWING");
+});
+
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/cues.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/cues.html
new file mode 100644
index 0000000000..4b7808c963
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/cues.html
@@ -0,0 +1,100 @@
+<!doctype html>
+<title>TextTrack.cues</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function(){
+ var video = document.createElement('video');
+ var t1 = video.addTextTrack('subtitles');
+ assert_equals(t1.cues, t1.cues, 't1.cues should return same object');
+ assert_not_equals(t1.cues, null, 't1.cues should not be null');
+ assert_true(t1.cues instanceof TextTrackCueList, 't1.cues instanceof TextTrackCueList');
+ assert_equals(t1.cues.length, 0, 't1.cues.length');
+}, document.title+', empty list');
+
+function addCue(texttrack, start, end, text, id) {
+ var c = new VTTCue(start, end, text);
+ c.id = id;
+ texttrack.addCue(c);
+ return c;
+}
+
+test(function(){
+ var video = document.createElement('video');
+ var t1 = video.addTextTrack('subtitles');
+ var t1_cues = t1.cues;
+ var c = addCue(t1, 0, 1, 'text', 'id');
+ assert_equals(t1.cues, t1_cues, "t1.cues should return same object");
+ assert_equals(t1.cues.length, 1, "t1.cues.length");
+ var c2 = addCue(t1, 1, 2, 'text2', 'id2');
+ assert_equals(t1.cues, t1_cues, "t1.cues should return the same object after adding a second cue");
+ assert_equals(t1.cues.length, 2, "t1.cues.length after adding a second cue");
+ assert_equals(t1.cues[0].id, "id");
+ assert_equals(t1.cues[1].id, "id2");
+}, document.title+', after addCue()');
+
+test(function(){
+ var video = document.createElement('video');
+ var t1 = video.addTextTrack('subtitles');
+ var t1_cues = t1.cues;
+ var c = addCue(t1, 0, 1, 'text', 'id');
+ var c2 = addCue(t1, 1, 2, 'text2', 'id2');
+ t1.mode = 'showing';
+ assert_equals(t1.cues, t1_cues, "t1.cues should return the same object after setting mode to 'showing'");
+ t1.mode = 'hidden';
+ assert_equals(t1.cues, t1_cues, "t1.cues should return the same object after setting mode to 'hidden'");
+ t1.mode = 'disabled';
+ assert_equals(t1.cues, null, "t1.cues should be null when mode is 'disabled'");
+ assert_equals(t1_cues.length, 2, "t1_cues should still be intact after setting mode to 'disabled'");
+ assert_equals(t1_cues[0].id, "id", "t1_cues first cue should still be intact after setting mode to 'disabled'");
+ assert_equals(t1_cues[1].id, "id2", "t1_cues second cue should still be intact after setting mode to 'disabled'");
+ t1.mode = 'hidden';
+ assert_equals(t1.cues, t1_cues, "t1.cues should return the same object after setting mode to 'disabled' and then 'hidden'");
+ t1.mode = 'disabled';
+ assert_equals(t1.cues, null, "t1.cues should be null when mode is set to 'disabled' again");
+ assert_equals(t1_cues.length, 2, "t1_cues should still be intact after setting mode to 'disabled' again");
+ assert_equals(t1_cues[0].id, "id", "t1_cues first cue should still be intact after setting mode to 'disabled' again");
+ assert_equals(t1_cues[1].id, "id2", "t1_cues second cue should still be intact after setting mode to 'disabled' again");
+ t1.mode = 'showing';
+ assert_equals(t1.cues, t1_cues, "t1.cues should return the same object after setting mode to 'disabled' and then 'showing'");
+}, document.title+', different modes');
+
+test(function(){
+ var video = document.createElement('video');
+ var t1 = video.addTextTrack('subtitles');
+ var t1_cues = t1.cues;
+ var c = addCue(t1, 0, 1, 'text', 'id');
+ var c2 = addCue(t1, 1, 2, 'text2', 'id2');
+ t1.mode = 'showing';
+ t1.cues[1].startTime = 0; // this should change the text track cue order
+ assert_equals(t1.cues[0].id, 'id2');
+ assert_equals(t1.cues[1].id, 'id');
+ t1.cues[0].startTime = 0.5; // this should change it back
+ assert_equals(t1.cues[0].id, 'id');
+ assert_equals(t1.cues[1].id, 'id2');
+}, document.title+', changing order');
+
+async_test(function(){
+ var video = document.createElement('video');
+ var t1 = video.addTextTrack('subtitles');
+ var t1_cues = t1.cues;
+ t1.mode = 'hidden';
+ var track = document.createElement('track');
+ track['default'] = true;
+ video.appendChild(track); // queues a task to "honor user preferences...", media element event task source
+ var t2 = track.track;
+ assert_equals(t2.cues, null, 't2.cues should be null');
+ // We need to wait until the "honor user preferences..." steps have run so we invoke play()
+ // which queues an event with the same task source.
+ video.onplay = this.step_func(function(){
+ assert_equals(t2.cues, t2.cues, 't2.cues should return same object');
+ assert_not_equals(t1.cues, t2.cues, 't1.cues and t2.cues should be different objects');
+ assert_not_equals(t2.cues, null, 't2.cues should not be null');
+ assert_true(t2.cues instanceof TextTrackCueList, 't2.cues instanceof TextTrackCueList');
+ assert_equals(t2.cues.length, 0, 't2.cues should have length 0');
+ this.done();
+ });
+ video.play(); // queues a task to fire 'play', media element event task source
+}, document.title+', default attribute');
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/kind.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/kind.html
new file mode 100644
index 0000000000..d5dbc8342c
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/kind.html
@@ -0,0 +1,31 @@
+<!doctype html>
+<title>TextTrack.kind</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function(){
+ var video = document.createElement('video');
+ var t1 = video.addTextTrack('subtitles');
+ var t2 = video.addTextTrack('captions');
+ var t3 = video.addTextTrack('descriptions');
+ var t4 = video.addTextTrack('chapters');
+ var t5 = video.addTextTrack('metadata');
+ assert_equals(t1.kind, 'subtitles');
+ assert_equals(t2.kind, 'captions');
+ assert_equals(t3.kind, 'descriptions');
+ assert_equals(t4.kind, 'chapters');
+ assert_equals(t5.kind, 'metadata');
+}, document.title+', addTextTrack');
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('kind', 'CAPTIONS');
+ var t = track.track;
+ assert_equals(t.kind, 'captions');
+}, document.title+', track element');
+test(function(){
+ var track = document.createElement('track');
+ track.kind = 'captions\u0000';
+ assert_equals(track.track.kind, 'metadata');
+}, document.title+', \\u0000');
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/label.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/label.html
new file mode 100644
index 0000000000..c60e85c21a
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/label.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<title>TextTrack.label</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.video = document.createElement('video');
+ window.t1 = video.addTextTrack('subtitles', 'foo');
+ window.track = document.createElement('track');
+ track.setAttribute('label', 'bar');
+ video.appendChild(track);
+ window.t2 = track.track;
+});
+test(function(){
+ assert_equals(t1.label, 'foo');
+ assert_equals(t2.label, 'bar');
+ track.label = 'baz';
+ assert_equals(t2.label, 'baz');
+ track.removeAttribute('label');
+ assert_equals(t2.label, '');
+});
+test(function(){
+ track.label = '\u0000a';
+ assert_equals(t2.label, '\u0000a');
+ track.setAttribute('label', '\u0000b', 'IDL attribute');
+ assert_equals(t2.label, '\u0000b', 'content attribute');
+}, document.title+', \\u0000');
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/language.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/language.html
new file mode 100644
index 0000000000..eda3653de0
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/language.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<title>TextTrack.language</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.video = document.createElement('video');
+ window.t1 = video.addTextTrack('subtitles', 'foo', 'foo');
+ window.track = document.createElement('track');
+ track.setAttribute('srclang', 'bar');
+ video.appendChild(track);
+ window.t2 = track.track;
+});
+test(function(){
+ assert_equals(t1.language, 'foo');
+ assert_equals(t2.language, 'bar');
+ track.srclang = 'baz';
+ assert_equals(t2.language, 'baz');
+ track.removeAttribute('srclang');
+ assert_equals(t2.language, '');
+});
+test(function(){
+ track.srclang = '\u0000a';
+ assert_equals(t2.language, '\u0000a', 'IDL attribute');
+ track.setAttribute('srclang', '\u0000b');
+ assert_equals(t2.language, '\u0000b', 'content attribute');
+}, document.title+', \\u0000');
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/mode.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/mode.html
new file mode 100644
index 0000000000..9f94156706
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/mode.html
@@ -0,0 +1,55 @@
+<!doctype html>
+<title>TextTrack.mode</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function(){
+ var track = document.createElement('track');
+ assert_equals(track.track.mode, 'disabled', 'initial');
+ track.track.mode = 1;
+ assert_equals(track.track.mode, 'disabled', '1');
+ track.track.mode = '';
+ assert_equals(track.track.mode, 'disabled', '""');
+ track.track.mode = null;
+ assert_equals(track.track.mode, 'disabled', 'null');
+ track.track.mode = undefined;
+ assert_equals(track.track.mode, 'disabled', 'undefined');
+ track.track.mode = 'showing';
+ assert_equals(track.track.mode, 'showing', 'showing (correct value)');
+ track.track.mode = 'DISABLED';
+ assert_equals(track.track.mode, 'showing', '"DISABLED"');
+ track.track.mode = 'd\u0130sabled'; // dotted uppercase i
+ assert_equals(track.track.mode, 'showing', '"d\u0130sabled" (dotted uppercase i)');
+ track.track.mode = 'd\u0131sabled'; // dotless lowercase i
+ assert_equals(track.track.mode, 'showing', '"d\u0131sabled" (dotless lowercase i)');
+ track.track.mode = 'disabled ';
+ assert_equals(track.track.mode, 'showing', '"disabled "');
+ track.track.mode = ' disabled';
+ assert_equals(track.track.mode, 'showing', '" disabled"');
+ track.track.mode = {};
+ assert_equals(track.track.mode, 'showing', '{}');
+ track.track.mode = 'HIDDEN';
+ assert_equals(track.track.mode, 'showing', '"HIDDEN"');
+ track.track.mode = 'h\u0130dden'; // dotted uppercase i
+ assert_equals(track.track.mode, 'showing', '"h\u0130dden" (dotted uppercase i)');
+ track.track.mode = 'h\u0131dden'; // dotless lowercase i
+ assert_equals(track.track.mode, 'showing', '"h\u0131dden" (dotless lowercase i)');
+}, document.title+', wrong value');
+test(function() {
+ var track = document.createElement('track');
+ assert_equals(track.track.mode, 'disabled', 'initial');
+ track.track.mode = 'disabled'; // no-op
+ assert_equals(track.track.mode, 'disabled', 'disabled (1)');
+ track.track.mode = 'hidden';
+ assert_equals(track.track.mode, 'hidden', 'hidden (1)');
+ track.track.mode = 'hidden'; // no-op
+ assert_equals(track.track.mode, 'hidden', 'hidden (2)');
+ track.track.mode = 'showing';
+ assert_equals(track.track.mode, 'showing', 'showing (1)');
+ track.track.mode = 'showing'; // no-op
+ assert_equals(track.track.mode, 'showing', 'showing (2)');
+ track.track.mode = {toString:function() { return 'disabled'; }};
+ assert_equals(track.track.mode, 'disabled', '{toString:...}');
+}, document.title+', correct value');
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/oncuechange.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/oncuechange.html
new file mode 100644
index 0000000000..16c76f9484
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/oncuechange.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<title>TextTrack.oncuechange</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.video = document.createElement('video');
+ window.t1 = video.addTextTrack('subtitles');
+ window.ev = new Event('cuechange');
+ window.ran = false;
+ window.cb = function() { ran = true; };
+});
+test(function(){
+ assert_equals(t1.oncuechange, null);
+ t1.oncuechange = cb;
+ t1.dispatchEvent(ev);
+ assert_true(ran);
+ t1.oncuechange = null;
+ ran = false;
+ t1.dispatchEvent(ev);
+ assert_false(ran);
+});
+test(function(){
+ t1.addEventListener('cuechange', cb, false);
+ t1.dispatchEvent(ev);
+ assert_true(ran);
+ t1.removeEventListener('cuechange', cb, false);
+ ran = false;
+ t1.dispatchEvent(ev);
+ assert_false(ran);
+}, 'TextTrack.addEventListener/removeEventListener');
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/removeCue.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/removeCue.html
new file mode 100644
index 0000000000..09043458cc
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/removeCue.html
@@ -0,0 +1,50 @@
+<!doctype html>
+<title>TextTrack.removeCue()</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.video = document.createElement('video');
+ document.body.appendChild(video);
+});
+test(function() {
+ var t1 = video.addTextTrack('subtitles');
+ var t2 = video.addTextTrack('subtitles');
+ var c1 = new VTTCue(0, 1, 'text1');
+ assert_throws_dom("NOT_FOUND_ERR", function() {
+ t1.removeCue(c1);
+ }, 'standalone');
+ t1.addCue(c1);
+ assert_throws_dom("NOT_FOUND_ERR", function() {
+ t2.removeCue(c1);
+ }, 'listed in t1, remove from t2');
+ t1.removeCue(c1);
+ assert_throws_dom("NOT_FOUND_ERR", function() {
+ t1.removeCue(c1);
+ }, 'standalone, remove from t1');
+ assert_throws_dom("NOT_FOUND_ERR", function() {
+ t2.removeCue(c1);
+ }, 'standalone, remove from t2');
+}, document.title+', two elementless tracks');
+var t = async_test(document.title+', cue from track element');
+t.step(function(){
+ var t1 = video.addTextTrack('subtitles');
+ var track = document.createElement('track');
+ track.onload = t.step_func(function(){
+ var cue = track.track.cues[0];
+ assert_throws_dom('NOT_FOUND_ERR', function() { t1.removeCue(cue); }, 'listed in track.track, remove from t1');
+ track.track.removeCue(cue);
+ assert_throws_dom('NOT_FOUND_ERR', function() { track.track.removeCue(cue); }, 'standalone, remove from track.track');
+ assert_throws_dom('NOT_FOUND_ERR', function() { t1.removeCue(cue); }, 'standalone, remove from t1');
+ t.done();
+ });
+ track.onerror = t.step_func(function() {
+ assert_unreached('got error event');
+ });
+ track.src= 'data:text/vtt,'+encodeURIComponent('WEBVTT\n\n00:00:00.000 --> 00:00:01.000\ntest\n');
+ track.kind = 'subtitles';
+ track.track.mode = 'hidden';
+ video.appendChild(track);
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/constructor.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/constructor.html
new file mode 100644
index 0000000000..8ee9adb1c0
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/constructor.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>TextTrackCue constructor</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <script>
+ test(function()
+ {
+ assert_not_equals(TextTrackCue, VTTCue);
+ }, "TextTrackCue and VTTCue are separate interfaces");
+ test(function()
+ {
+ assert_throws_js(TypeError, function()
+ {
+ new TextTrackCue(0, 0, "");
+ });
+ }, "TextTrackCue constructor should not be supported");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/endTime.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/endTime.html
new file mode 100644
index 0000000000..18b14bdfa9
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/endTime.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<title>TextTrackCue.endTime</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.video = document.createElement('video');
+ window.t1 = video.addTextTrack('subtitles');
+ document.body.appendChild(video);
+});
+test(function(){
+ var c1 = new VTTCue(-2, -1, 'text1');
+ assert_equals(c1.endTime, -1);
+ c1.endTime = c1.endTime;
+ assert_equals(c1.endTime, -1);
+ assert_throws_js(TypeError, function(){ c1.endTime = NaN; });
+ c1.endTime = +Infinity;
+ assert_equals(c1.endTime, +Infinity);
+ assert_throws_js(TypeError, function(){ c1.endTime = -Infinity; });
+}, document.title+', script-created cue');
+
+var t_parsed = async_test(document.title+', parsed cue');
+t_parsed.step(function(){
+ var t = document.createElement('track');
+ t.onload = this.step_func(function(){
+ var c = t.track.cues;
+ assert_equals(c[0].endTime, 0.001);
+ assert_equals(c[1].endTime, 3600.001);
+ this.done();
+ });
+ t.onerror = this.step_func(function() {
+ assert_unreached('got error event');
+ });
+ t.src = 'data:text/vtt,'+encodeURIComponent('WEBVTT\n\n00:00:00.000 --> 00:00:00.001\ntest'+
+ '\n\nfoobar\n01:00:00.000 --> 01:00:00.001\ntest');
+ t.track.mode = 'showing';
+ video.appendChild(t);
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/id.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/id.html
new file mode 100644
index 0000000000..a88f94766f
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/id.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<title>TextTrackCue.id</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.video = document.createElement('video');
+ window.t1 = video.addTextTrack('subtitles');
+ document.body.appendChild(video);
+});
+test(function(){
+ var c1 = new VTTCue(0, 1, 'text1');
+ c1.id = 'id1\r\n\u0000';
+ assert_equals(c1.id, 'id1\r\n\u0000');
+ c1.id = c1.id;
+ assert_equals(c1.id, 'id1\r\n\u0000');
+ c1.id = null;
+ assert_equals(c1.id, 'null');
+}, document.title+', script-created cue');
+
+var t_parsed = async_test(document.title+', parsed cue');
+t_parsed.step(function(){
+ var t = document.createElement('track');
+ t.onload = this.step_func(function(){
+ var c = t.track.cues;
+ assert_equals(c[0].id, '');
+ assert_equals(c[1].id, 'foobar');
+ this.done();
+ });
+ t.onerror = this.step_func(function() {
+ assert_unreached('got error event');
+ });
+ t.src = 'data:text/vtt,'+encodeURIComponent('WEBVTT\n\n00:00:00.000 --> 00:00:00.001\ntest'+
+ '\n\nfoobar\n00:00:00.000 --> 00:00:00.001\ntest');
+ t.track.mode = 'showing';
+ video.appendChild(t);
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/onenter.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/onenter.html
new file mode 100644
index 0000000000..17deed0530
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/onenter.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<title>TextTrackCue.onenter</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.c1 = new VTTCue(0, 1, 'text1');
+ window.ev = new Event('enter');
+ window.ran = false;
+ window.cb = function() { ran = true; };
+});
+test(function(){
+ assert_equals(c1.onenter, null, 'initial value');
+ c1.onenter = undefined;
+ assert_equals(c1.onenter, null, 'assigning undefined');
+ c1.onenter = cb;
+ assert_equals(c1.onenter, cb, 'assigning onenter');
+ c1.dispatchEvent(ev);
+ assert_true(ran, 'dispatching event');
+ c1.onenter = null;
+ assert_equals(c1.onenter, null, 'assigning null');
+ ran = false;
+ c1.dispatchEvent(ev);
+ assert_false(ran, 'dispatching event after nulling onenter');
+});
+test(function(){
+ c1.addEventListener('enter', cb, false);
+ c1.dispatchEvent(ev);
+ assert_true(ran);
+ c1.removeEventListener('enter', cb, false);
+ ran = false;
+ c1.dispatchEvent(ev);
+ assert_false(ran);
+}, 'TextTrackCue.addEventListener/removeEventListener');
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/onexit.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/onexit.html
new file mode 100644
index 0000000000..815377e4d1
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/onexit.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<title>TextTrackCue.onexit</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.c1 = new VTTCue(0, 1, 'text1');
+ window.ev = new Event('exit');
+ window.ran = false;
+ window.cb = function() { ran = true; };
+});
+test(function(){
+ assert_equals(c1.onexit, null, 'initial value');
+ c1.onexit = undefined;
+ assert_equals(c1.onexit, null, 'assigning undefined');
+ c1.onexit = cb;
+ assert_equals(c1.onexit, cb, 'assigning onexit');
+ c1.dispatchEvent(ev);
+ assert_true(ran, 'dispatching event');
+ c1.onexit = null;
+ assert_equals(c1.onexit, null, 'assigning null');
+ ran = false;
+ c1.dispatchEvent(ev);
+ assert_false(ran, 'dispatching event after nulling onexit');
+});
+test(function(){
+ c1.addEventListener('exit', cb, false);
+ c1.dispatchEvent(ev);
+ assert_true(ran);
+ c1.removeEventListener('exit', cb, false);
+ ran = false;
+ c1.dispatchEvent(ev);
+ assert_false(ran);
+}, 'TextTrackCue.addEventListener/removeEventListener');
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/pauseOnExit.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/pauseOnExit.html
new file mode 100644
index 0000000000..31ea4c63b7
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/pauseOnExit.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<title>TextTrackCue.pauseOnExit</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.video = document.createElement('video');
+ window.t1 = video.addTextTrack('subtitles');
+ document.body.appendChild(video);
+});
+test(function(){
+ var c1 = new VTTCue(0, 1, 'text1');
+ assert_equals(c1.pauseOnExit, false);
+ c1.pauseOnExit = null;
+ assert_equals(c1.pauseOnExit, false);
+ c1.pauseOnExit = 'foo';
+ assert_equals(c1.pauseOnExit, true);
+}, document.title+', script-created cue');
+
+var t_parsed = async_test(document.title+', parsed cue');
+t_parsed.step(function(){
+ var t = document.createElement('track');
+ t.onload = this.step_func(function(){
+ var c1 = t.track.cues[0];
+ assert_equals(c1.pauseOnExit, false);
+ c1.pauseOnExit = null;
+ assert_equals(c1.pauseOnExit, false);
+ c1.pauseOnExit = 'foo';
+ assert_equals(c1.pauseOnExit, true);
+ this.done();
+ });
+ t.onerror = this.step_func(function() {
+ assert_unreached('got error event');
+ });
+ t.src = 'data:text/vtt,'+encodeURIComponent('WEBVTT\n\n00:00:00.000 --> 00:00:00.001\ntest');
+ t.track.mode = 'showing';
+ video.appendChild(t);
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/startTime.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/startTime.html
new file mode 100644
index 0000000000..7fba1df415
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/startTime.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<title>TextTrackCue.startTime</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.video = document.createElement('video');
+ window.t1 = video.addTextTrack('subtitles');
+ document.body.appendChild(video);
+});
+test(function(){
+ var c1 = new VTTCue(-1, 1, 'text1');
+ assert_equals(c1.startTime, -1);
+ c1.startTime = c1.startTime;
+ assert_equals(c1.startTime, -1);
+ assert_throws_js(TypeError, function(){ c1.startTime = NaN; });
+ assert_throws_js(TypeError, function(){ c1.startTime = +Infinity; });
+ assert_throws_js(TypeError, function(){ c1.startTime = -Infinity; });
+}, document.title+', script-created cue');
+
+var t_parsed = async_test(document.title+', parsed cue');
+t_parsed.step(function(){
+ var t = document.createElement('track');
+ t.onload = this.step_func(function(){
+ var c = t.track.cues;
+ assert_equals(c[0].startTime, 0);
+ assert_equals(c[1].startTime, 3600);
+ this.done();
+ });
+ t.onerror = this.step_func(function() {
+ assert_unreached('got error event');
+ });
+ t.src = 'data:text/vtt,'+encodeURIComponent('WEBVTT\n\n00:00:00.000 --> 00:00:00.001\ntest'+
+ '\n\nfoobar\n01:00:00.000 --> 01:00:00.001\ntest');
+ t.track.mode = 'showing';
+ video.appendChild(t);
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/track.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/track.html
new file mode 100644
index 0000000000..219e3e703b
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/track.html
@@ -0,0 +1,38 @@
+<!doctype html>
+<title>TextTrackCue.track</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.video = document.createElement('video');
+ window.t1 = video.addTextTrack('subtitles');
+ document.body.appendChild(video);
+});
+test(function(){
+ var c1 = new VTTCue(0, 1, 'text1');
+ assert_equals(c1.track, null);
+ t1.addCue(c1);
+ assert_equals(c1.track, t1);
+ t1.removeCue(c1);
+ assert_equals(c1.track, null);
+}, document.title+', script-created cue');
+
+var t_parsed = async_test(document.title+', parsed cue');
+t_parsed.step(function(){
+ var t = document.createElement('track');
+ t.onload = this.step_func(function(){
+ var c = t.track.cues[0];
+ assert_equals(c.track, t.track);
+ t.track.removeCue(c);
+ assert_equals(c.track, null);
+ this.done();
+ });
+ t.onerror = this.step_func(function() {
+ assert_unreached('got error event');
+ });
+ t.src = 'data:text/vtt,'+encodeURIComponent('WEBVTT\n\n00:00:00.000 --> 00:00:00.001\ntest');
+ t.track.mode = 'showing';
+ video.appendChild(t);
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCueList/getCueById.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCueList/getCueById.html
new file mode 100644
index 0000000000..8184189b05
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCueList/getCueById.html
@@ -0,0 +1,53 @@
+<!doctype html>
+<title>TextTrackCueList.getCueById</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function(){
+ var video = document.createElement('video');
+ var t = video.addTextTrack('subtitles');
+ document.body.appendChild(video);
+ var cues = t.cues;
+ var c = new VTTCue(0, 1, 'text1');
+ t.addCue(c);
+ assert_equals(cues.getCueById(""), null, '""');
+ assert_equals(cues.getCueById(null), null, 'null');
+ assert_equals(cues.getCueById(undefined), null, 'undefined');
+}, document.title+ ', no id');
+test(function(){
+ var video = document.createElement('video');
+ var t = video.addTextTrack('subtitles');
+ document.body.appendChild(video);
+ var cues = t.cues;
+ var c = new VTTCue(0, 1, 'text1');
+ c.id = 'foo';
+ t.addCue(c);
+ assert_equals(cues.getCueById(""), null, '""');
+ assert_equals(cues.getCueById("foo"), c, '"foo"');
+ assert_equals(cues.getCueById({toString:function(){return "foo"}}), c, 'object');
+}, document.title+ ', id foo');
+test(function(){
+ var video = document.createElement('video');
+ var t = video.addTextTrack('subtitles');
+ document.body.appendChild(video);
+ var cues = t.cues;
+ var c = new VTTCue(0, 1, 'text1');
+ c.id = '1';
+ t.addCue(c);
+ assert_equals(cues.getCueById(""), null, '""');
+ assert_equals(cues.getCueById("1"), c, '"1"');
+ assert_equals(cues.getCueById(1), c, '1');
+}, document.title+ ', no 1');
+test(function(){
+ var video = document.createElement('video');
+ var t = video.addTextTrack('subtitles');
+ document.body.appendChild(video);
+ var cues = t.cues;
+ var c = new VTTCue(0, 1, 'text1');
+ c.id = 'a\u0000b';
+ t.addCue(c);
+ assert_equals(cues.getCueById("a\u0000b"), c, '"a\\u0000b"');
+ assert_equals(cues.getCueById("a"), null, '"a"');
+}, document.title+ ', id a\\u0000b');
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCueList/getter.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCueList/getter.html
new file mode 100644
index 0000000000..8056d24543
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCueList/getter.html
@@ -0,0 +1,49 @@
+<!doctype html>
+<title>TextTrackCueList getter</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.video = document.createElement('video');
+ window.t1 = video.addTextTrack('subtitles');
+ document.body.appendChild(video);
+});
+test(function(){
+ var cues = t1.cues;
+ assert_equals(cues[0], undefined, 'cues[0] before');
+ var c1 = new VTTCue(0, 1, 'text1');
+ t1.addCue(c1);
+ assert_equals(cues[0], c1, 'cues[0]');
+ assert_equals(cues[1], undefined, 'cues[1]');
+ assert_equals(cues[-1], undefined, 'cues[-1]');
+ t1.removeCue(c1);
+ assert_equals(cues[0], undefined, 'cues[0] after');
+});
+test(function(){
+ var cues = t1.cues;
+ assert_equals(cues[0], undefined);
+ cues[0] = 'foo';
+ assert_equals(cues[0], undefined);
+ var c1 = new VTTCue(0, 1, 'text1');
+ t1.addCue(c1);
+ assert_equals(cues[0], c1);
+ cues[0] = 'foo';
+ assert_equals(cues[0], c1);
+ t1.removeCue(c1);
+}, document.title+', no indexed set/create');
+test(function(){
+ 'use strict';
+ var cues = t1.cues;
+ assert_equals(cues[0], undefined);
+ assert_throws_js(TypeError, function() { cues[0] = 'foo'; });
+ assert_equals(cues[0], undefined);
+ var c1 = new VTTCue(0, 1, 'text1');
+ t1.addCue(c1);
+ assert_equals(cues[0], c1);
+ assert_throws_js(TypeError, function() { cues[0] = 'foo'; });
+ assert_equals(cues[0], c1);
+ t1.removeCue(c1);
+}, document.title+', no indexed set/create (strict)');
+
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCueList/length.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCueList/length.html
new file mode 100644
index 0000000000..91e6e7ff99
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCueList/length.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<title>TextTrackCueList.length</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.video = document.createElement('video');
+ window.t1 = video.addTextTrack('subtitles');
+ document.body.appendChild(video);
+});
+test(function(){
+ var cues = t1.cues;
+ assert_equals(cues.length, 0);
+ var c1 = new VTTCue(0, 1, 'text1');
+ t1.addCue(c1);
+ assert_equals(cues.length, 1);
+ t1.removeCue(c1);
+ assert_equals(cues.length, 0);
+});
+
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/getTrackById.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/getTrackById.html
new file mode 100644
index 0000000000..b701dd5e73
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/getTrackById.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<title>TextTrackList.getTrackById</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function(){
+ var video = document.createElement('video');
+ var track1 = video.addTextTrack('subtitles');
+ var track2 = video.addTextTrack('subtitles');
+ assert_equals(track1.id, '');
+ assert_equals(track2.id, '');
+ assert_equals(video.textTracks.getTrackById(''), track1);
+ assert_equals(video.textTracks.getTrackById('fake-id'), null);
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/getter.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/getter.html
new file mode 100644
index 0000000000..9baa459419
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/getter.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<title>TextTrackList getter</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.video = document.createElement('video');
+ video.addTextTrack('subtitles', 'b');
+ window.track = document.createElement('track');
+ track.label = 'a';
+ video.appendChild(track);
+ video.addTextTrack('subtitles', 'c');
+});
+test(function(){
+ assert_equals(video.textTracks[0].label, 'a');
+ assert_equals(video.textTracks[1].label, 'b');
+ assert_equals(video.textTracks[2].label, 'c');
+});
+test(function(){
+ var track_before = video.textTracks[0];
+ video.textTracks[0] = 'foo';
+ assert_equals(video.textTracks[0], track_before);
+}, document.title+', no indexed set/create');
+test(function(){
+ 'use strict';
+ var track_before = video.textTracks[0];
+ assert_throws_js(TypeError, function(){ video.textTracks[0] = 'foo'; });
+ assert_equals(video.textTracks[0], track_before);
+}, document.title+', no indexed set/create (strict)');
+
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/length.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/length.html
new file mode 100644
index 0000000000..7a24130d10
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/length.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>TextTrackList.length</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.video = document.createElement('video');
+ video.addTextTrack('subtitles');
+ window.track = document.createElement('track');
+ video.appendChild(track);
+ video.addTextTrack('subtitles');
+});
+test(function(){
+ assert_equals(video.textTracks.length, 3);
+});
+
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/onaddtrack.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/onaddtrack.html
new file mode 100644
index 0000000000..114ca89046
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/onaddtrack.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<title>TextTrackList.onaddtrack</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.tracks = document.createElement('video').textTracks;
+ window.ev = new Event('addtrack');
+ window.ran = false;
+ window.cb = function() { ran = true; };
+});
+test(function(){
+ assert_equals(tracks.onaddtrack, null);
+ tracks.onaddtrack = cb;
+ assert_equals(tracks.onaddtrack, cb);
+ tracks.dispatchEvent(ev);
+ assert_true(ran);
+ tracks.onaddtrack = null;
+ ran = false;
+ tracks.dispatchEvent(ev);
+ assert_false(ran);
+});
+test(function(){
+ tracks.addEventListener('addtrack', cb, false);
+ tracks.dispatchEvent(ev);
+ assert_true(ran);
+ tracks.removeEventListener('addtrack', cb, false);
+ ran = false;
+ tracks.dispatchEvent(ev);
+ assert_false(ran);
+}, 'TextTrackList.addEventListener/removeEventListener');
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/onremovetrack.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/onremovetrack.html
new file mode 100644
index 0000000000..b8da16ce2e
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/onremovetrack.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<title>TextTrackList.onremovetrack</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.tracks = document.createElement('video').textTracks;
+ window.ev = new Event('removetrack');
+ window.ran = false;
+ window.cb = function() { ran = true; };
+});
+test(function(){
+ assert_equals(tracks.onremovetrack, null);
+ tracks.onremovetrack = cb;
+ assert_equals(tracks.onremovetrack, cb);
+ tracks.dispatchEvent(ev);
+ assert_true(ran);
+ tracks.onremovetrack = null;
+ ran = false;
+ tracks.dispatchEvent(ev);
+ assert_false(ran);
+});
+test(function(){
+ tracks.addEventListener('removetrack', cb, false);
+ tracks.dispatchEvent(ev);
+ assert_true(ran);
+ tracks.removeEventListener('removetrack', cb, false);
+ ran = false;
+ tracks.dispatchEvent(ev);
+ assert_false(ran);
+}, 'TextTrackList.addEventListener/removeEventListener');
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TrackEvent/constructor.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TrackEvent/constructor.html
new file mode 100644
index 0000000000..cb5b89711f
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TrackEvent/constructor.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<title>TrackEvent constructor</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function(){
+ var ev = new TrackEvent('foo');
+ assert_true(ev instanceof TrackEvent, 'ev instanceof TrackEvent');
+ assert_true(ev instanceof Event, 'ev instanceof Event');
+ assert_equals(ev.track, null, 'ev.track');
+ ev.track = {};
+ assert_equals(ev.track, null, 'ev.track after assignment');
+}, document.title+', one arg');
+test(function(){
+ var video = document.createElement('video');
+ var testTrack = video.addTextTrack('subtitles', 'foo', 'foo');
+ var ev = new TrackEvent('foo', {track: testTrack});
+ assert_true(ev instanceof TrackEvent, 'ev instanceof TrackEvent');
+ assert_true(ev instanceof Event, 'ev instanceof Event');
+ assert_equals(ev.track, testTrack, 'ev.track');
+ ev.track = {};
+ assert_equals(ev.track, testTrack, 'ev.track after assignment');
+}, document.title+', two args');
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TrackEvent/createEvent.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TrackEvent/createEvent.html
new file mode 100644
index 0000000000..1d7eb540c3
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/interfaces/TrackEvent/createEvent.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>TrackEvent created with createEvent</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function(){
+ // https://www.w3.org/Bugs/Public/show_bug.cgi?id=17268
+ assert_throws_dom('NOT_SUPPORTED_ERR', function() {
+ var ev = document.createEvent('TrackEvent');
+ });
+ var ev = new TrackEvent('foo');
+ assert_false('initTrackEvent' in ev, 'initTrackEvent');
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/autoplay-overrides-preload.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/autoplay-overrides-preload.html
new file mode 100644
index 0000000000..332184d55c
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/autoplay-overrides-preload.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML>
+<title>autoplay overrides preload</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<div id=log></div>
+<script>
+['none', 'metadata'].forEach(function(preload) {
+ ['first', 'last'].forEach(function(order) {
+ async_test(function(t) {
+ var a = document.createElement('audio');
+ a.src = getAudioURI('/media/sound_5');
+ if (order == 'first') {
+ a.autoplay = true;
+ a.preload = preload;
+ } else {
+ a.preload = preload;
+ a.autoplay = true;
+ }
+ a.addEventListener('error', t.unreached_func());
+ a.addEventListener('playing', t.step_func(function() {
+ assert_equals(a.readyState, a.HAVE_ENOUGH_DATA);
+ assert_false(a.paused);
+ t.done();
+ }));
+ }, 'autoplay (set ' + order + ') overrides preload "' + preload + '"');
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/load-events-networkState.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/load-events-networkState.html
new file mode 100644
index 0000000000..d163c0e5b9
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/load-events-networkState.html
@@ -0,0 +1,91 @@
+<!doctype html>
+<title>load() fires abort/emptied events when networkState is not NETWORK_EMPTY</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<div id=log></div>
+<script>
+// Load media resource
+// https://html.spec.whatwg.org/multipage/media.html#loading-the-media-resource
+function load_test(t, v) {
+ assert_not_equals(v.networkState, v.NETWORK_EMPTY);
+
+ var expected_events = [];
+ if (v.networkState == v.NETWORK_LOADING || v.networkState == v.NETWORK_IDLE) {
+ expected_events.push('abort');
+ }
+
+ if (v.networkState != v.NETWORK_EMPTY) {
+ expected_events.push('emptied');
+ }
+
+ if (v.currentTime != 0.0) {
+ expected_events.push('timeupdate');
+ }
+
+ var actual_events = [];
+ v.onabort = v.onemptied = v.ontimeupdate = t.step_func(function(e) {
+ actual_events.push(e.type);
+ });
+
+ v.onloadstart = t.step_func(function() {
+ assert_array_equals(actual_events, expected_events);
+ t.done();
+ });
+
+ v.load();
+
+ assert_array_equals(actual_events, [], 'events should be fired in queued tasks');
+}
+
+async_test(function(t) {
+ var v = document.createElement('video');
+ // suspend is fired optionally "if the user agent intends to not attempt to
+ // fetch the resource" or "once the entire media resource has been fetched"
+ v.preload = 'none';
+ v.src = getAudioURI('/media/sound_5');
+ v.onerror = t.unreached_func();
+ v.onsuspend = t.step_func(function() {
+ v.onsuspend = null;
+ assert_equals(v.networkState, v.NETWORK_IDLE);
+ load_test(t, v);
+ });
+}, 'NETWORK_IDLE');
+
+// Test if media element receives `emptied` before `timeupdate`
+async_test(function(t) {
+ var v = document.createElement('video');
+ v.src = getAudioURI('/media/sound_5');
+ v.onerror = t.unreached_func();
+ v.onloadeddata = t.step_func(function() {
+ v.onloadeddata = null;
+ assert_not_equals(v.networkState, v.NETWORK_EMPTY);
+ // Modify current time to ensure that loading would trigger `timeupdate` by
+ // resetting the current time.
+ v.currentTime = 1.0;
+ load_test(t, v);
+ });
+}, 'NETWORK_DISPATCH_EMPTIED_BEFORE_TIMEUPDATE');
+
+async_test(function(t) {
+ var v = document.createElement('video');
+ v.src = 'resources/delayed-broken-video.py';
+ v.onerror = t.unreached_func();
+ v.onloadstart = t.step_func(function() {
+ v.onloadstart = null;
+ assert_equals(v.networkState, v.NETWORK_LOADING);
+ load_test(t, v);
+ });
+}, 'NETWORK_LOADING');
+
+async_test(function(t) {
+ var v = document.createElement('video');
+ v.src = 'data:,';
+ v.onerror = t.step_func(function() {
+ v.onerror = null;
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE);
+ load_test(t, v);
+ });
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE);
+}, 'NETWORK_NO_SOURCE');
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/load-removes-queued-error-event.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/load-removes-queued-error-event.html
new file mode 100644
index 0000000000..54d5c28dad
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/load-removes-queued-error-event.html
@@ -0,0 +1,44 @@
+<!doctype html>
+<title>load() removes queued error event</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+// The loadstart and error event firing tasks are queued in the synchronous
+// section of the resource selection algorithm, so no tasks can come between
+// them. Calling load() in the loadstart event handler removes the queued error
+// event task at very latest opportunity, failing any implementation that fires
+// the events in the same task.
+
+async_test(function(t) {
+ var v = document.createElement('video');
+ var events = [];
+ v.onloadstart = v.onerror = t.step_func(function(e) {
+ events.push(e.type);
+ if (events.length == 1) {
+ v.load();
+ } else if (events.length == 3) {
+ assert_array_equals(events, ['loadstart', 'loadstart', 'error']);
+ t.done();
+ }
+ });
+ v.src = '';
+}, 'video error event');
+
+async_test(function(t) {
+ var v = document.createElement('video');
+ var s = document.createElement('source');
+ var events = [];
+ v.onloadstart = s.onerror = t.step_func(function(e) {
+ events.push(e.type);
+ if (events.length == 1) {
+ v.load();
+ } else if (events.length == 3) {
+ assert_array_equals(events, ['loadstart', 'loadstart', 'error']);
+ t.done();
+ }
+ });
+ v.onerror = t.step_func(function() { assert_unreached(); });
+ v.appendChild(s);
+}, 'source error event');
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-insert-before.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-insert-before.html
new file mode 100644
index 0000000000..39c9887505
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-insert-before.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<title>inserting another source before the candidate</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var v;
+function createSource(src) {
+ var source = document.createElement('source');
+ source.src = src;
+ return source;
+}
+var t = async_test(function(t) {
+ v = document.createElement('video');
+ v.addEventListener('loadstart', t.step_func(function() {
+ assert_equals(v.currentSrc.substr(v.currentSrc.lastIndexOf('#')), '#a');
+ t.done();
+ }), false);
+ v.appendChild(createSource('#a')); // invokes resource selection
+});
+</script>
+<!-- now resource selection algorithm will continue its sync section (the </script> tag below provides a stable state) -->
+<!-- #a is candidate -->
+<!-- pointer is between #a and the end of the list -->
+<script>
+t.step(function() {
+ v.insertBefore(createSource('#b'), v.firstChild); // pointer is unchanged, #a is still candidate
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-moved.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-moved.html
new file mode 100644
index 0000000000..f59452e0d8
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-moved.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<title>moving the candidate source</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var s;
+var t = async_test(function(t) {
+ var v = document.createElement('video');
+ s = document.createElement('source');
+ s.src = 'resources/delayed-broken-video.py';
+ s.onerror = t.step_func(function() { t.done(); });
+ v.appendChild(s); // invokes resource selection
+ onload = t.step_func(function() { assert_unreached(); });
+});
+</script>
+<script>
+t.step(function() {
+ document.body.appendChild(s);
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-remove-addEventListener.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-remove-addEventListener.html
new file mode 100644
index 0000000000..0c1e6f0ad8
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-remove-addEventListener.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<title>removing the candidate source, addEventListener</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var v;
+function createSource(src) {
+ var source = document.createElement('source');
+ source.src = src;
+ return source;
+}
+var t = async_test(function(t) {
+ v = document.createElement('video');
+ v.appendChild(createSource('resources/delayed-broken-video.py')); // invokes resource selection
+ v.firstChild.addEventListener('error', t.step_func(function() { t.done(); }), false);
+});
+</script>
+<!-- now resource selection algorithm will continue its sync section (the </script> tag below provides a stable state) -->
+<!-- the <source> is candidate -->
+<!-- pointer is between the <source> and the end of the list -->
+<script>
+t.step(function() {
+ v.removeChild(v.firstChild); // tests that we fire 'error' on it despite being removed
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-remove-no-listener.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-remove-no-listener.html
new file mode 100644
index 0000000000..f384eb3121
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-remove-no-listener.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<title>removing the candidate source, no listener</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var v;
+function createSource(src) {
+ var source = document.createElement('source');
+ source.src = src;
+ return source;
+}
+var t = async_test(function(t) {
+ v = document.createElement('video');
+ v.appendChild(createSource('resources/delayed-broken-video.py')); // invokes resource selection
+});
+</script>
+<!-- now resource selection algorithm will continue its sync section (the </script> tag below provides a stable state) -->
+<!-- the <source> is candidate -->
+<!-- pointer is between the <source> and the end of the list -->
+<script>
+t.step(function() {
+ v.removeChild(v.firstChild); // just tests that we don't crash
+ onload = t.step_func(function() { t.done(); });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-remove-onerror.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-remove-onerror.html
new file mode 100644
index 0000000000..c295c85bfc
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-remove-onerror.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<title>removing the candidate source, onerror</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var v;
+function createSource(src) {
+ var source = document.createElement('source');
+ source.src = src;
+ return source;
+}
+var t = async_test(function(t) {
+ v = document.createElement('video');
+ v.appendChild(createSource('resources/delayed-broken-video.py')); // invokes resource selection
+ v.firstChild.onerror = t.step_func(function() { t.done(); });
+});
+</script>
+<!-- now resource selection algorithm will continue its sync section (the </script> tag below provides a stable state) -->
+<!-- the <source> is candidate -->
+<!-- pointer is between the <source> and the end of the list -->
+<script>
+t.step(function() {
+ v.removeChild(v.firstChild); // tests that we fire 'error' on it despite being removed
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-currentSrc.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-currentSrc.html
new file mode 100644
index 0000000000..61902161ed
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-currentSrc.html
@@ -0,0 +1,93 @@
+<!doctype html>
+<title>currentSrc should not be reset when changing source</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<audio src="/media/sine440.mp3"></audio>
+<script>
+let v;
+let t = async_test("Test currentSrc behaviour in various playback scenarios");
+v = document.querySelector('audio');
+function queueTaskAndStep(f) {
+ step_timeout(function() {
+ t.step(f);
+ }, 0);
+}
+
+function next() {
+ let testcase = tests.shift();
+ if (!testcase) {
+ t.done();
+ return;
+ }
+ step_timeout(testcase, 0);
+}
+
+let tests = [
+ function() {
+ v.src = "/media/sound_0.mp3";
+ queueTaskAndStep(function() {
+ assert_true(v.currentSrc.indexOf("sound_0.mp3") != -1, "currentSrc must be equal to the source after load if present");
+ next();
+ });
+ },
+ function() {
+ v.src = URL.createObjectURL(new MediaSource());
+ queueTaskAndStep(function() {
+ assert_not_equals(v.currentSrc, "", "currentSrc must not be equal to the empty string after load if playing a MediaSource from the src attribute");
+ next();
+ });
+ },
+ function() {
+ fetch('/media/sound_0.mp3')
+ .then(function(response) {
+ return response.arrayBuffer();
+ }).then((b) => {
+ v.src = URL.createObjectURL(new Blob([new Uint8Array(b)], ["audio/mpeg"]));
+ queueTaskAndStep(function() {
+ assert_not_equals(v.currentSrc, "", "currentSrc must be not equal to the empty string after load if playing a Blob from the src attribute");
+ next();
+ });
+ });
+ },
+ function() {
+ v.src = "/media/sound_0.mp3";
+ // Source should be ignored when there is an `src`
+ let sourceNode = document.createElement("source");
+ sourceNode.setAttribute("src", "/media/sine440.mp3");
+ sourceNode.setAttribute("type", "audio/mpeg");
+ v.appendChild(sourceNode);
+ queueTaskAndStep(function() {
+ assert_true(v.currentSrc.indexOf("sine440.mp3") == -1, "The src attribute takes precedence over any source child element when both are preset");
+ next();
+ })
+ },
+ function() {
+ // But taken into account when there is no `src` attribute;
+ v.src = "";
+ v.removeAttribute("src");
+ queueTaskAndStep(function() {
+ assert_true(v.currentSrc.indexOf("sine440.mp3") != -1, "The child source element is the current source when no src attribute is present");
+ next();
+ });
+ },
+ function() {
+ v.firstChild.remove();
+ v.src = "https://test:test/";
+ queueTaskAndStep(function() {
+ assert_true(v.currentSrc.indexOf("sine440.mp3") != -1, "Not reset when a new load errors");
+ next();
+ });
+ },
+ function() {
+ v.srcObject = new MediaStream();
+ queueTaskAndStep(function() {
+ assert_equals(v.currentSrc, "", "When playing a MediaStream, currentSrc should also be reset to an empty string");
+ next();
+ });
+ }
+];
+
+next();
+
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-audio-constructor-no-src.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-audio-constructor-no-src.html
new file mode 100644
index 0000000000..cb2a579597
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-audio-constructor-no-src.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<title>NOT invoking resource selection with new Audio() sans src</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var a = new Audio();
+ assert_equals(a.networkState, a.NETWORK_EMPTY);
+ a.onloadstart = t.step_func(function() { assert_unreached(); });
+ window.onload = t.step_func(function() { t.done(); });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-audio-constructor.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-audio-constructor.html
new file mode 100644
index 0000000000..662129756f
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-audio-constructor.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<title>invoking resource selection with new Audio(src)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var a = new Audio('');
+ a.onloadstart = t.step_func(function() { t.done(); });
+ window.onload = t.step_func(function() { assert_unreached(); });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-in-sync-event.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-in-sync-event.html
new file mode 100644
index 0000000000..1635598efd
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-in-sync-event.html
@@ -0,0 +1,30 @@
+<!doctype html>
+<title>await a stable state and sync event handlers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<video></video>
+<script>
+var v;
+var t = async_test(function(t) {
+ v = document.querySelector('video');
+ var a = document.createElement('a');
+ a.onclick = t.step_func(function() {
+ v.setAttribute('src', '#'); // invokes media load which invokes resource selection
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState in onclick handler');
+ });
+ a.click(); // sync fires click, so sets src
+ // now we should still await a stable state because the script hasn't
+ // finished, the event handler has just returned
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState after click()');
+ v.removeAttribute('src');
+});
+t.step(function() {
+ // now the sync section of resource selection should have run and should
+ // have found no src="" or <source> thus networkState being set to NETWORK_EMPTY.
+ // if the sync section was run when onclick returned, then networkState
+ // would be either NETWORK_LOADING or NETWORK_NO_SOURCE.
+ assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState after src removed');
+ t.done();
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-fragment-into-document.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-fragment-into-document.html
new file mode 100644
index 0000000000..5d4c32f670
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-fragment-into-document.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<title>NOT invoking resource selection by inserting document fragment into a document</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var v;
+var t = async_test(function(t) {
+ v = document.createElement('video');
+ var fragment = document.createDocumentFragment();
+ fragment.appendChild(v);
+ assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState after fragment.appendChild(v)');
+ document.body.appendChild(fragment);
+ assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState after document.body.appendChild(fragment)');
+});
+</script>
+<script>
+t.step(function() {
+ assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState in separate script');
+ t.done();
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-into-document.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-into-document.html
new file mode 100644
index 0000000000..2f9ec978a5
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-into-document.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<title>NOT invoking resource selection by inserting into a document</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function(t) {
+ var v = document.createElement('video');
+ document.body.appendChild(v);
+ assert_equals(v.networkState, v.NETWORK_EMPTY);
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-into-iframe.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-into-iframe.html
new file mode 100644
index 0000000000..45d133d878
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-into-iframe.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<title>NOT invoking resource selection by inserting into other document with src set</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<iframe hidden></iframe>
+<script>
+async_test(function(t) {
+ var v = document.createElement('video');
+ v.src = 'data:,';
+ v.onerror = t.step_func(function() {
+ assert_equals(v.readyState, v.HAVE_NOTHING);
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE);
+ var iframe = document.querySelector('iframe');
+ iframe.contentDocument.body.appendChild(v);
+ v.onloadstart = t.step_func(function() { assert_unreached(); });
+ // wait for an event after the above
+ var v2 = document.createElement('video');
+ v2.src = 'data:,';
+ v2.onloadstart = t.step_func(function() { t.done(); });
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-parent-into-document.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-parent-into-document.html
new file mode 100644
index 0000000000..6da34344fd
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-parent-into-document.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>NOT invoking resource selection by inserting parent into a document</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var v = document.createElement('video');
+ var div = document.createElement('div');
+ div.appendChild(v);
+ assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState after div.appendChild(v)');
+ document.body.appendChild(div);
+ assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState after document.body.appendChild(div)');
+ window.onload = t.step_func(function() {
+ assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState in window.onload');
+ t.done();
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-in-div.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-in-div.html
new file mode 100644
index 0000000000..b79bea52f1
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-in-div.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>NOT invoking resource selection by inserting &lt;source> in &lt;div> in &lt;video></title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<video><div></div></video>
+<script>
+async_test(function(t) {
+ var v = document.querySelector('video');
+ v.onloadstart = t.step_func(function() { assert_unreached(); });
+ v.firstChild.appendChild(document.createElement('source'));
+ window.onload = t.step_func(function() { t.done(); });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-in-namespace.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-in-namespace.html
new file mode 100644
index 0000000000..b73f229ecc
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-in-namespace.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>NOT invoking resource selection by inserting &lt;source> in the wrong namespace</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<video></video>
+<script>
+async_test(function(t) {
+ var v = document.querySelector('video');
+ v.onloadstart = t.step_func(function() { assert_unreached(); });
+ v.appendChild(document.createElementNS('bogus','source'));
+ window.onload = t.step_func(function() { t.done(); });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-networkState.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-networkState.html
new file mode 100644
index 0000000000..5ef6e4cb3b
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-networkState.html
@@ -0,0 +1,38 @@
+<!doctype html>
+<title>NOT invoking resource selection by inserting &lt;source> when networkState is not NETWORK_EMPTY</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var loadstartCount = 0;
+var s1ErrorCount = 0;
+var s2ErrorCount = 0;
+var v;
+var t = async_test(function(t) {
+ v = document.createElement('video');
+ v.onloadstart = function() { loadstartCount++; };
+ var s1 = document.createElement('source');
+ s1.src = 'resources/delayed-broken-video.py';
+ s1.onerror = function() { s1ErrorCount++; };
+ v.appendChild(s1); // invokes resource selection
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState in first script');
+});
+</script>
+<script>
+t.step(function() {
+ assert_equals(v.networkState, v.NETWORK_LOADING, 'networkState in second script');
+ assert_equals(s1ErrorCount, 0, 's1ErrorCount in second script');
+ var s2 = document.createElement('source');
+ s2.onerror = t.step_func(function() {
+ s2ErrorCount++;
+ assert_equals(s1ErrorCount, 1, 's1ErrorCount in s2.onerror');
+ });
+ v.appendChild(s2);
+ onload = t.step_func(function() {
+ assert_equals(s2ErrorCount, 1, 's2ErrorCount in window.onload');
+ assert_equals(loadstartCount, 1, 'loadstartCount in window.onload'); // reliable if https://www.w3.org/Bugs/Public/show_bug.cgi?id=24353 is fixed
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState in window.onload'); // See Waiting step
+ t.done();
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-not-in-document.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-not-in-document.html
new file mode 100644
index 0000000000..2007b2e8b3
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-not-in-document.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<title>invoking resource selection by inserting &lt;source> in video not in a document</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var v = document.createElement('video');
+ v.onloadstart = t.step_func(function() { t.done(); });
+ v.appendChild(document.createElement('source'));
+ window.onload = t.step_func(function() { assert_unreached(); });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source.html
new file mode 100644
index 0000000000..969daad623
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>invoking resource selection by inserting &lt;source></title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<video></video>
+<script>
+async_test(function(t) {
+ var v = document.querySelector('video');
+ v.onloadstart = t.step_func(function() { t.done(); });
+ v.appendChild(document.createElement('source'));
+ window.onload = t.step_func(function() { assert_unreached(); });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-load.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-load.html
new file mode 100644
index 0000000000..909c72cd15
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-load.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>invoking resource selection with load()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var v;
+var t = async_test(function(t) {
+ v = document.createElement('video');
+ assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState after creating v');
+ v.load();
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState after v.load()');
+});
+</script>
+<script>
+t.step(function() {
+ assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState in separate script');
+ t.done();
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-pause-networkState.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-pause-networkState.html
new file mode 100644
index 0000000000..18561a2649
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-pause-networkState.html
@@ -0,0 +1,28 @@
+<!doctype html>
+<title>NOT invoking resource selection with pause() when networkState is not NETWORK_EMPTY</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<video></video>
+<script>
+var v;
+var t = async_test(function(t) {
+ v = document.querySelector('video');
+ v.src = 'data:,';
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState after setting src');
+ var errorCount = 0;
+ v.onerror = t.step_func(function() {
+ errorCount++;
+ if (errorCount == 1) {
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState in onerror');
+ v.pause(); // should not invoke RSA. if it does, error will be fired again.
+ } else {
+ assert_unreached();
+ }
+ });
+ onload = t.step_func(function() {
+ assert_equals(errorCount, 1, 'errorCount');
+ t.done();
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-pause.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-pause.html
new file mode 100644
index 0000000000..4f1bca74dd
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-pause.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>invoking resource selection with pause()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var v;
+var t = async_test(function(t) {
+ v = document.createElement('video');
+ assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState after creating v');
+ v.pause();
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState after v.pause()');
+});
+</script>
+<script>
+t.step(function() {
+ assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState in separate script');
+ t.done();
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-play.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-play.html
new file mode 100644
index 0000000000..64a440080c
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-play.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>invoking resource selection with play()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var v;
+var t = async_test(function(t) {
+ v = document.createElement('video');
+ assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState after creating v');
+ v.play();
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState after v.play()');
+});
+</script>
+<script>
+t.step(function() {
+ assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState in separate script');
+ t.done();
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-from-document-networkState.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-from-document-networkState.html
new file mode 100644
index 0000000000..1eed276b20
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-from-document-networkState.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<title>NOT invoking resource selection with implicit pause() when networkState is not NETWORK_EMPTY</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<video></video>
+<script>
+var v;
+var t = async_test(function(t) {
+ v = document.querySelector('video');
+ v.src = 'data:,';
+ document.body.appendChild(v);
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState after setting src');
+ var errorCount = 0;
+ v.onerror = t.step_func(function() {
+ errorCount++;
+ if (errorCount == 1) {
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState in onerror');
+ document.body.removeChild(v); // invokes pause() which should not invoke RSA. if it does, error will be fired again.
+ } else {
+ assert_unreached();
+ }
+ });
+ onload = t.step_func(function() {
+ assert_equals(errorCount, 1, 'errorCount');
+ t.done();
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-from-document.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-from-document.html
new file mode 100644
index 0000000000..65d0f73114
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-from-document.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>NOT invoking resource selection by removing from document with NETWORK_EMPTY</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var v;
+test(function() {
+ v = document.createElement('video');
+ document.body.appendChild(v);
+ assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState after appending v to document');
+ v.parentNode.removeChild(v); // search for "When a media element is removed from a Document,"
+ assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState after removing v');
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-src.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-src.html
new file mode 100644
index 0000000000..6302ffeacf
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-src.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<title>NOT invoking media load or resource selection when removing the src attribute</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var v;
+var t = async_test(function(t) {
+ v = document.createElement('video');
+ v.setAttribute('src', ''); // invokes media load
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState after setting src');
+ var s = document.createElement('source');
+ s.onerror = this.step_func(function() { assert_unreached(); });
+ v.appendChild(s); // src is present so nothing happens here
+ onload = this.step_func(function() { t.done(); });
+});
+</script>
+<script>
+t.step(function() {
+ v.removeAttribute('src'); // nothing should happen
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-in-namespace.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-in-namespace.html
new file mode 100644
index 0000000000..438db124d2
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-in-namespace.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>NOT invoking load by setting src in the wrong namespace</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<video></video>
+<script>
+async_test(function(t) {
+ var v = document.querySelector('video');
+ v.onloadstart = t.step_func(function() { assert_unreached(); });
+ v.setAttributeNS('bogus','src', '');
+ window.onload = t.step_func(function() { t.done(); });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-networkState.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-networkState.html
new file mode 100644
index 0000000000..ed86dbe0c5
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-networkState.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<title>invoking load by setting src when networkState is not NETWORK_EMPTY</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function(t) {
+ var v = document.createElement('video');
+ v.play().catch(() => {}); // invokes resource selection and sets .paused to false
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState');
+ assert_false(v.paused, 'paused');
+ v.setAttribute('src', ''); // invokes media load which sets .paused to true
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState after setting src');
+ assert_true(v.paused, 'paused after setting src');
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-not-in-document.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-not-in-document.html
new file mode 100644
index 0000000000..f6c4f2406a
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-not-in-document.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<title>invoking load by setting src on video not in a document</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var v = document.createElement('video');
+ v.onloadstart = t.step_func(function() { t.done(); });
+ v.setAttribute('src','');
+ window.onload = t.step_func(function() { assert_unreached(); });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src.html
new file mode 100644
index 0000000000..e04b1b0580
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>invoking load by setting src</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<video></video>
+<script>
+async_test(function(t) {
+ var v = document.querySelector('video');
+ v.onloadstart = t.step_func(function() { t.done(); });
+ v.setAttribute('src', '');
+ window.onload = t.step_func(function() { assert_unreached(); });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-control.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-control.html
new file mode 100644
index 0000000000..dad5e5fd00
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-control.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<title>pointer updates (control test)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var a = 0;
+var b = 0;
+var c = 0;
+</script>
+<video
+ ><source onerror=a++
+ ><source onerror=b++ src='resources/delayed-broken-video.py'
+ ><source onerror=c++
+ ></video
+>
+<script>
+async_test(function(t) {
+ window.onload = t.step_func(function() {
+ assert_equals(a, 1, 'error events on a');
+ assert_equals(b, 1, 'error events on b');
+ assert_equals(c, 1, 'error events on c');
+ t.done();
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-insert-br.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-insert-br.html
new file mode 100644
index 0000000000..3ee141e306
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-insert-br.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<title>pointer updates (adding br elements)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var a = 0;
+var b = 0;
+var c = 0;
+</script>
+<video
+ ><source onerror=a++
+ ><source onerror=b++ src='resources/delayed-broken-video.py'
+ ><source onerror=c++
+ ></video
+>
+<script>
+async_test(function(t) {
+ var video = document.querySelector('video');
+ // add br elements
+ var br = document.createElement('br');
+ video.insertBefore(br, video.querySelector('[onerror="a++"]'));
+ video.insertBefore(br.cloneNode(false), video.querySelector('[onerror="b++"]'));
+ video.insertBefore(br.cloneNode(false), video.querySelector('[onerror="c++"]'));
+ video.appendChild(br.cloneNode(false));
+ window.onload = t.step_func(function() {
+ assert_equals(a, 1, 'error events on a');
+ assert_equals(b, 1, 'error events on b');
+ assert_equals(c, 1, 'error events on c');
+ t.done();
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-insert-source.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-insert-source.html
new file mode 100644
index 0000000000..2d32e6fca0
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-insert-source.html
@@ -0,0 +1,44 @@
+<!doctype html>
+<title>pointer updates (adding source elements)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var a = 0;
+var b = 0;
+var c = 0;
+var x1 = 0;
+var x2 = 0;
+var x3 = 0;
+var x4 = 0;
+</script>
+<video
+ ><source onerror=a++
+ ><source onerror=b++ src='resources/delayed-broken-video.py'
+ ><source onerror=c++
+ ></video
+>
+<script>
+async_test(function(t) {
+ var video = document.querySelector('video');
+ // add source elements
+ var source1 = document.createElement('source'); source1.onerror = function() { x1++; };
+ var source2 = document.createElement('source'); source2.onerror = function() { x2++; };
+ var source3 = document.createElement('source'); source3.onerror = function() { x3++; };
+ var source4 = document.createElement('source'); source4.onerror = function() { x4++; };
+ video.insertBefore(source1, video.querySelector('[onerror="a++"]'));
+ video.insertBefore(source2, video.querySelector('[onerror="b++"]'));
+ video.insertBefore(source3, video.querySelector('[onerror="c++"]'));
+ video.appendChild(source4);
+ window.onload = t.step_func(function() {
+ assert_equals(a, 1, 'error events on a');
+ assert_equals(b, 1, 'error events on b');
+ assert_equals(c, 1, 'error events on c');
+ assert_equals(x1, 0, 'error events on x1');
+ assert_equals(x2, 0, 'error events on x2');
+ assert_equals(x3, 1, 'error events on x3');
+ assert_equals(x4, 1, 'error events on x4');
+ t.done();
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-insert-text.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-insert-text.html
new file mode 100644
index 0000000000..15a4e4be06
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-insert-text.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<title>pointer updates (adding text nodes)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var a = 0;
+var b = 0;
+var c = 0;
+</script>
+<video
+ ><source onerror=a++
+ ><source onerror=b++ src='resources/delayed-broken-video.py'
+ ><source onerror=c++
+ ></video
+>
+<script>
+async_test(function(t) {
+ var video = document.querySelector('video');
+ // add text nodes
+ var text = document.createTextNode('x');
+ video.insertBefore(text, video.querySelector('[onerror="a++"]'));
+ video.insertBefore(text.cloneNode(false), video.querySelector('[onerror="b++"]'));
+ video.insertBefore(text.cloneNode(false), video.querySelector('[onerror="c++"]'));
+ video.appendChild(text.cloneNode(false));
+ window.onload = t.step_func(function() {
+ assert_equals(a, 1, 'error events on a');
+ assert_equals(b, 1, 'error events on b');
+ assert_equals(c, 1, 'error events on c');
+ t.done();
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-remove-source-after.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-remove-source-after.html
new file mode 100644
index 0000000000..0d1c940375
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-remove-source-after.html
@@ -0,0 +1,56 @@
+<!doctype html>
+<title>pointer updates (removing source element after pointer)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var a = 0;
+var b = 0;
+var c = 0;
+var x1 = 0;
+var x2 = 0;
+var x3 = 0;
+var x4 = 0;
+</script>
+<video
+ ><source onerror=a++
+ ><source onerror=b++ src='resources/delayed-broken-video.py'
+ ><source onerror=x1++
+ ><source onerror=x2++
+ ><source onerror=x3++
+ ><source onerror=x4++
+ ><source onerror=c++
+ ></video
+>
+<script>
+var v;
+var t = async_test(function(t) {
+ v = document.querySelector('video');
+ v.removeChild(document.querySelector('[onerror="x1++"]'));
+ window.onload = t.step_func(function() {
+ assert_equals(a, 1, 'error events on a');
+ assert_equals(b, 1, 'error events on b');
+ assert_equals(c, 1, 'error events on c');
+ assert_equals(x1, 0, 'error events on x1');
+ assert_equals(x2, 0, 'error events on x2');
+ assert_equals(x3, 0, 'error events on x3');
+ assert_equals(x4, 0, 'error events on x4');
+ t.done();
+ });
+});
+</script>
+<script>
+t.step(function() {
+ v.removeChild(document.querySelector('[onerror="x2++"]'));
+});
+</script>
+<script>
+t.step(function() {
+ v.removeChild(document.querySelector('[onerror="x3++"]'));
+});
+</script>
+<script>
+t.step(function() {
+ v.removeChild(document.querySelector('[onerror="x4++"]'));
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-remove-source.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-remove-source.html
new file mode 100644
index 0000000000..191f9b5e21
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-remove-source.html
@@ -0,0 +1,43 @@
+<!doctype html>
+<title>pointer updates (removing source elements)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var a = 0;
+var b = 0;
+var c = 0;
+var x1 = 0;
+var x2 = 0;
+var x3 = 0;
+var x4 = 0;
+</script>
+<video
+ ><source onerror=x1++
+ ><source onerror=a++
+ ><source onerror=x2++
+ ><source onerror=b++ src='resources/delayed-broken-video.py'
+ ><source onerror=x3++
+ ><source onerror=c++
+ ><source onerror=x4++
+ ></video
+>
+<script>
+async_test(function(t) {
+ var video = document.querySelector('video');
+ // remove the xn elements
+ [].forEach.call(document.querySelectorAll('[onerror^="x"]'), function(elm) {
+ video.removeChild(elm);
+ });
+ window.onload = t.step_func(function() {
+ assert_equals(a, 1, 'error events on a');
+ assert_equals(b, 1, 'error events on b');
+ assert_equals(c, 1, 'error events on c');
+ assert_equals(x1, 1, 'error events on x1');
+ assert_equals(x2, 1, 'error events on x2');
+ assert_equals(x3, 0, 'error events on x3');
+ assert_equals(x4, 0, 'error events on x4');
+ t.done();
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-remove-text.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-remove-text.html
new file mode 100644
index 0000000000..f0fe5da909
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-remove-text.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<title>pointer updates (removing text nodes)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var a = 0;
+var b = 0;
+var c = 0;
+</script>
+<video
+ >x<source onerror=a++
+ >x<source onerror=b++ src='resources/delayed-broken-video.py'
+ >x<source onerror=c++
+ >x</video
+>
+<script>
+async_test(function(t) {
+ var video = document.querySelector('video');
+ // remove the text nodes
+ [].forEach.call(video.childNodes, function(node) {
+ if (node.nodeType == node.TEXT_NODE) {
+ video.removeChild(node);
+ }
+ });
+ window.onload = t.step_func(function() {
+ assert_equals(a, 1, 'error events on a');
+ assert_equals(b, 1, 'error events on b');
+ assert_equals(c, 1, 'error events on c');
+ t.done();
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-remove-source.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-remove-source.html
new file mode 100644
index 0000000000..fbeead0191
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-remove-source.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<title>Changes to networkState when inserting and removing a &lt;source></title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var v;
+var t = async_test(function(t) {
+ v = document.createElement('video');
+ assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState when creating the element');
+ v.appendChild(document.createElement('source')); // runs resource selection algorithm
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState when inserting a source element');
+ v.removeChild(v.firstChild);
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState after removing the source element');
+});
+</script>
+<!-- now resource selection will continue its sync section (the </script> tag below provides a stable state) -->
+<!-- will find neither src nor source, so sets networkState to NETWORK_EMPTY -->
+<script>
+t.step(function() {
+ assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState after letting the sync section of resource selection run');
+ t.done();
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-remove-src.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-remove-src.html
new file mode 100644
index 0000000000..4d78871823
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-remove-src.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<title>invoking resource selection by setting src; await stable state</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var v;
+var t = async_test(function(t) {
+ v = document.createElement('video');
+ v.onloadstart = t.step_func(function() { assert_unreached(); });
+ v.setAttribute('src', ''); // runs resource selection algorithm, but it will wait running the sync section until this script has finished
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE);
+ v.removeAttribute('src'); // will make resource selection algorithm revert to NETWORK_EMPTY and abort (in the sync section)
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE);
+ window.onload = t.step_func(function() { t.done(); });
+});
+</script>
+<script>
+t.step(function() {
+ assert_equals(v.networkState, v.NETWORK_EMPTY);
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-resumes-onload.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-resumes-onload.html
new file mode 100644
index 0000000000..b166763d14
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-resumes-onload.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>resource selection should not delay the load event indefinitely</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<video></video>
+<script>
+async_test(function(t) {
+ const v = document.querySelector('video');
+ v.onloadstart = t.unreached_func("loadstart event should not be fired when the resource selection algorithm cannot determine mode");
+ const s = document.createElement('source');
+ v.appendChild(s); // this will trigger resource selection
+ v.removeChild(s); // force an early return in resource selection algorithm
+ window.onload = t.step_func_done(function() {
+ assert_equals(v.networkState, v.NETWORK_EMPTY);
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-source-media-env-change.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-source-media-env-change.html
new file mode 100644
index 0000000000..67f2c8300d
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-source-media-env-change.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<title>the &lt;source> media attribute: no reaction to environment change</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<iframe src="resources/media-min-width.html" width="300"></iframe>
+<script>
+// promises for the iframed test to resolve
+let beforeEnvChange = new Promise((resolve, reject) => {
+ window[0].resolveBeforeEnvChange = resolve;
+});
+let afterEnvChange = new Promise((resolve, reject) => {
+ window[0].resolveAfterEnvChange = resolve;
+});
+let afterLoadCalled = new Promise((resolve, reject) => {
+ window[0].resolveAfterLoadCalled = resolve;
+});
+const t = promise_test(async () => {
+ [beforeEnvChange, afterEnvChange, afterLoadCalled] = await Promise.all([ beforeEnvChange, afterEnvChange, afterLoadCalled ]);
+ assert_equals(beforeEnvChange, '#a', 'beforeEnvChange');
+ assert_equals(afterEnvChange, '#a', 'afterEnvChange');
+ assert_equals(afterLoadCalled, '#b', 'afterLoadCalled');
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-source-media.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-source-media.html
new file mode 100644
index 0000000000..df5f47add2
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-source-media.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>the &lt;source> media attribute</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<video><source src="resources/delayed-broken-video.py" media="not all"></video>
+<script>
+test(function() {
+ var v = document.querySelector('video');
+ var s = document.querySelector('source');
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE);
+ assert_equals(v.currentSrc, '');
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resources/delayed-broken-video.py b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resources/delayed-broken-video.py
new file mode 100644
index 0000000000..4eae3261f7
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resources/delayed-broken-video.py
@@ -0,0 +1,5 @@
+import time
+
+def main(request, response):
+ time.sleep(0.1)
+ return [(b"Content-Type", b"text/plain")], u"FAIL"
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resources/media-min-width.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resources/media-min-width.html
new file mode 100644
index 0000000000..8a4ad500cb
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resources/media-min-width.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<video width="200"></video>
+<script>
+function createSource(src, media) {
+ var source = document.createElement('source');
+ source.src = src;
+ if (media) {
+ source.media = media;
+ }
+ return source;
+}
+const rAF = () => new Promise(resolve => requestAnimationFrame(resolve));
+const hash = str => str.substr(str.lastIndexOf('#'));
+(async () => {
+ const v = document.querySelector('video');
+ v.getBoundingClientRect(); // force layout flush. ensure viewport dimensions are up-to-date
+ v.append(createSource('/media-source/mp4/test.mp4#a', '(min-width: 200px)'));
+ v.append(createSource('/media-source/mp4/test.mp4#b'));
+ await rAF();
+ await rAF();
+ window.resolveBeforeEnvChange(hash(v.currentSrc));
+ window.frameElement.width = '150';
+ await rAF();
+ await rAF();
+ window.resolveAfterEnvChange(hash(v.currentSrc));
+ v.load()
+ await rAF();
+ await rAF();
+ window.resolveAfterLoadCalled(hash(v.currentSrc));
+})();
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/stable-state-beforeunload-manual.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/stable-state-beforeunload-manual.html
new file mode 100644
index 0000000000..61ed225fa1
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/stable-state-beforeunload-manual.html
@@ -0,0 +1,30 @@
+<!doctype html>
+<title>stable state in beforeunload</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<button>click this button and cancel navigation</button>
+<a href="data:text/plain,FAIL: did not cancel navigation"></a>
+<script>
+async_test(function(t) {
+ window.onbeforeunload = t.step_func(function(event) {
+ var message = "foo bar";
+ event.returnValue = message;
+ return message;
+ });
+ var button = document.querySelector('button');
+ var link = document.querySelector('a');
+ button.onclick = t.step_func(function() {
+ v = document.createElement('video');
+ v.src = 'data:,';
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState before dialog');
+ assert_equals(v.currentSrc, '', 'currentSrc before dialog');
+ link.click();
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState after dialog');
+ assert_equals(v.currentSrc, '', 'currentSrc after dialog');
+ t.done();
+ window.onbeforeonload = null;
+ button.remove();
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/stable-state-dialogs-manual.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/stable-state-dialogs-manual.html
new file mode 100644
index 0000000000..267dde913c
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/stable-state-dialogs-manual.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>stable state in dialogs</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+['alert', 'confirm', 'prompt'].forEach(function(dialog) {
+ test(function() {
+ v = document.createElement('video');
+ v.src = 'data:,';
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState before dialog');
+ assert_equals(v.currentSrc, '', 'currentSrc before dialog');
+ window[dialog]('dismiss this dialog');
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState after dialog');
+ assert_equals(v.currentSrc, '', 'currentSrc after dialog');
+ }, 'stable state in ' + dialog + '()');
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/stable-state-print-manual.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/stable-state-print-manual.html
new file mode 100644
index 0000000000..1261a00793
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/stable-state-print-manual.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<title>stable state in print()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<button>click this button and dismiss the print dialog</button>
+<script>
+async_test(function(t) {
+ var button = document.querySelector('button');
+ button.onclick = t.step_func(function() {
+ v = document.createElement('video');
+ v.src = 'data:,';
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState before dialog');
+ assert_equals(v.currentSrc, '', 'currentSrc before dialog');
+ print();
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState after dialog');
+ assert_equals(v.currentSrc, '', 'currentSrc after dialog');
+ t.done();
+ button.remove();
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/location-of-the-media-resource/currentSrc.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/location-of-the-media-resource/currentSrc.html
new file mode 100644
index 0000000000..be4d09f739
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/location-of-the-media-resource/currentSrc.html
@@ -0,0 +1,48 @@
+<!doctype html>
+<title>currentSrc</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+['audio', 'video'].forEach(function(tagName) {
+ test(function() {
+ assert_equals(document.createElement(tagName).currentSrc, '');
+ }, tagName + '.currentSrc initial value');
+
+ ['', '.', ' ', 'data:,'].forEach(function(src) {
+ async_test(function(t) {
+ var e = document.createElement(tagName);
+ e.src = src;
+ assert_equals(e.currentSrc, '');
+ e.addEventListener('loadstart', function () {
+ t.step_timeout(function () {
+ if (src == '') {
+ assert_equals(e.currentSrc, '');
+ } else {
+ assert_equals(e.currentSrc, e.src);
+ }
+ t.done();
+ }, 0);
+ })
+ }, tagName + '.currentSrc after setting src attribute "' + src + '"');
+
+ async_test(function(t) {
+ var e = document.createElement(tagName);
+ var s = document.createElement('source');
+ s.src = src;
+ e.appendChild(s);
+ assert_equals(e.currentSrc, '');
+ e.addEventListener('loadstart', function() {
+ t.step_timeout(function () {
+ if (src == '') {
+ assert_equals(e.currentSrc, '');
+ } else {
+ assert_equals(e.currentSrc, s.src);
+ }
+ t.done();
+ }, 0);
+ });
+ }, tagName + '.currentSrc after adding source element with src attribute "' + src + '"');
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/media_fragment_seek.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/media_fragment_seek.html
new file mode 100644
index 0000000000..2a0106ce16
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/media_fragment_seek.html
@@ -0,0 +1,49 @@
+<!doctype html>
+<meta charset="utf-8">
+<meta name="timeout" content="long">
+<title>Video should seek to time specified in media fragment syntax</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<div id="log"></div>
+<video id="video"></video>
+<script>
+async_test(function () {
+ let video = document.getElementById("video");
+ video.src = getVideoURI('/media/movie_5') + "#t=4,7";
+ video.load();
+ this.step_timeout(function () {
+ assert_equals(video.currentTime, 4.0);
+
+ video.src = getVideoURI('/media/movie_5') + "#t=%6Ept:3";
+ video.load();
+ this.step_timeout(function () {
+ assert_true(video.src.endsWith("t=%6Ept:3"));
+ assert_equals(video.currentTime, 3.0);
+
+ video.src = getVideoURI('/media/movie_5') + "#t=00:00:01.00";
+ video.load();
+ this.step_timeout(function () {
+ assert_true(video.src.endsWith("t=00:00:01.00"));
+ assert_equals(video.currentTime, 1.0);
+
+ video.src = getVideoURI('/media/movie_5') + "#u=12&t=3";
+ video.load();
+ this.step_timeout(function () {
+ assert_true(video.src.endsWith("#u=12&t=3"));
+ assert_equals(video.currentTime, 3.0);
+
+ video.src = getVideoURI('/media/movie_5') + "#t=npt%3A3";
+ video.load();
+ this.step_timeout(function () {
+ assert_true(video.src.endsWith("t=npt%3A3"));
+ assert_equals(video.currentTime, 3.0);
+ this.done();
+ }, 1000);
+ }, 1000);
+ }, 1000);
+ }, 1000);
+ }, 1000);
+});
+</script>
+
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/mime-types/canPlayType.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/mime-types/canPlayType.html
new file mode 100644
index 0000000000..56edf25aa8
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/mime-types/canPlayType.html
@@ -0,0 +1,123 @@
+<!doctype html>
+<title>canPlayType</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<audio id="audio"></audio>
+<video id="video"></video>
+<div id="log"></div>
+<script>
+let VIDEO_ELEM = document.getElementById('video');
+let AUDIO_ELEM = document.getElementById('audio');
+
+function t(type, expected) {
+ assert_equals(canPlayType(type), expected, type);
+}
+
+function mime(type, codecs) {
+ if (codecs.length) {
+ return type + '; codecs="' + codecs.join(', ') + '"';
+ }
+ return type;
+}
+
+test(function() {
+ assert_equals(mime('video/webm', []), 'video/webm');
+ assert_equals(mime('video/webm', ['vp8']), 'video/webm; codecs="vp8"');
+ assert_equals(mime('video/webm', ['vp8', 'vorbis']), 'video/webm; codecs="vp8, vorbis"');
+}, 'utility code');
+
+function canPlayType(type) {
+ let audioCanPlay = AUDIO_ELEM.canPlayType(type);
+ let videoCanPlay = VIDEO_ELEM.canPlayType(type);
+ assert_equals(audioCanPlay, videoCanPlay,
+ 'audio.canPlayType() and video.canPlayType() agree');
+ assert_in_array(audioCanPlay, ['', 'maybe', 'probably'],
+ 'return value is one of "", "maybe" and "probably"');
+ return audioCanPlay;
+}
+
+test(function() {
+ t('application/octet-stream', '');
+ t('application/octet-stream; codecs="vorbis"', '');
+ t('application/octet-stream; codecs="vp8, vorbis"', '');
+ t('application/octet-stream; codecs="mp4a.40.2"', '');
+ t('application/octet-stream; codecs="theora, vorbis"', '');
+ t('application/octet-stream; codecs="avc1.42E01E, mp4a.40.2"', '');
+}, 'application/octet-stream not supported');
+
+test(function() {
+ t('application/marks-fantasmagorical-format', '');
+ t('video/x-new-fictional-format', '');
+ t('video/x-new-fictional-format;codecs="kittens,bunnies"', '');
+}, 'fictional formats and codecs not supported');
+
+function type_codecs_test(type, audioCodecs, videoCodecs) {
+ var typeSupported = false;
+ var codecSupported = false;
+
+ // Test 'type' without codecs.
+ // Spec: Generally, a user agent should never return "probably" for a type
+ // that allows the codecs parameter if that parameter is not present.
+ test(function() {
+ t(type, 'maybe');
+ t(type + ';', 'maybe');
+ t(type + ';codecs', 'maybe');
+ t(type + ';codecs=', 'maybe');
+ typeSupported = true;
+ }, type + ' (optional)');
+
+ function test_codec(codec) {
+ var typeWithCodec = mime(type, [codec]);
+ test(function() {
+ t(typeWithCodec, 'probably');
+ codecSupported = true;
+ }, typeWithCodec + ' (optional)');
+ }
+
+ // Test each audio and video codec separately.
+ audioCodecs.forEach(test_codec);
+ videoCodecs.forEach(test_codec);
+
+ // Test different pairings and orderings of audio+video codecs.
+ if (audioCodecs.length > 0 && videoCodecs.length > 0) {
+ test(function() {
+ audioCodecs.forEach(function(ac) {
+ videoCodecs.forEach(function(vc) {
+ var canPlayBoth = canPlayType(mime(type, [ac, vc]));
+ if (canPlayBoth) {
+ t(mime(type, [ac]), canPlayBoth);
+ t(mime(type, [vc]), canPlayBoth);
+ }
+ });
+ });
+ }, type + ' codecs subset');
+
+ test(function() {
+ audioCodecs.forEach(function(ac) {
+ videoCodecs.forEach(function(vc) {
+ assert_equals(canPlayType(mime(type, [ac, vc])),
+ canPlayType(mime(type, [vc, ac])));
+ });
+ });
+ }, type + ' codecs order');
+ }
+
+ test(function() {
+ t(mime(type, ['bogus']), '');
+ }, type + ' with bogus codec');
+
+ test(function() {
+ // At least one known codec must be supported if the container format is.
+ assert_equals(typeSupported, codecSupported);
+ }, type + ' with and without codecs');
+}
+
+type_codecs_test('audio/mp4', ['mp4a.40.2'], []);
+type_codecs_test('audio/ogg', ['opus', 'vorbis'], []);
+type_codecs_test('audio/wav', ['1'], []);
+type_codecs_test('audio/webm', ['opus', 'vorbis'], []);
+type_codecs_test('video/3gpp', ['samr'], ['mp4v.20.8']);
+type_codecs_test('video/mp4', ['mp4a.40.2'], ['avc1.42E01E', 'avc1.4D401E', 'avc1.58A01E', 'avc1.64001E', 'mp4v.20.8', 'mp4v.20.240']);
+type_codecs_test('video/ogg', ['opus', 'vorbis'], ['theora']);
+type_codecs_test('video/webm', ['opus', 'vorbis'], ['vp8', 'vp8.0', 'vp9', 'vp9.0']);
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/networkState_during_loadstart.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/networkState_during_loadstart.html
new file mode 100644
index 0000000000..8570bfd111
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/networkState_during_loadstart.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video}.networkState - NETWORK_LOADING</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#dom-media-networkstate">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+var ta = async_test("audioElement.networkState should be NETWORK_LOADING during loadstart event");
+var a = document.getElementById("a");
+a.addEventListener("loadstart", function() {
+ ta.step(function() {
+ assert_equals(a.networkState,
+ a.NETWORK_LOADING);
+ });
+ ta.done();
+ a.pause();
+}, false);
+a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+
+var tv = async_test("videoElement.networkState should be NETWORK_LOADING during loadstart event");
+var v = document.getElementById("v");
+v.addEventListener("loadstart", function() {
+ tv.step(function() {
+ assert_equals(v.networkState,
+ v.NETWORK_LOADING);
+ });
+ tv.done();
+ v.pause();
+}, false);
+v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/networkState_during_progress.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/networkState_during_progress.html
new file mode 100644
index 0000000000..db9df23cb6
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/networkState_during_progress.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video}.networkState - NETWORK_LOADING</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#dom-media-networkstate">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var ta = async_test("audioElement.networkState should be NETWORK_LOADING during progress event");
+ var a = document.getElementById("a");
+ a.addEventListener("error", ta.unreached_func());
+ a.addEventListener("progress", ta.step_func(function() {
+ assert_equals(a.networkState, a.NETWORK_LOADING);
+ ta.done();
+ a.pause();
+ }), false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - networkState during progress");
+
+test(function() {
+ var tv = async_test("videoElement.networkState should be NETWORK_LOADING during progress event");
+ var v = document.getElementById("v");
+ v.addEventListener("error", tv.unreached_func());
+ v.addEventListener("progress", tv.step_func(function() {
+ assert_equals(v.networkState, v.NETWORK_LOADING);
+ tv.done();
+ v.pause();
+ }), false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - networkState during progress");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/networkState_initial.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/networkState_initial.html
new file mode 100644
index 0000000000..0a203e6542
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/networkState_initial.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video}.networkState - default state</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#dom-media-networkstate">spec reference</a></p>
+ <audio id="a">
+ </audio>
+ <video id="v">
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var a = document.getElementById("a");
+ assert_equals(
+ a.networkState,
+ a.NETWORK_EMPTY,
+ "audioElement.networkState should be NETWORK_EMPTY to begin with");
+}, "audio.networkState - default state");
+
+test(function() {
+ var v = document.getElementById("v");
+ assert_equals(
+ v.networkState,
+ v.NETWORK_EMPTY,
+ "videoElement.networkState should be NETWORK_EMPTY to begin with");
+}, "video.networkState - default state");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/offsets-into-the-media-resource/currentTime.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/offsets-into-the-media-resource/currentTime.html
new file mode 100644
index 0000000000..e9b6589941
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/offsets-into-the-media-resource/currentTime.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<title>currentTime</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+ var v = document.createElement('video');
+ assert_equals(v.currentTime, 0);
+}, 'currentTime initial value');
+
+test(function() {
+ var v = document.createElement('video');
+ assert_equals(v.readyState, v.HAVE_NOTHING);
+ v.currentTime = Number.MAX_VALUE;
+ assert_equals(v.currentTime, Number.MAX_VALUE);
+ assert_false(v.seeking);
+}, 'setting currentTime when readyState is HAVE_NOTHING');
+
+async_test(function(t) {
+ var v = document.createElement('video');
+ v.src = getVideoURI('/media/movie_5');
+ v.onloadedmetadata = t.step_func(function() {
+ assert_greater_than(v.readyState, v.HAVE_NOTHING);
+ assert_false(v.seeking);
+ v.currentTime = 1;
+ assert_true(v.seeking);
+ t.done();
+ });
+}, 'setting currentTime when readyState is greater than HAVE_NOTHING');
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/offsets-into-the-media-resource/duration.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/offsets-into-the-media-resource/duration.html
new file mode 100644
index 0000000000..0ac26eddb9
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/offsets-into-the-media-resource/duration.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<title>duration</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+ var v = document.createElement('video');
+ assert_true(isNaN(v.duration));
+}, 'duration initial value');
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/paused_false_during_play.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/paused_false_during_play.html
new file mode 100644
index 0000000000..946deecf43
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/paused_false_during_play.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - paused property</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("audio.paused should be false during play event");
+ var a = document.getElementById("a");
+ a.addEventListener("error", t.unreached_func());
+ a.addEventListener("play", t.step_func(function() {
+ assert_false(a.paused);
+ t.done();
+ a.pause();
+ }), false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - paused property");
+
+test(function() {
+ var t = async_test("video.paused should be false during play event");
+ var v = document.getElementById("v");
+ v.addEventListener("error", t.unreached_func());
+ v.addEventListener("play", t.step_func(function() {
+ assert_false(v.paused);
+ t.done();
+ v.pause();
+ }), false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - paused property");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/paused_true_during_pause.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/paused_true_during_pause.html
new file mode 100644
index 0000000000..817615c5cb
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/paused_true_during_pause.html
@@ -0,0 +1,48 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - paused property</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" controls>
+ </audio>
+ <video id="v" controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("audio.paused should be true during pause event");
+ var a = document.getElementById("a");
+ a.addEventListener("pause", function() {
+ t.step(function() {
+ assert_true(a.paused);
+ });
+
+ t.done();
+ }, false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+ a.play().catch(() => {});
+ a.pause();
+}, "audio events - paused property");
+
+test(function() {
+ var t = async_test("video.paused should be true during pause event");
+ var v = document.getElementById("v");
+ v.addEventListener("pause", function() {
+ t.step(function() {
+ assert_true(v.paused);
+ });
+
+ t.done();
+ }, false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+ v.play().catch(() => {});
+ v.pause();
+}, "video events - paused property");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/pitch-detector.js b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/pitch-detector.js
new file mode 100644
index 0000000000..78f22ccd85
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/pitch-detector.js
@@ -0,0 +1,58 @@
+// This should be removed when the webaudio/historical.html tests are passing.
+// Tracking bug: https://bugs.webkit.org/show_bug.cgi?id=204719
+window.AudioContext = window.AudioContext || window.webkitAudioContext;
+
+var FFT_SIZE = 2048;
+
+var audioContext;
+var sourceNode;
+
+function getPitchDetector(media) {
+ if(!audioContext) {
+ audioContext = new AudioContext();
+ sourceNode = audioContext.createMediaElementSource(media);
+ }
+
+ var analyser = audioContext.createAnalyser();
+ analyser.fftSize = FFT_SIZE;
+
+ sourceNode.connect(analyser);
+ analyser.connect(audioContext.destination);
+
+ return {
+ ensureStart() { return audioContext.resume(); },
+ detect() { return getPitch(analyser); },
+ cleanup() {
+ sourceNode.disconnect();
+ analyser.disconnect();
+ },
+ };
+}
+
+function getPitch(analyser) {
+ // Returns the frequency value for the nth FFT bin.
+ var binConverter = (bin) =>
+ (audioContext.sampleRate/2)*((bin)/(analyser.frequencyBinCount-1));
+
+ var buf = new Uint8Array(analyser.frequencyBinCount);
+ analyser.getByteFrequencyData(buf);
+ return findDominantFrequency(buf, binConverter);
+}
+
+// Returns the dominant frequency, +/- a certain margin.
+function findDominantFrequency(buf, binConverter) {
+ var max = 0;
+ var bin = 0;
+
+ for (var i=0;i<buf.length;i++) {
+ if(buf[i] > max) {
+ max = buf[i];
+ bin = i;
+ }
+ }
+
+ // The spread of frequencies within bins is constant and corresponds to
+ // (1/(FFT_SIZE-1))th of the sample rate. Use the value of bin #1 as a
+ // shorthand for that value.
+ return { value:binConverter(bin), margin:binConverter(1) };
+} \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/loop-from-ended.tentative.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/loop-from-ended.tentative.html
new file mode 100644
index 0000000000..d099a8a0f8
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/loop-from-ended.tentative.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<title>play() with loop set to true after playback ended</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<video></video>
+<script>
+// Seek towards end of video (for faster testing).
+// Play video to end with "loop" set to false.
+// Once ended, set "loop" to true. Call play.
+// Verify that "seeked" event fires, seeking back to the beginning.
+// Pause video and end test.
+// Chromium bug: https://crbug.com/364442
+// Spec issue: https://github.com/whatwg/html/issues/4487
+async_test(function(t) {
+ var video = document.querySelector("video");
+
+ video.onloadedmetadata = t.step_func(function() {
+ // Video is initially paused and "loop" unset.
+ assert_true(video.paused, "paused initially ");
+ assert_false(video.loop, "loop initially");
+ // Seek to just before the end of the video and play.
+ video.currentTime = video.duration - 0.5;
+ video.onended = t.step_func(function() {
+ // Verify played to end and stopped.
+ assert_true(video.ended, "ended at ended event");
+ assert_true(video.paused, "paused at ended event");
+ assert_equals(video.currentTime, video.duration, "currentTime at ended event");
+
+ // With playback ended, set "loop" attribute. This will cause ended == false.
+ // looping video cannot be "ended", only paused.
+ assert_false(video.loop, "loop at ended event");
+ video.loop = true;
+ assert_true(video.loop, "loop after seek");
+ assert_false(video.ended, "ended after seek");
+ assert_true(video.paused, "paused after seek");
+
+ video.onseeked = t.step_func_done(function() {
+ // Observed seek. Verify current time decreased and still playing.
+ assert_true(video.loop, "loop at seeked event")
+ assert_false(video.paused, "paused at seeked event");
+ assert_false(video.ended, "ended at seeked event");
+ assert_less_than(video.currentTime, video.duration, "currentTime at seeked event");
+ // Pausing now that test is over to prevent additional unwanted looping.
+ video.pause();
+ });
+
+ // Play video with "loop" set. Expect seek back to start.
+ video.play();
+ });
+
+ video.play();
+ });
+
+ video.src = getVideoURI("/media/movie_5");
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-move-to-other-document.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-move-to-other-document.html
new file mode 100644
index 0000000000..77b4a288d8
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-move-to-other-document.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<title>paused state when moving to other document</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<div id="log"></div>
+<video hidden></video>
+<iframe hidden></iframe>
+<script>
+async_test(function(t) {
+ var v = document.querySelector('video');
+ v.src = getVideoURI('/media/movie_300');
+ v.play();
+ v.onplaying = t.step_func(function() {
+ assert_false(v.paused, 'paused after playing');
+ document.querySelector('iframe').contentDocument.body.appendChild(v);
+ assert_false(v.paused, 'paused after moving');
+ t.step_timeout(function() {
+ assert_false(v.paused, 'paused after stable state')
+ t.done();
+ }, 0);
+ });
+ v.onpause = t.step_func(function() { assert_unreached(); });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-move-within-document.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-move-within-document.html
new file mode 100644
index 0000000000..911aa7b5c9
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-move-within-document.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<title>paused state when moving within a document</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<div id="log"></div>
+<video hidden></video>
+<div id="elsewhere"></div>
+<script>
+async_test(function(t) {
+ var v = document.querySelector('video');
+ v.src = getVideoURI('/media/movie_300');
+ v.play();
+ v.onplaying = t.step_func(function() {
+ assert_false(v.paused, 'paused after playing');
+ document.getElementById('elsewhere').appendChild(v);
+ assert_false(v.paused, 'paused after moving');
+ t.step_timeout(function() {
+ assert_false(v.paused, 'paused after stable state')
+ t.done();
+ }, 0);
+ });
+ v.onpause = t.step_func(function() { assert_unreached(); });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-remove-from-document-different-load.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-remove-from-document-different-load.html
new file mode 100644
index 0000000000..4802665cdd
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-remove-from-document-different-load.html
@@ -0,0 +1,44 @@
+<!doctype html>
+<title>paused state when removing from a document</title>
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1583052">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<div id="log"></div>
+<div>
+ <video hidden></video>
+</div>
+<script>
+function afterStableState(func) {
+ var a = new Audio();
+ a.volume = 0;
+ a.addEventListener('volumechange', func);
+}
+
+async_test(function(t) {
+ var v = document.querySelector('video');
+
+ // Much like pause-remove-from-document.html, modulo this call.
+ document.body.appendChild(v);
+
+ v.src = getVideoURI('/media/movie_300');
+ v.play();
+ v.onplaying = t.step_func(function() {
+ assert_false(v.paused, 'paused after playing');
+ v.parentNode.removeChild(v);
+ assert_false(v.paused, 'paused after removing');
+ afterStableState(t.step_func(function() {
+ assert_true(v.paused, 'paused after stable state');
+ v.onpause = t.step_func(function() {
+ assert_true(v.paused, 'paused in pause event');
+ // re-insert and verify that it stays paused
+ document.body.appendChild(v);
+ t.step_timeout(function() {
+ assert_true(v.paused, 'paused after re-inserting');
+ t.done();
+ }, 0);
+ });
+ }));
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-remove-from-document-networkState.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-remove-from-document-networkState.html
new file mode 100644
index 0000000000..5140ea5611
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-remove-from-document-networkState.html
@@ -0,0 +1,27 @@
+<!doctype html>
+<title>paused state when removing from a document when networkState is NETWORK_EMPTY</title>
+<meta name="timeout" content="long" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<video hidden></video>
+<script>
+// Negative test for the specified behavior prior to HTML r8447.
+promise_test(async function(t) {
+ var v = document.querySelector('video');
+ var watcher = new EventWatcher(t, v, [ 'pause' ]);
+ var p = v.play();
+
+ await new Promise(resolve => t.step_timeout(resolve, 0));
+ assert_equals(v.networkState, v.NETWORK_EMPTY,
+ 'networkState after stable state');
+ assert_false(v.paused, 'paused after stable state');
+ v.parentNode.removeChild(v);
+ assert_false(v.paused, 'paused after removing');
+
+ await watcher.wait_for('pause');
+
+ await promise_rejects_dom(t, 'AbortError', p, 'We expect promise being rejected');
+ assert_true(v.paused, 'paused after removing and stable state');
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-remove-from-document.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-remove-from-document.html
new file mode 100644
index 0000000000..5425844037
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-remove-from-document.html
@@ -0,0 +1,37 @@
+<!doctype html>
+<title>paused state when removing from a document</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<div id="log"></div>
+<video hidden></video>
+<script>
+function afterStableState(func) {
+ var a = new Audio();
+ a.volume = 0;
+ a.addEventListener('volumechange', func);
+}
+
+async_test(function(t) {
+ var v = document.querySelector('video');
+ v.src = getVideoURI('/media/movie_300');
+ v.play();
+ v.onplaying = t.step_func(function() {
+ assert_false(v.paused, 'paused after playing');
+ v.parentNode.removeChild(v);
+ assert_false(v.paused, 'paused after removing');
+ afterStableState(t.step_func(function() {
+ assert_true(v.paused, 'paused after stable state');
+ v.onpause = t.step_func(function() {
+ assert_true(v.paused, 'paused in pause event');
+ // re-insert and verify that it stays paused
+ document.body.appendChild(v);
+ t.step_timeout(function() {
+ assert_true(v.paused, 'paused after re-inserting');
+ t.done();
+ }, 0);
+ });
+ }));
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/play-in-detached-document.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/play-in-detached-document.html
new file mode 100644
index 0000000000..8e9a7843b7
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/play-in-detached-document.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<title>play() in detached document</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<div id="log"></div>
+<script>
+// Negative test for failure to play in a detached document.
+async_test(function(t)
+{
+ var doc = document.implementation.createHTMLDocument("");
+ var v = doc.createElement("video");
+ doc.body.appendChild(v);
+ v.src = getVideoURI("/media/movie_5");
+ v.play().catch(() => {});
+
+ v.addEventListener("timeupdate", t.step_func(function() {
+ assert_false(v.paused);
+ if (v.currentTime > 0) {
+ t.done();
+ }
+ }));
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/playbackRate.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/playbackRate.html
new file mode 100644
index 0000000000..d8e14b5fc1
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/playbackRate.html
@@ -0,0 +1,53 @@
+<!doctype html>
+<title>playbackRate</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+ var v = document.createElement('video');
+ assert_equals(v.playbackRate, 1);
+}, 'playbackRate initial value');
+
+function testPlaybackRateHelper(t, newPlaybackRate) {
+ var v = document.createElement('video');
+ var initialRate = v.playbackRate;
+
+ v.addEventListener('ratechange', t.step_func_done(function() {
+ assert_equals(v.playbackRate, newPlaybackRate);
+ }));
+
+ try {
+ v.playbackRate = newPlaybackRate;
+ } catch(e) {
+ assert_equals(e.name, 'NotSupportedError');
+ assert_equals(v.playbackRate, initialRate);
+ t.done();
+ }
+}
+
+async_test(function(t) {
+ testPlaybackRateHelper(this, 3);
+}, "playbackRate set to small positive value");
+
+async_test(function(t) {
+ testPlaybackRateHelper(this, 100);
+}, "playbackRate set to large positive value");
+
+async_test(function(t) {
+ testPlaybackRateHelper(this, -3);
+}, "playbackRate set to small negative value");
+
+async_test(function(t) {
+ testPlaybackRateHelper(this, -100);
+}, "playbackRate set to large negative value");
+
+async_test(function(t) {
+ testPlaybackRateHelper(this, 0);
+}, "playbackRate set to 0");
+
+async_test(function(t) {
+ testPlaybackRateHelper(this, -1);
+}, "playbackRate set to -1");
+
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/preload_reflects_none_autoplay.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/preload_reflects_none_autoplay.html
new file mode 100644
index 0000000000..2670b0dd81
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/preload_reflects_none_autoplay.html
@@ -0,0 +1,31 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video}.preload - reflection test</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#dom-media-preload">spec reference</a></p>
+ <audio id="audio" autoplay preload="none">
+ </audio>
+ <video id="video" autoplay preload="none">
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ assert_equals(
+ document.getElementById("audio").preload,
+ "none",
+ "audioElement.preload reflects 'none' value even if autoplay attribute is present");
+}, "audio.preload - reflection test");
+
+test(function() {
+ assert_equals(
+ document.getElementById("video").preload,
+ "none",
+ "videoElement.preload reflects 'none' value even if autoplay attribute is present");
+}, "video.preload - reflection test");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/preserves-pitch.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/preserves-pitch.html
new file mode 100644
index 0000000000..ba76f51d47
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/preserves-pitch.html
@@ -0,0 +1,132 @@
+<!DOCTYPE html>
+<title>Test preservesPitch.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="pitch-detector.js"></script>
+<script>
+
+// Remove when media-elements/historical.html's preservePitch prefix tests are are passing.
+function getPreservesPitch(audio) {
+ if ("preservesPitch" in HTMLAudioElement.prototype) {
+ return audio.preservesPitch;
+ }
+ if ("webkitPreservesPitch" in HTMLAudioElement.prototype) {
+ return audio.webkitPreservesPitch;
+ }
+ return undefined;
+}
+
+// Remove when media-elements/historical.html's preservePitch prefix tests are are passing.
+function setPreservesPitch(audio, value) {
+ if ("preservesPitch" in HTMLAudioElement.prototype) {
+ audio.preservesPitch = value;
+ } else if ("webkitPreservesPitch" in HTMLAudioElement.prototype) {
+ audio.webkitPreservesPitch = value;
+ }
+}
+
+test(function(t) {
+ assert_true("preservesPitch" in HTMLAudioElement.prototype);
+}, "Test that preservesPitch is present and unprefixed.");
+
+test(function(t) {
+ let defaultAudio = document.createElement('audio');
+ assert_true(getPreservesPitch(defaultAudio));
+
+ setPreservesPitch(defaultAudio, false);
+ assert_false(getPreservesPitch(defaultAudio));
+}, "Test that preservesPitch is on by default");
+
+
+var audio;
+
+function addTestCleanups(t, detector) {
+ t.add_cleanup(() => {
+ audio.pause();
+ audio.currentTime = 0;
+ });
+ t.add_cleanup(() => detector.cleanup());
+}
+
+function testPreservesPitch(preservesPitch, playbackRate, expectedPitch, description) {
+ promise_test(async t => {
+ let detector = getPitchDetector(audio);
+ addTestCleanups(t, detector);
+
+ audio.playbackRate = playbackRate;
+ setPreservesPitch(audio, preservesPitch);
+
+ function waitUntil(time) {
+ return new Promise((resolve) => {
+ audio.ontimeupdate = () => {
+ if (audio.currentTime >= time) {
+ resolve();
+ }
+ };
+ });
+ }
+
+ // Wait until we have played some audio. Otherwise, the detector
+ // might return a pitch of 0Hz.
+ audio.play();
+ await waitUntil(0.5);
+
+ var pitch = detector.detect();
+
+ // 25Hz is larger than the margin we get from 48kHz and 44.1kHz
+ // audio being analyzed by a FFT of size 2048. If we get something
+ // different, there is an error within the test's calculations (or
+ // we might be dealing a larger sample rate).
+ assert_less_than(pitch.margin, 25,
+ "Test error: the margin should be reasonably small.")
+
+ // Allow for a 15% margin of error in the pitch detector, to reduce test
+ // flakiness. Since our tests speed up and slow down by a factor of 2,
+ // this should be plenty of leeway, without causing false negatives.
+ assert_approx_equals(pitch.value, expectedPitch, expectedPitch*0.15,
+ "The actual pitch should be close to the expected pitch.");
+
+ }, description);
+}
+
+var REFERENCE_PITCH = 440;
+
+promise_test(async t => {
+ // Create the audio element only once, in order to lower the chances of
+ // tests timing out.
+ audio = document.createElement('audio');
+
+ // This file contains 5 seconds of a 440hz sine wave.
+ audio.src = "/media/sine440.mp3";
+
+ let detector = getPitchDetector(audio);
+ addTestCleanups(t, detector);
+
+ // The first time we run the test, we need to interact with the
+ // AudioContext and Audio element via user gestures.
+ await test_driver.bless("Play audio element", () => {
+ return Promise.all([audio.play(), detector.ensureStart()]);
+ });
+}, "Setup Audio element and AudioContext")
+
+testPreservesPitch(true, 1.0, REFERENCE_PITCH,
+ "The default playbackRate should not affect pitch")
+
+testPreservesPitch(false, 1.0, REFERENCE_PITCH,
+ "The default playbackRate should not affect pitch, even with preservesPitch=false")
+
+testPreservesPitch(true, 2.0, REFERENCE_PITCH,
+ "Speed-ups should not change the pitch when preservesPitch=true")
+
+testPreservesPitch(true, 0.5, REFERENCE_PITCH,
+ "Slow-downs should not change the pitch when preservesPitch=true")
+
+testPreservesPitch(false, 2.0, REFERENCE_PITCH*2.0,
+ "Speed-ups should change the pitch when preservesPitch=false")
+
+testPreservesPitch(false, 0.5, REFERENCE_PITCH*0.5,
+ "Slow-downs should change the pitch when preservesPitch=false")
+
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/ready-states/autoplay-hidden.optional.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/ready-states/autoplay-hidden.optional.html
new file mode 100644
index 0000000000..16c6e29be9
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/ready-states/autoplay-hidden.optional.html
@@ -0,0 +1,37 @@
+<!doctype html>
+<title>autoplay hidden</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/media.html#ready-states"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<div id="log"></div>
+<script>
+
+// https://html.spec.whatwg.org/multipage/media.html#ready-states:eligible-for-autoplay-2
+
+promise_test(async t => {
+ let video = document.createElement("video");
+ video.src = getVideoURI("/media/movie_5");
+ video.autoplay = true;
+ // In Safari, Chrome and Firefox, the video needs to be muted in order to be
+ // paused when hidden. They decided to do this in order to save resources when
+ // a video goes out of view and isn't expected to make any sound.
+ video.muted = true;
+ video.loop = true;
+ let watcher = new EventWatcher(t, video, ["playing", "pause"]);
+ document.body.appendChild(video);
+
+ await watcher.wait_for("playing");
+ assert_false(video.paused, "paused when video is display");
+ video.hidden = true;
+
+ await watcher.wait_for("pause");
+ assert_true(video.paused, "paused when video is hidden");
+ video.hidden = false;
+
+ await watcher.wait_for("playing");
+ assert_false(video.paused, "paused when video is display");
+}, "Allow delaying autoplay until video elements become visible");
+
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/ready-states/autoplay-with-slow-text-tracks.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/ready-states/autoplay-with-slow-text-tracks.html
new file mode 100644
index 0000000000..930d9cbd5b
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/ready-states/autoplay-with-slow-text-tracks.html
@@ -0,0 +1,46 @@
+<!doctype html>
+<title>autoplay with slow text tracks</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<div id="log"></div>
+<script>
+setup({ single_test: true });
+// https://html.spec.whatwg.org/#ready-states says:
+//
+// HAVE_FUTURE_DATA: "the text tracks are ready".
+// HAVE_ENOUGH_DATA: All the conditions described for the HAVE_FUTURE_DATA state are met, ...
+//
+// When the ready state of a media element whose networkState is not NETWORK_EMPTY changes,
+// the user agent must follow the steps given below:
+// If the new ready state is HAVE_ENOUGH_DATA
+// (autoplay)
+//
+// So if the text tracks are not yet ready, we can't autoplay.
+
+var started = 0;
+var numOfTests = 5;
+
+function createTest() {
+ var video = document.createElement('video');
+ video.src = getVideoURI('/media/movie_5');
+ video.autoplay = true;
+ video.muted = true;
+ video.controls = true;
+ video.onplaying = function() {
+ started++;
+ assert_equals(track.track.cues.length, 1);
+ if (started === numOfTests) {
+ done();
+ }
+ };
+ var track = document.createElement('track');
+ track.src = '/media/foo.vtt?pipe=trickle(d2)';
+ track.default = true;
+ video.appendChild(track);
+ document.body.appendChild(video);
+}
+for (var i = 0; i < numOfTests; ++i) {
+ createTest();
+}
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/ready-states/autoplay.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/ready-states/autoplay.html
new file mode 100644
index 0000000000..b60b58a421
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/ready-states/autoplay.html
@@ -0,0 +1,73 @@
+<!doctype html>
+<title>autoplay</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<div id="log"></div>
+<script>
+function autoplay_test(tagName, src) {
+ function expect_events(t, e, expected_events) {
+ var actual_events = [];
+ var callback = t.step_func(function(ev) {
+ actual_events.push(ev.type);
+ assert_array_equals(actual_events,
+ expected_events.slice(0, actual_events.length));
+ if (expected_events.length == actual_events.length) {
+ t.done();
+ }
+ });
+ ['canplay', 'canplaythrough',
+ 'pause', 'play', 'playing', 'error'].forEach(function(type) {
+ e.addEventListener(type, callback);
+ });
+ }
+
+ async_test(function(t) {
+ var e = document.createElement(tagName);
+ e.src = src;
+ e.autoplay = true;
+ expect_events(t, e, ['canplay', 'play', 'playing', 'canplaythrough']);
+ }, tagName + '.autoplay');
+
+ async_test(function(t) {
+ var e = document.createElement(tagName);
+ e.src = src;
+ e.autoplay = true;
+ e.pause(); // sets the autoplaying flag to false
+ e.load(); // sets the autoplaying flag to true
+ expect_events(t, e, ['canplay', 'play', 'playing', 'canplaythrough']);
+ }, tagName + '.autoplay and load()');
+
+ async_test(function(t) {
+ var e = document.createElement(tagName);
+ e.src = src;
+ e.autoplay = true;
+ e.play(); // sets the autoplaying flag to false
+ // play() also sets the paused attribute to false; there is no way for the
+ // autoplaying flag to be true when the paused attribute is false.
+ assert_equals(e.paused, false);
+ expect_events(t, e, ['play', 'canplay', 'playing', 'canplaythrough']);
+ }, tagName + '.autoplay and play()');
+
+ async_test(function(t) {
+ var e = document.createElement(tagName);
+ e.src = src;
+ e.autoplay = true;
+ e.pause(); // sets the autoplaying flag to false
+ expect_events(t, e, ['canplay', 'canplaythrough']);
+ }, tagName + '.autoplay and pause()');
+
+ async_test(function(t) {
+ var e = document.createElement(tagName);
+ e.src = src;
+ e.autoplay = true;
+ document.body.appendChild(e);
+ document.body.removeChild(e);
+ // in stable state, internal pause steps sets the autoplaying flag to false
+ expect_events(t, e, ['canplay', 'canplaythrough']);
+ }, tagName + '.autoplay and internal pause steps');
+}
+
+autoplay_test('audio', getAudioURI('/media/sound_5'));
+autoplay_test('video', getVideoURI('/media/movie_5'));
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/readyState_during_canplay.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/readyState_during_canplay.html
new file mode 100644
index 0000000000..358a87fe21
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/readyState_during_canplay.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - readyState property during canplay</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("audio.readyState should be >= HAVE_FUTURE_DATA during canplay event");
+ var a = document.getElementById("a");
+ a.addEventListener("error", t.unreached_func());
+ a.addEventListener("canplay", t.step_func(function() {
+ assert_greater_than_equal(a.readyState, a.HAVE_FUTURE_DATA);
+ t.done();
+ a.pause();
+ }), false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - readyState property during canplay");
+
+test(function() {
+ var t = async_test("video.readyState should be >= HAVE_FUTURE_DATA during canplay event");
+ var v = document.getElementById("v");
+ v.addEventListener("error", t.unreached_func());
+ v.addEventListener("canplay", t.step_func(function() {
+ assert_greater_than_equal(v.readyState, v.HAVE_FUTURE_DATA);
+ t.done();
+ v.pause();
+ }), false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - readyState property during canplay");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/readyState_during_canplaythrough.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/readyState_during_canplaythrough.html
new file mode 100644
index 0000000000..2721d18633
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/readyState_during_canplaythrough.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - readyState property during canplaythrough</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("audio.readyState should be HAVE_ENOUGH_DATA during canplaythrough event");
+ var a = document.getElementById("a");
+ a.addEventListener("error", t.unreached_func());
+ a.addEventListener("canplaythrough", t.step_func(function() {
+ assert_equals(a.readyState, a.HAVE_ENOUGH_DATA);
+ t.done();
+ a.pause();
+ }), false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - readyState property during canplaythrough");
+
+test(function() {
+ var t = async_test("video.readyState should be HAVE_ENOUGH_DATA during canplaythrough event");
+ var v = document.getElementById("v");
+ v.addEventListener("error", t.unreached_func());
+ v.addEventListener("canplaythrough", t.step_func(function() {
+ assert_equals(v.readyState, v.HAVE_ENOUGH_DATA);
+ t.done();
+ v.pause();
+ }), false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - readyState property during canplaythrough");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/readyState_during_loadeddata.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/readyState_during_loadeddata.html
new file mode 100644
index 0000000000..f237b1fbd3
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/readyState_during_loadeddata.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - readyState property during loadeddata</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("audio.readyState should be >= HAVE_CURRENT_DATA during loadeddata event");
+ var a = document.getElementById("a");
+ a.addEventListener("error", t.unreached_func());
+ a.addEventListener("loadeddata", t.step_func(function() {
+ assert_greater_than_equal(a.readyState, a.HAVE_CURRENT_DATA);
+ t.done();
+ a.pause();
+ }), false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - readyState property during loadeddata");
+
+test(function() {
+ var t = async_test("video.readyState should be >= HAVE_CURRENT_DATA during loadeddata event");
+ var v = document.getElementById("v");
+ v.addEventListener("error", t.unreached_func());
+ v.addEventListener("loadeddata", t.step_func(function() {
+ assert_greater_than_equal(v.readyState, v.HAVE_CURRENT_DATA);
+ t.done();
+ v.pause();
+ }), false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - readyState property during loadeddata");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/readyState_during_loadedmetadata.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/readyState_during_loadedmetadata.html
new file mode 100644
index 0000000000..73f33f0b98
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/readyState_during_loadedmetadata.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - readyState property during loadedmetadata</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("audio.readyState should be >= HAVE_METADATA during loadedmetadata event");
+ var a = document.getElementById("a");
+ a.addEventListener("error", t.unreached_func());
+ a.addEventListener("loadedmetadata", t.step_func(function() {
+ assert_greater_than_equal(a.readyState, a.HAVE_METADATA);
+ t.done();
+ a.pause();
+ }), false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - readyState property during loadedmetadata");
+
+test(function() {
+ var t = async_test("video.readyState should be >= HAVE_METADATA during loadedmetadata event");
+ var v = document.getElementById("v");
+ v.addEventListener("error", t.unreached_func());
+ v.addEventListener("loadedmetadata", t.step_func(function() {
+ assert_greater_than_equal(v.readyState, v.HAVE_METADATA);
+ t.done();
+ v.pause();
+ }), false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - readyState property during loadedmetadata");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/readyState_during_playing.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/readyState_during_playing.html
new file mode 100644
index 0000000000..663bad701b
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/readyState_during_playing.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - readyState property during playing</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("audio.readyState should be >= HAVE_FUTURE_DATA during playing event");
+ var a = document.getElementById("a");
+ a.addEventListener("error", t.unreached_func());
+ a.addEventListener("playing", t.step_func(function() {
+ assert_greater_than_equal(a.readyState, a.HAVE_FUTURE_DATA);
+ t.done();
+ a.pause();
+ }), false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - readyState property during playing");
+
+test(function() {
+ var t = async_test("video.readyState should be >= HAVE_FUTURE_DATA during playing event");
+ var v = document.getElementById("v");
+ v.addEventListener("error", t.unreached_func());
+ v.addEventListener("playing", t.step_func(function() {
+ assert_greater_than_equal(v.readyState, v.HAVE_FUTURE_DATA);
+ t.done();
+ v.pause();
+ }), false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - readyState property during playing");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/readyState_initial.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/readyState_initial.html
new file mode 100644
index 0000000000..e9c112bd24
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/readyState_initial.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video}.readyState - default state</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#dom-media-networkstate">spec reference</a></p>
+ <audio id="a">
+ </audio>
+ <video id="v">
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var a = document.getElementById("a");
+ assert_equals(
+ a.readyState,
+ a.HAVE_NOTHING,
+ "audioElement.readyState should be HAVE_NOTHING to begin with");
+}, "audio.readyState - default state");
+
+test(function() {
+ var v = document.getElementById("v");
+ assert_equals(
+ v.readyState,
+ v.HAVE_NOTHING,
+ "videoElement.readyState should be HAVE_NOTHING to begin with");
+}, "video.readyState - default state");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/seeking/seek-to-currentTime.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/seeking/seek-to-currentTime.html
new file mode 100644
index 0000000000..82b27bf87d
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/seeking/seek-to-currentTime.html
@@ -0,0 +1,34 @@
+<!doctype html>
+<title>seek to currentTime</title>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var v = document.createElement('video');
+ v.src = getVideoURI('/media/movie_5');
+ v.onloadedmetadata = t.step_func(function() {
+ assert_greater_than(v.readyState, v.HAVE_NOTHING, 'readyState');
+ assert_greater_than(v.seekable.length, 0, 'seekable ranges');
+ assert_false(v.seeking, 'seeking before setting currentTime');
+ v.currentTime = v.currentTime;
+ assert_true(v.seeking, 'seeking after setting currentTime');
+ var events = [];
+ v.onseeking = v.ontimeupdate = v.onseeked = t.step_func(function(e) {
+ events.push(e.type);
+ // v.seeking can be true or false in the seeking event, see
+ // https://www.w3.org/Bugs/Public/show_bug.cgi?id=24774
+ if (e.type != 'seeking') {
+ assert_equals(v.seeking, false, 'seeking in ' + e.type + ' event');
+ }
+ if (e.type == 'seeked') {
+ assert_array_equals(events, ['seeking', 'timeupdate', 'seeked'],
+ 'fired events');
+ t.done();
+ }
+ });
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/seeking/seek-to-max-value.htm b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/seeking/seek-to-max-value.htm
new file mode 100644
index 0000000000..a31f6c07ab
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/seeking/seek-to-max-value.htm
@@ -0,0 +1,23 @@
+<!doctype html>
+<title>seek to Number.MAX_VALUE</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var v = document.createElement('video');
+ v.src = getVideoURI('/media/movie_5');
+ v.onloadedmetadata = t.step_func(function() {
+ assert_equals(v.seekable.length, 1);
+ v.currentTime = Number.MAX_VALUE;
+ assert_true(v.seeking, 'seeking after setting');
+ assert_equals(v.currentTime, v.seekable.end(0), 'currentTime after setting');
+ v.onseeked = t.step_func(function(e) {
+ assert_false(v.seeking, 'seeking in seeked event');
+ assert_equals(v.currentTime, v.seekable.end(0), 'currentTime in seeked event');
+ t.done();
+ });
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/seeking/seek-to-negative-time.htm b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/seeking/seek-to-negative-time.htm
new file mode 100644
index 0000000000..56a99028de
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/seeking/seek-to-negative-time.htm
@@ -0,0 +1,23 @@
+<!doctype html>
+<title>seek to negative time</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var v = document.createElement('video');
+ v.src = getVideoURI('/media/movie_5');
+ v.onloadedmetadata = t.step_func(function() {
+ assert_equals(v.seekable.start(0), 0, 'earliest seekable time');
+ v.currentTime = -1;
+ assert_true(v.seeking, 'seeking after setting');
+ assert_equals(v.currentTime, 0, 'currentTime after setting');
+ v.onseeked = t.step_func(function(e) {
+ assert_false(v.seeking, 'seeking in seeked event');
+ assert_equals(v.currentTime, 0, 'currentTime in seeked event');
+ t.done();
+ });
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/src_object_blob.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/src_object_blob.html
new file mode 100644
index 0000000000..ae2bb76b26
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/src_object_blob.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>HTMLMediaElement.srcObject blob</title>
+<script src='/common/media.js'></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src=/resources/testdriver.js></script>
+<script src=/resources/testdriver-vendor.js></script>
+<video></video>
+<script>
+ const video = document.querySelector("video");
+ promise_test(async () => {
+ const blob = await fetch(getVideoURI('/media/movie_5'))
+ .then(r => r.blob());
+ try {
+ video.srcObject = blob;
+ } catch (error) {
+ assert_unreached(error);
+ }
+ const done = new Promise(res => video.addEventListener('ended', res));
+ test_driver.bless('initiate media playback', function () {
+ video.play();
+ });
+ return done;
+ });
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/src_reflects_attribute_not_source_elements.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/src_reflects_attribute_not_source_elements.html
new file mode 100644
index 0000000000..3dd43cc3f5
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/src_reflects_attribute_not_source_elements.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video}.src - reflection test</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#dom-media-src">spec reference</a></p>
+ <audio id="audio" src="foo">
+ <source src="barbaz" />
+ </audio>
+ <video id="video" src="foo">
+ <source src="barbaz" />
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ assert_equals(
+ document.getElementById("audio").src.indexOf("barbaz"),
+ -1,
+ "audioElement.src should reflect src attribute, not source child elements");
+}, "audio.src - reflection test");
+
+test(function() {
+ assert_equals(
+ document.getElementById("video").src.indexOf("barbaz"),
+ -1,
+ "videoElement.src should reflect src attribute, not source child elements");
+}, "video.src - reflection test");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cloneNode.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cloneNode.html
new file mode 100644
index 0000000000..9e0f0bf900
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cloneNode.html
@@ -0,0 +1,87 @@
+<!doctype html>
+<title>track element cloneNode</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+ var elm = document.createElement('track');
+ assert_equals(elm.readyState, elm.NONE, 'elm.readyState after element creation');
+ var clone = elm.cloneNode(true);
+ assert_equals(clone.readyState, clone.NONE, 'clone.readyState after element creation');
+ assert_not_equals(clone.track, elm.track, 'clone.track and elm.track');
+}, document.title+', not loaded');
+
+async_test(function(t) {
+ var elm = document.createElement('track');
+ var video = document.createElement('video');
+ video.appendChild(elm);
+ elm.track.mode = 'showing';
+ assert_equals(elm.readyState, elm.NONE, 'elm.readyState after appening to video setting mode');
+ elm.src = 'resources/track.vtt?pipe=trickle(d1)';
+ assert_equals(elm.readyState, elm.NONE, 'elm.readyState after setting src');
+ t.step_timeout(function() {
+ assert_equals(elm.readyState, elm.LOADING, 'elm.readyState in setTimeout');
+ var clone = elm.cloneNode(true);
+ assert_equals(clone.readyState, clone.NONE, 'clone.readyState after element creation');
+ video.appendChild(clone);
+ clone.track.mode = 'showing';
+ assert_equals(clone.readyState, clone.NONE, 'clone.readyState after appending to video and setting mode');
+ assert_not_equals(clone.track, elm.track, 'clone.track and elm.track');
+ t.done();
+ }, 0);
+}, document.title+', loading');
+
+async_test(function(t) {
+ var elm = document.createElement('track');
+ var video = document.createElement('video');
+ video.appendChild(elm);
+ elm.track.mode = 'showing';
+ elm.src = 'data:text/vtt,'+encodeURIComponent('WEBVTT\n\n00:00:00.000 --> 00:00:01.000\nfoo');
+ assert_equals(elm.readyState, elm.NONE, 'elm.readyState after setting src');
+ elm.onload = this.step_func(function() {
+ assert_equals(elm.readyState, elm.LOADED, 'elm.readyState');
+ assert_equals(elm.track.cues.length, 1, 'elm.track.cues.length');
+ assert_equals(elm.track.cues[0].startTime, 0, 'elm.track.cues[0].startTime');
+ assert_equals(elm.track.cues[0].endTime, 1, 'elm.track.cues[0].endTime');
+ assert_equals(elm.track.cues[0].text, 'foo', 'elm.track.cues[0].text');
+ var clone = elm.cloneNode(true);
+ assert_equals(clone.readyState, clone.NONE, 'clone.readyState after element creation');
+ video.appendChild(clone);
+ clone.track.mode = 'showing';
+ assert_equals(clone.readyState, clone.NONE, 'clone.readyState after appending to video and setting mode');
+ assert_not_equals(clone.track, elm.track, 'clone.track and elm.track');
+ clone.onload = this.step_func(function(){
+ assert_equals(clone.readyState, clone.LOADED, 'clone.readyState');
+ assert_not_equals(clone.track, elm.track, 'clone.track and elm.track');
+ assert_not_equals(clone.track.cues, elm.track.cues, 'clone.track.cues and elm.track.cues');
+ assert_equals(clone.track.cues.length, 1, 'clone.track.cues.length');
+ assert_not_equals(clone.track.cues[0], elm.track.cues[0], 'cues[0]');
+ assert_equals(clone.track.cues[0].startTime, 0, 'clone.track.cues[0].startTime');
+ assert_equals(clone.track.cues[0].endTime, 1, 'clone.track.cues[0].endTime');
+ assert_equals(clone.track.cues[0].text, 'foo', 'clone.track.cues[0].text');
+ this.done();
+ });
+ clone.onerror = this.step_func(function() { assert_unreached('clone got error'); });
+ });
+ elm.onerror = this.step_func(function() { assert_unreached('elm got error'); });
+}, document.title+', loaded');
+
+async_test(function(t) {
+ var elm = document.createElement('track');
+ var video = document.createElement('video');
+ video.appendChild(elm);
+ elm.track.mode = 'showing';
+ elm.onerror = t.step_func(function() {
+ assert_equals(elm.readyState, elm.ERROR, 'elm.readyState in onerror');
+ var clone = elm.cloneNode(true);
+ assert_equals(clone.readyState, clone.NONE, 'clone.readyState after element creation');
+ video.appendChild(clone);
+ clone.track.mode = 'showing';
+ assert_equals(clone.readyState, clone.NONE, 'clone.readyState after appending to video and setting mode');
+ assert_not_equals(clone.track, elm.track, 'clone.track and elm.track');
+ clone.onerror = t.step_func_done();
+ });
+ elm.src = 'javascript:"network error"';
+}, document.title+', failed to load');
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/003.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/003.html
new file mode 100644
index 0000000000..4236df29b9
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/003.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: No CORS, same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/004.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/004.html
new file mode 100644
index 0000000000..4f86d011a3
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/004.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: No CORS, same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/005.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/005.html
new file mode 100644
index 0000000000..e6a693400c
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/005.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/006.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/006.html
new file mode 100644
index 0000000000..351b97d677
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/006.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/007.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/007.html
new file mode 100644
index 0000000000..4ccc6b66ac
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/007.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/008.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/008.html
new file mode 100644
index 0000000000..0444a83085
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/008.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/009.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/009.html
new file mode 100644
index 0000000000..dd62232755
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/009.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: No CORS, not same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/010.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/010.html
new file mode 100644
index 0000000000..d75d6f4d6d
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/010.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, not same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:origin, cookie:'no'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/011.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/011.html
new file mode 100644
index 0000000000..6d0fae6de7
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/011.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, not same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:origin, cookie:'no'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/012.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/012.html
new file mode 100644
index 0000000000..110497b494
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/012.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, not same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:origin, cookie:'yes'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/013.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/013.html
new file mode 100644
index 0000000000..d2a9ddb193
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/013.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, not same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:origin, cookie:'yes'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/014.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/014.html
new file mode 100644
index 0000000000..a1d6a8b295
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/014.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: No CORS, same-origin, no headers, redirects to same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}, {cors:'no', cookie:'yes'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/015.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/015.html
new file mode 100644
index 0000000000..2850a24e17
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/015.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: No CORS, same-origin, with headers, redirects to same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}, {cors:'no', cookie:'yes'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/016.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/016.html
new file mode 100644
index 0000000000..5cd5a85d43
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/016.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, same-origin, no headers, redirects to same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}, {cors:'no', cookie:'yes'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/017.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/017.html
new file mode 100644
index 0000000000..0ec5bc3291
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/017.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, same-origin, no headers, redirects to same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}, {cors:'no', cookie:'yes'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/018.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/018.html
new file mode 100644
index 0000000000..f639d043a3
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/018.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, same-origin, no headers, redirects to same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}, {cors:'no', cookie:'yes'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/019.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/019.html
new file mode 100644
index 0000000000..45e1291c92
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/019.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, same-origin, with headers, redirects to same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}, {cors:'no', cookie:'yes'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/020.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/020.html
new file mode 100644
index 0000000000..e1153b6813
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/020.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, not same-origin, no headers, redirects to same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:origin, cookie:'no'}]}; // redirect not followed
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/021.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/021.html
new file mode 100644
index 0000000000..ec2e9d8bb4
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/021.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, not same-origin, with headers, redirects to same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:origin, cookie:'no'}, {cors:'null', cookie:'no'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/022.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/022.html
new file mode 100644
index 0000000000..e8fb0c3d43
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/022.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, not same-origin, with headers, redirects to same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:origin, cookie:'no'}, {cors:'null', cookie:'no'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/023.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/023.html
new file mode 100644
index 0000000000..ac9bb35465
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/023.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, not same-origin, no headers, redirects to same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:origin, cookie:'yes'}]}; // redirect not followed
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/024.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/024.html
new file mode 100644
index 0000000000..302340022d
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/024.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, not same-origin, with headers, redirects to same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:origin, cookie:'yes'}, {cors:'null', cookie:'yes'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/025.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/025.html
new file mode 100644
index 0000000000..5cbe8528e2
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/025.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, not same-origin, with headers, redirects to same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:origin, cookie:'yes'}, {cors:'null', cookie:'yes'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/026.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/026.html
new file mode 100644
index 0000000000..c8386ffff3
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/026.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: No CORS, same-origin, with headers, redirects to not same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:'no', cookie:'yes'}]}; // redirect not followed
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/027.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/027.html
new file mode 100644
index 0000000000..5fe4760e66
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/027.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, same-origin, no headers, redirects to not same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:'no', cookie:'yes'}, {cors:origin, cookie:'no'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/028.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/028.html
new file mode 100644
index 0000000000..6019d37b63
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/028.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, same-origin, with headers, redirects to not same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}, {cors:origin, cookie:'no'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/029.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/029.html
new file mode 100644
index 0000000000..7fa85456de
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/029.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, same-origin, no headers, redirects to not same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:'no', cookie:'yes'}, {cors:origin, cookie:'yes'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/030.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/030.html
new file mode 100644
index 0000000000..f7abf3b1ed
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/030.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, same-origin, with headers, redirects to not same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}, {cors:origin, cookie:'yes'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/031.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/031.html
new file mode 100644
index 0000000000..d709d0bc42
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/031.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, not same-origin, no headers, redirects to not same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:origin, cookie:'no'}]}; // redirect not followed
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/032.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/032.html
new file mode 100644
index 0000000000..62b1008a41
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/032.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, not same-origin, with headers, redirects to not same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:origin, cookie:'no'}, {cors:origin, cookie:'no'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/033.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/033.html
new file mode 100644
index 0000000000..215cae2419
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/033.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, not same-origin, with headers, redirects to not same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:origin, cookie:'no'}, {cors:origin, cookie:'no'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/034.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/034.html
new file mode 100644
index 0000000000..bebb43ba8c
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/034.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, not same-origin, no headers, redirects to not same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:origin, cookie:'yes'}]}; // redirect not followed
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/035.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/035.html
new file mode 100644
index 0000000000..a17fb7dfc1
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/035.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, not same-origin, with headers, redirects to not same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:origin, cookie:'yes'}, {cors:origin, cookie:'yes'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/036.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/036.html
new file mode 100644
index 0000000000..52411177ea
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/036.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, not same-origin, with headers, redirects to not same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:origin, cookie:'yes'}, {cors:origin, cookie:'yes'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/037.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/037.html
new file mode 100644
index 0000000000..675b913a13
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/037.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, same-origin, no headers, redirects to not same-origin, no headers, redirects to same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:'no', cookie:'yes'}, {cors:origin, cookie:'no'}]}; // second redirect not followed
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/038.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/038.html
new file mode 100644
index 0000000000..a29b2bdead
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/038.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, same-origin, with headers, redirects to not same-origin, with headers, redirects to same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}, {cors:origin, cookie:'no'}, {cors:'null', cookie:'no'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/039.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/039.html
new file mode 100644
index 0000000000..fcd4871ddb
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/039.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, same-origin, no headers, redirects to not same-origin, with headers, redirects to same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:'no', cookie:'yes'}, {cors:origin, cookie:'no'}, {cors:'null', cookie:'no'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/040.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/040.html
new file mode 100644
index 0000000000..3c819684c4
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/040.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, same-origin, no headers, redirects to not same-origin, no headers, redirects to same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:'no', cookie:'yes'}, {cors:origin, cookie:'yes'}]}; // second redirect not followed
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/041.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/041.html
new file mode 100644
index 0000000000..f0f81953fc
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/041.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, same-origin, with headers, redirects to not same-origin, with headers, redirects to same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}, {cors:origin, cookie:'yes'}, {cors:'null', cookie:'yes'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/042.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/042.html
new file mode 100644
index 0000000000..c1ffa5f1ea
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/042.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, same-origin, no headers, redirects to not same-origin, with headers, redirects to same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:'no', cookie:'yes'}, {cors:origin, cookie:'yes'}, {cors:'null', cookie:'yes'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/043.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/043.html
new file mode 100644
index 0000000000..09072a9895
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/043.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, same-origin, no headers, redirects to same-origin, no headers, redirects to not same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:'no', cookie:'yes'}, {cors:'no', cookie:'yes'}, {cors:origin, cookie:'no'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/044.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/044.html
new file mode 100644
index 0000000000..0d4a9fefbd
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/044.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, same-origin, no headers, redirects to same-origin, no headers, redirects to not same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}, {cors:'no', cookie:'yes'}, {cors:origin, cookie:'no'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/045.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/045.html
new file mode 100644
index 0000000000..7151364f9c
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/045.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, same-origin, no headers, redirects to same-origin, no headers, redirects to not same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:'no', cookie:'yes'}, {cors:'no', cookie:'yes'}, {cors:origin, cookie:'yes'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/046.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/046.html
new file mode 100644
index 0000000000..e286462814
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/046.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, same-origin, no headers, redirects to same-origin, no headers, redirects to not same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}, {cors:'no', cookie:'yes'}, {cors:origin, cookie:'yes'}]};
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/support/common.js b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/support/common.js
new file mode 100644
index 0000000000..e30c627149
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/support/common.js
@@ -0,0 +1,144 @@
+setup(function(){
+ window.id = token();
+ var p = document.createElement('p');
+ p.innerHTML = 'Test id: <samp>'+id+'</samp>';
+ document.body.appendChild(p);
+ window.actual = {event:null, requests:[]};
+ window.errors = [];
+ window.origin = location.protocol+'//'+location.host;
+ window.escapedOrigin = encodeURIComponent(origin);
+ window.sameOriginURL = "http://{{domains[]}}:{{ports[http][0]}}" + location.pathname.replace(/\/[^\/]+$/, '/');
+ window.otherOriginURL = "http://{{domains[www1]}}:{{ports[http][0]}}" + location.pathname.replace(/\/[^\/]+$/, '/');
+}, {timeout:10000, explicit_done:true});
+
+onload = function() {
+ (async_test()).step(function() {
+ // fail early if track isn't supported
+ assert_true('HTMLTrackElement' in window, 'track not supported');
+ window.corsMode = document.title.match(/^track CORS: (No CORS|Anonymous|Use Credentials)/)[1];
+ var requests_tmp = document.title.substr(('track CORS: '+corsMode+', ').length).split(/, redirects to /g);
+ window.requests = [];
+ requests_tmp.forEach(function(r) {
+ var parts = r.split(', ');
+ requests.push({sameOrigin:parts[0] == 'same-origin', withHeaders:parts[1] == 'with headers'});
+ });
+ if (document.title.indexOf('not same-origin') > -1) {
+ window.hasCrossDomainCookie = true;
+ this.step(setCrossDomainCookie);
+ } else {
+ window.hasCrossDomainCookie = false;
+ this.step(loadTrack);
+ }
+ });
+ done();
+};
+
+function setCrossDomainCookie() {
+ var iframe = document.createElement('iframe');
+ iframe.onload = this.step_func(loadTrack);
+ iframe.src = otherOriginURL + 'support/set-cookie.html#'+id;
+ document.body.appendChild(iframe);
+}
+
+function loadTrack() {
+ var video = document.createElement('video');
+ window.track = document.createElement('track');
+ if (corsMode == 'Anonymous')
+ video.setAttribute('crossorigin', 'anonymous');
+ else if (corsMode == 'Use Credentials')
+ video.setAttribute('crossorigin', 'use-credentials');
+ // else No CORS, omit the crossorigin attribute
+ video.appendChild(track);
+ document.body.appendChild(video);
+ track.track.mode = 'showing';
+ document.cookie = id+'=yes;path=/;max-age=10';
+ var url = '';
+ var r;
+ while (r = requests.pop()) {
+ url = (r.sameOrigin ? sameOriginURL : otherOriginURL) +
+ 'support/cors-tester.py?id=' + id +
+ (r.withHeaders ? '&origin=' + escapedOrigin : '') +
+ (url === '' ? '' : '&redirect=' + encodeURIComponent(url));
+ }
+ track.src = url;
+ track.onerror = track.onload = this.step_func(function(e) {
+ actual.event = e.type;
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', 'support/cors-tester.py?read=true&id=' + id, true);
+ xhr.onload = this.step_func(function() {
+ if (xhr.status == 200) {
+ var lines = xhr.responseText.split('\n');
+ lines.forEach(function(line) {
+ var chunks = line.split(' | ');
+ var current = {};
+ actual.requests.push(current);
+ chunks.forEach(function(chunk) {
+ var nameval = chunk.split(' = ');
+ var name = nameval[0];
+ var value = nameval[1];
+ current[name] = value;
+ });
+ });
+ } else if (xhr.status == 404) {
+ //No stash was found
+ } else {
+ errors.push('got unexpected xhr status: '+xhr.status);
+ }
+ this.step(removeCookies);
+ });
+ xhr.onerror = this.step_func(function() {
+ errors.push('got xhr error');
+ this.step(removeCookies);
+ });
+ xhr.send();
+ });
+}
+
+function removeCookies() {
+ document.cookie = id+'=;path=/;max-age=0';
+ var nextStep = checkData;
+ if (hasCrossDomainCookie) {
+ var iframe = document.createElement('iframe');
+ iframe.onload = this.step_func(nextStep);
+ iframe.src = otherOriginURL + 'support/cors-tester.py?delete-cookie&id=' + id;
+ document.body.appendChild(iframe);
+ } else {
+ this.step(nextStep);
+ }
+}
+
+function removeLog() {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', 'support/cors-tester.py?cleanup&id='+id, true);
+ xhr.onload = this.step_func(function() {
+ assert_equals(xhr.responseText, 'OK', 'failed to clean up log: '+id);
+ this.step(checkData);
+ });
+ xhr.onerror = this.step_func(function() {
+ assert_unreached('failed to clean up log: '+id);
+ });
+ xhr.send();
+}
+
+function checkData() {
+ assert_equals(errors.length, 0, errors);
+ try {
+ if (actual.event == 'load' && expected.event == 'error')
+ assert_unreached('Security problem: got load event but expected error event');
+ assert_object_equals(actual, expected);
+ } catch(ex) {
+ var style = document.createElement('style');
+ style.textContent = '.json-diffs td { vertical-align:top } .json-diffs pre { margin:0 }';
+ document.head.appendChild(style);
+ var table = document.createElement('table');
+ table.border = "";
+ table.className = 'json-diffs';
+ table.innerHTML = '<tr><th>Actual<th>Expected<tr><td><pre></pre><td><pre></pre>';
+ table.getElementsByTagName('pre')[0].textContent = JSON.stringify(actual, null, 2);
+ table.getElementsByTagName('pre')[1].textContent = JSON.stringify(expected, null, 2);
+ document.body.insertBefore(table, document.getElementById('log'));
+ throw ex;
+ }
+ assert_equals(track.track.cues.length, expected.event == 'load' ? 1 : 0, 'track.track.cues.length');
+ this.done();
+}
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/support/cors-tester.py b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/support/cors-tester.py
new file mode 100644
index 0000000000..ad1cce1922
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/support/cors-tester.py
@@ -0,0 +1,50 @@
+from wptserve.handlers import HTTPException
+
+def main(request, response):
+ if request.method != u"GET":
+ raise HTTPException(400, message=u"Method was not GET")
+
+ if not b"id" in request.GET:
+ raise HTTPException(400, message=u"No id")
+
+ id = request.GET[b'id']
+ if b"read" in request.GET:
+ data = request.server.stash.take(id)
+ if data is None:
+ response.set_error(404, u"Tried to read data not yet set")
+ return
+ return [(b"Content-Type", b"text/plain")], data
+
+ elif b"cleanup" in request.GET:
+ request.server.stash.take(id)
+ return b"OK"
+
+ elif b"delete-cookie" in request.GET:
+ response.delete_cookie(id)
+ return [(b"Content-Type", b"text/plain")], b"OK"
+
+ if b"origin" in request.GET:
+ response.headers.set(b'Access-Control-Allow-Origin', request.GET[b'origin'])
+ response.headers.set(b'Access-Control-Allow-Credentials', b'true')
+
+ cors = request.headers.get(b"origin", b"no")
+
+ cookie = request.cookies.first(id, None)
+ cookie_value = cookie.value if cookie is not None else b"no"
+
+ line = b'cors = ' + cors + b' | cookie = ' + cookie_value
+
+ data = request.server.stash.take(id)
+ if data is not None:
+ line = data + b"\n" + line
+
+ request.server.stash.put(id, line)
+
+ if b"redirect" in request.GET:
+ response.status = 302
+ response.headers.set(b'Location', request.GET[b'redirect'])
+ else:
+ return b"""WEBVTT
+
+00:00:00.000 --> 00:00:10.000
+Test"""
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/support/remove-cookie.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/support/remove-cookie.html
new file mode 100644
index 0000000000..00430e3f0e
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/support/remove-cookie.html
@@ -0,0 +1,6 @@
+<!doctype html>
+<title>Remove cookie from location.hash</title>
+<script>
+if (location.hash)
+ document.cookie = decodeURIComponent(location.hash.substr(1))+'=yes;path=/;max-age=0';
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/support/set-cookie.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/support/set-cookie.html
new file mode 100644
index 0000000000..cc1c926386
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/cors/support/set-cookie.html
@@ -0,0 +1,6 @@
+<!doctype html>
+<title>Set cookie from location.hash</title>
+<script>
+if (location.hash)
+ document.cookie = decodeURIComponent(location.hash.substr(1))+'=yes;path=/;max-age=15';
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/crashtests/track-element-src-aborted-load-onerror-crash.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/crashtests/track-element-src-aborted-load-onerror-crash.html
new file mode 100644
index 0000000000..9db5ef0748
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/crashtests/track-element-src-aborted-load-onerror-crash.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<title>HTMLTrackElement 'src' attribute changed, load pending, 'error' handler mutates</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/media.html#start-the-track-processing-model">
+<link rel="help" href="https://crbug.com/1374341">
+<video></video>
+<script>
+ const video = document.querySelector('video');
+ video.style.visibility = 'collapse';
+ video.setAttribute('crossorigin', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa');
+ const track = document.createElement('track');
+ track.src = 'x';
+ track.track.mode = 'hidden';
+ video.appendChild(track);
+ track.onerror = () => {
+ for (let i = 0; i < 10; ++i)
+ video.setAttribute('foo' + i, 'bar');
+ };
+ setTimeout(() => {
+ track.src = 'y';
+ }, 0);
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/no-cuechange-before-play.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/no-cuechange-before-play.html
new file mode 100644
index 0000000000..cd53914ecd
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/no-cuechange-before-play.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Ensure that the 'cuechange' event is not fired before video playback has begun.</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+promise_test(function(t) {
+ let video = document.createElement('video');
+ video.src = getVideoURI('/media/movie_5');
+ video.preload = 'auto';
+
+ // Create a track element. The 'cuechange' event should not be fired.
+ let track = document.createElement('track');
+ track.oncuechange = t.unreached_func('The \`cuechange\` event should not be fired');
+
+ let videoWatcher = new EventWatcher(t, video, 'canplaythrough');
+ let trackWatcher = new EventWatcher(t, track, ['cuechange', 'load'])
+
+ track.src = 'resources/captions-fast.vtt';
+ track.kind = 'captions';
+ track.default = true;
+ track.track.mode = 'showing';
+ video.appendChild(track);
+
+ return Promise.all([videoWatcher.wait_for('canplaythrough'), trackWatcher.wait_for('load')]);
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/align-positioning-bad.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/align-positioning-bad.vtt
new file mode 100644
index 0000000000..ff4c3fb5cd
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/align-positioning-bad.vtt
@@ -0,0 +1,20 @@
+WEBVTT
+Either one or both of positioning and alignment values are invalid.
+
+1
+00:00:00.000 --> 00:00:30.500 position:10% align: start
+Bear is Coming!!!!!
+Positioning on the left bottom, middle aligned,
+because the alignment is mistyped.
+
+2
+00:00:31.000 --> 00:00:45.500 position:200% align:middle
+I said Bear is coming!!!!
+Positioning on the bottom middle, middle aligned,
+because the positioning is off.
+
+3
+00:01:01.000 --> 00:02:00.500 position:-80% align:ends
+I said Bear is coming now!!!!
+Positioning on the bottom middle, middle aligned,
+because both the alignment and positioning don't apply.
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/align-positioning.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/align-positioning.vtt
new file mode 100644
index 0000000000..a6e6af2ef9
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/align-positioning.vtt
@@ -0,0 +1,20 @@
+WEBVTT
+Cues should position at different horizontal positions with different alignments.
+
+1
+00:00:00.000 --> 00:00:30.500 position:10% align:start
+Bear is Coming!!!!!
+Positioning on the left bottom, start aligned, and
+first character rendering position is at 10% of width.
+
+2
+00:00:31.000 --> 00:00:45.500 position:20% align:middle
+I said Bear is coming!!!!
+Positioning on the bottom left, middle aligned, and
+middle character rendering position of each line is at 20% of width.
+
+3
+00:01:01.000 --> 00:02:00.500 align:end position:80%
+I said Bear is coming now!!!!
+Positioning on the bottom right, end aligned, and
+last character rendering position of each line is at 80% of width.
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/align-text-line-position-bad.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/align-text-line-position-bad.vtt
new file mode 100644
index 0000000000..b196f13a20
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/align-text-line-position-bad.vtt
@@ -0,0 +1,21 @@
+WEBVTT
+One or more of line/text positioning and alignment values are invalid (settings are ignored).
+
+1
+00:00:00.000 --> 00:00:30.500 position: 0% align: start line: 0%
+Bear is Coming!!!!!
+None of the cue settings will be applied, just the default.
+
+2
+00:00:31.000 --> 00:00:01.500 position:0% align:end line:-30%
+I said Bear is coming!!!!
+The line position setting is ignored.
+No text is visible though because it's off-screen at position
+0 and the last character is at position 0%.
+
+3
+00:01:01.000 --> 00:01:30.000 line:-3 align:middler position:60%
+I said Bear is coming now!!!!
+Positioning on line 3 from the viewport bottom, middle aligned,
+with middle character of cue at 60% width.
+The alignment is ignored.
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/align-text-line-position.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/align-text-line-position.vtt
new file mode 100644
index 0000000000..dd3a6debb8
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/align-text-line-position.vtt
@@ -0,0 +1,28 @@
+WEBVTT
+Cues with valid alignment, line and text position settings.
+
+1
+00:00:00.000 --> 00:00:15.000 position:10% align:start line:0%
+Bear is Coming!!!!!
+Positioning on the top of the viewport at 10% horizontally,
+start aligned.
+
+00:00:15.500 --> 00:00:30.500 line:0 align:start
+Bear is Coming!!!!!
+This is line 0, middle aligned, first character at 50% width.
+
+2
+00:00:31.000 --> 00:00:45.500 position:80% line:80%
+I said Bear is coming!!!!
+Middle aligned, middle of cue's character is at 80% width and 80% height.
+
+00:00:46.000 --> 00:01:00.500 line:5 align:end position:30%
+I said Bear is coming!!!!
+This is line 6 from the top of the video viewport,
+end aligned with last character at 30% of viewport width.
+
+3
+00:01:01.000 --> 00:01:30.000 line:-3 align:middle position:60%
+I said Bear is coming now!!!!
+Positioning on line 3 from the viewport bottom, middle aligned,
+with middle character of cue at 60% width.
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/alignment-bad.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/alignment-bad.vtt
new file mode 100644
index 0000000000..5beb376f45
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/alignment-bad.vtt
@@ -0,0 +1,22 @@
+WEBVTT
+Cue alignment may only be start, middle, or end. These are all misspelled and so will default to middle.
+
+1
+00:00:00.000 --> 00:00:30.500 align:starta
+Bear is Coming!!!!!
+Erroneous alignment value -> middle.
+
+2
+00:00:31.000 --> 00:01:00.500 align:-start
+I said Bear is coming!!!!
+Erroneous alignment value --> middle.
+
+3
+00:01:01.000 --> 00:02:00.500 align: end
+I said Bear is coming now!!!!
+Erroneous alignment value with surplus whitespace --> middle.
+
+4
+00:02:01.000 --> 100:20:00.500 align:piugjk
+I said Bear is coming now!!!!
+Erroneous alignment value -> middle.
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/alignment-ltr.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/alignment-ltr.vtt
new file mode 100644
index 0000000000..673b29ac85
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/alignment-ltr.vtt
@@ -0,0 +1,22 @@
+WEBVTT
+Cue alignment may be start, middle, or end (default is middle).
+
+1
+00:00:00.000 --> 00:00:30.500 align:start
+الدب قادم!!!!!
+بدء محاذاته.
+
+2
+00:00:31.000 --> 00:01:00.500 align:middle
+قلت الدب قادم!!
+محاذاة الوسط.
+
+3
+00:01:01.000 --> 00:02:00.500 align:end
+قلت الدب قادم الآن!!
+محاذاة الغاية.
+
+4
+00:02:01.000 --> 100:20:00.500
+قلت الدب قادم الآن!!
+الافتراضية هي محاذاة الوسط. \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/alignment.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/alignment.vtt
new file mode 100644
index 0000000000..ad7792f772
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/alignment.vtt
@@ -0,0 +1,22 @@
+WEBVTT
+Cue alignment may be start, middle, or end (default is middle).
+
+1
+00:00:00.000 --> 00:00:30.500 align:start
+Bear is Coming!!!!!
+Start align.
+
+2
+00:00:31.000 --> 00:01:00.500 align:middle
+I said Bear is coming!!!!
+Middle align.
+
+3
+00:01:01.000 --> 00:02:00.500 align:end
+I said Bear is coming now!!!!
+End align.
+
+4
+00:02:01.000 --> 100:20:00.500
+I said Bear is coming now!!!!
+Default is middle alignment. \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/bom.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/bom.vtt
new file mode 100644
index 0000000000..0c8de32bcb
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/bom.vtt
@@ -0,0 +1,10 @@
+WEBVTT FILE
+A BOM character at the start of a file should be ignored.
+
+1
+00:00:00.000 --> 00:00:30.500
+Bear is Coming!!!!!
+
+2
+00:00:31.000 --> 00:20:00.500
+I said Bear is coming!!!! \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/captions-fast.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/captions-fast.vtt
new file mode 100644
index 0000000000..7fe5b1241a
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/captions-fast.vtt
@@ -0,0 +1,13 @@
+WEBVTT
+
+1
+00:00:00.000 --> 00:00:00.300
+Lorem
+
+2
+00:00:00.300 --> 00:00:01.300
+ipsum
+
+3
+00:00:01.800 --> 00:00:02.800
+dolor
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/captions-gaps.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/captions-gaps.vtt
new file mode 100644
index 0000000000..44c74665c2
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/captions-gaps.vtt
@@ -0,0 +1,18 @@
+WEBVTT
+
+1
+00:00:01.000 --> 00:00:02.000
+Lorem ipsum dolor sit amet,
+
+2
+00:00:03.000 --> 00:00:04.000
+consectetuer adipiscing elit,
+
+3
+00:00:05.000 --> 00:00:06.000
+sed diam nonummy nibh euismod tincidunt
+
+4
+00:00:07.000 --> 00:00:08.000
+ut laoreet dolore magna aliquam erat volutpat.
+
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/captions-html.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/captions-html.vtt
new file mode 100644
index 0000000000..0730f8bc40
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/captions-html.vtt
@@ -0,0 +1,18 @@
+WEBVTT
+
+1
+00:00:00.000 --> 00:00:01.000
+Lorem <b>ipsum</b> <u>dolor</u> <i.sit>sit</i> amet,
+
+2
+00:00:03.000 --> 00:00:04.000
+consectetuer adipiscing elit,
+
+3
+00:00:05.000 --> 00:00:06.000
+sed diam nonummy nibh euismod tincidunt
+
+4
+00:00:07.000 --> 00:00:08.000
+ut laoreet dolore magna aliquam erat volutpat.
+
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/captions.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/captions.vtt
new file mode 100644
index 0000000000..787c430868
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/captions.vtt
@@ -0,0 +1,18 @@
+WEBVTT
+
+1
+00:00:00.000 --> 00:00:01.000
+Lorem
+
+2
+00:00:01.000 --> 00:00:02.000
+ipsum
+
+3
+00:00:02.000 --> 00:00:03.000
+dolor
+
+4
+00:00:03.000 --> 00:00:04.000
+sit
+
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/class-bad.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/class-bad.vtt
new file mode 100644
index 0000000000..650ea2c496
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/class-bad.vtt
@@ -0,0 +1,17 @@
+WEBVTT
+Invalid <c> class markup.
+
+1
+00:00:00.000 --> 00:00:30.500 align:start position:20%
+<c .black>Bear is Coming!!!!!</c>
+The space signified an annotation start.
+
+2
+00:00:31.000 --> 00:01:00.500 align:start position:20%
+<c.red&large>I said Bear is coming!!!!</c>
+Probably should only allow characters that CSS allows in class names.
+
+3
+00:01:01.000 --> 00:02:00.500 align:start position:20%
+I said <c.9red.upper+case>Bear is coming now</c>!!!!
+Probably should only allow characters that CSS allows in class names.
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/class.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/class.vtt
new file mode 100644
index 0000000000..ea3ef623f5
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/class.vtt
@@ -0,0 +1,14 @@
+WEBVTT
+Cue text fragment with <c> class markup is mapped to HTML <span> element with CSS classes.
+
+1
+00:00:00.000 --> 00:00:30.500 align:start position:20%
+<c.black>Bear is Coming!!!!!</c>
+
+2
+00:00:31.000 --> 00:01:00.500 align:start position:20%
+<c.green>I said Bear is coming!!!!</c>
+
+3
+00:01:01.000 --> 00:02:00.500 align:start position:20%
+I said <c.red.uppercase>Bear is coming now</c>!!!!
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-id-error.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-id-error.vtt
new file mode 100644
index 0000000000..2b5db0c1da
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-id-error.vtt
@@ -0,0 +1,14 @@
+WEBVTT
+Cue identifiers cannot contain the string "-->".
+
+-->random_id
+00:00:00.000 --> 00:00:30.500
+Bear is Coming!!!!!
+
+another random identifier-->
+00:00:31.000 --> 00:01:00.500
+I said Bear is coming!!!!
+
+identifier-->too
+00:01:01.000 --> 00:20:00.500
+I said Bear is coming now!!!! \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-id.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-id.vtt
new file mode 100644
index 0000000000..3902118620
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-id.vtt
@@ -0,0 +1,18 @@
+WEBVTT
+Random text is accepted for cue identifiers.
+
+random_id
+00:00:00.000 --> 00:00:30.500
+Bear is Coming!!!!!
+
+another random identifier
+00:00:31.000 --> 00:01:00.500
+I said Bear is coming!!!!
+
+identifier--too
+00:01:01.000 --> 00:02:00.500
+I said Bear is coming now!!!!
+
+identifier--too
+00:02:01.000 --> 00:03:00.500
+Duplicate identifier \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-no-id-error.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-no-id-error.vtt
new file mode 100644
index 0000000000..111bae6344
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-no-id-error.vtt
@@ -0,0 +1,14 @@
+WEBVTT
+Cue identifiers cannot contain "-->". Whole cue is ignored.
+
+-->
+00:00:00.000 --> 00:00:30.500
+Bear is Coming!!!!!
+
+-->
+00:00:31.000 --> 00:01:00.500
+I said Bear is coming!!!!
+
+-->
+00:01:01.000 --> 00:20:00.500
+I said Bear is coming now!!!! \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-no-id.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-no-id.vtt
new file mode 100644
index 0000000000..0d52a70ee4
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-no-id.vtt
@@ -0,0 +1,11 @@
+WEBVTT
+Cues don't have to have identifiers.
+
+00:00:00.000 --> 00:00:30.500
+Bear is Coming!!!!!
+
+00:00:31.000 --> 00:01:00.500
+I said Bear is coming!!!!
+
+00:01:01.000 --> 00:20:00.500
+I said Bear is coming now!!!! \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-recovery-cuetext.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-recovery-cuetext.vtt
new file mode 100644
index 0000000000..88f56cceca
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-recovery-cuetext.vtt
@@ -0,0 +1,6 @@
+WEBVTT
+
+00:00.000 --> 00:01.000
+Valid cue 1
+00:02.000 --> 00:03.000
+Valid cue 2
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-recovery-header.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-recovery-header.vtt
new file mode 100644
index 0000000000..205955e3e4
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-recovery-header.vtt
@@ -0,0 +1,6 @@
+WEBVTT
+00:00.000 --> 00:01.000
+Valid cue 1
+
+00:02.000 --> 00:03.000
+Valid cue 2
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-recovery-note.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-recovery-note.vtt
new file mode 100644
index 0000000000..56defcc48b
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-recovery-note.vtt
@@ -0,0 +1,9 @@
+WEBVTT
+
+00:00.000 --> 00:01.000
+Valid cue 1
+
+NOTE about something
+NOTE or something else - maybe an identifier
+00:02.000 --> 00:03.000
+Valid cue 2
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size-align-bad.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size-align-bad.vtt
new file mode 100644
index 0000000000..5e4a61a5e4
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size-align-bad.vtt
@@ -0,0 +1,18 @@
+WEBVTT
+Either size or alignment are invalid.
+
+1
+00:00:00.000 --> 00:00:30.500 size:100% align:@start
+Bear is Coming!!!!!
+Box for the cue is 100% of the video viewport width, alignment is ignored.
+
+2
+00:00:31.000 --> 00:01:00.500 size:-10% align:end
+I said Bear is coming!!!!
+Box for the cue is as big as the text, no line wrapping,
+(except if viewport is too small) and end aligned.
+
+3
+00:01:01.000 --> 00:02:00.500 size:110% align:@end
+I said Bear is coming now!!!!
+Both cue size and alignment are ignored.
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size-align.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size-align.vtt
new file mode 100644
index 0000000000..6d36536539
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size-align.vtt
@@ -0,0 +1,19 @@
+WEBVTT
+Valid cue size with alignment settings.
+
+1
+00:00:00.000 --> 00:00:30.500 size:100% align:start
+Bear is Coming!!!!!
+Box for the cue is 100% of the video viewport width
+and because of the start align, all text is left aligned on the video viewport.
+
+2
+00:00:31.000 --> 00:01:00.500 size:10% align:end
+I said Bear is coming!!!!
+Box for the cue is 10% of the video viewport width, which will mean that automatic line wrapping will happen
+and the text is aligned to the end.
+
+3
+00:01:01.000 --> 00:02:00.500 size:0% align:middle
+I said Bear is coming now!!!!
+Cue text box size of 0 is acceptable, even if not visible.
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size-bad.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size-bad.vtt
new file mode 100644
index 0000000000..700600d7a7
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size-bad.vtt
@@ -0,0 +1,17 @@
+WEBVTT
+Invalid cue sizes (all settings are ignored).
+
+1
+00:00:00.000 --> 00:00:30.500 size: 50%
+Bear is Coming!!!!!
+Cue size setting doesn't parse and is ignored.
+
+2
+00:00:31.000 --> 00:01:00.500 size:-10%
+I said Bear is coming!!!!
+Negative cue size setting is not acceptable and is ignored.
+
+3
+00:01:01.000 --> 00:02:00.500 size:4000%
+I said Bear is coming now!!!!
+Cue size beyond 100% is not acceptable and is ignored.
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size.vtt
new file mode 100644
index 0000000000..017d59a18b
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size.vtt
@@ -0,0 +1,19 @@
+WEBVTT
+Valid cue size values.
+
+1
+00:00:00.000 --> 00:00:30.500 size:100%
+Bear is Coming!!!!!
+Box for the cue is 100% of the video viewport width,
+exemplified through background color,
+even if the text needs less.
+
+2
+00:00:31.000 --> 00:01:00.500 size:10%
+I said Bear is coming!!!!
+Box for the cue is 10% of the video viewport width, which will mean that automatic line wrapping will happen.
+
+3
+00:01:01.000 --> 00:02:00.500 size:0%
+I said Bear is coming now!!!!
+Cue text box size of 0 is acceptable, even if not visible.
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cues-chrono-order.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cues-chrono-order.vtt
new file mode 100644
index 0000000000..fd6d484f88
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cues-chrono-order.vtt
@@ -0,0 +1,14 @@
+WEBVTT
+Cues that have overlapping time ranges.
+
+1
+00:00:01.000 --> 00:00:02.000
+Bear is Coming!!!!!
+
+2
+00:00:02.500 --> 00:00:03.500
+I said Bear is coming!!!!
+
+3
+00:00:04.000 --> 00:00:05.000
+I said Bear is coming now!!!! \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cues-no-separation.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cues-no-separation.vtt
new file mode 100644
index 0000000000..9062c67ede
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cues-no-separation.vtt
@@ -0,0 +1,11 @@
+WEBVTT
+Cues must be separated by at least one blank line, otherwise treated like one big cue.
+
+1
+00:00:00.000 --> 00:00:30.500
+Bear is Coming!!!!!
+2
+00:00:31.000 --> 00:01:00.500
+I said Bear is coming!!!!
+00:01:01.000 --> 100:20:00.500
+I said Bear is coming now!!!! \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cues-overlapping.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cues-overlapping.vtt
new file mode 100644
index 0000000000..3f035d331f
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cues-overlapping.vtt
@@ -0,0 +1,14 @@
+WEBVTT
+Cues that have overlapping time ranges.
+
+1
+00:00:01.000 --> 00:00:06.000
+Bear is Coming!!!!!
+
+2
+00:00:01.500 --> 00:00:05.000
+I said Bear is coming!!!!
+
+3
+00:00:02.000 --> 00:00:05.000
+I said Bear is coming now!!!! \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cues.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cues.vtt
new file mode 100644
index 0000000000..125ed66785
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cues.vtt
@@ -0,0 +1,17 @@
+WEBVTT
+Cues may be separated by one or more blank lines.
+
+1
+00:00:00.000 --> 00:00:30.500
+Bear is Coming!!!!!
+
+
+2
+00:00:31.000 --> 00:01:00.500
+I said Bear is coming!!!!
+
+
+
+3
+00:01:01.000 --> 100:20:00.500
+I said Bear is coming now!!!! \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/default-styles.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/default-styles.vtt
new file mode 100644
index 0000000000..d890ca3f71
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/default-styles.vtt
@@ -0,0 +1,19 @@
+WEBVTT
+
+COMMENT-->
+this is a comment, that will parse as part of the header;
+the STYLE and DEFAULTS below are parsed as invalid cues
+
+STYLE-->
+::cue(.narration) { color: blue; }
+
+DEFAULTS -->
+line:-1 align:middle size:50%
+
+1
+00:00:00.000 --> 00:00:30.500
+Bear is Coming!!!!!
+
+2
+00:00:31.000 --> 00:20:00.500
+I said Bear is coming!!!! \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/degenerate-cues.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/degenerate-cues.vtt
new file mode 100644
index 0000000000..c04390420f
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/degenerate-cues.vtt
@@ -0,0 +1,5 @@
+WEBVTT
+
+00:00.000 --> 00:01.000
+00:02.000 --> 00:03.000
+00:04.000 --> 00:05.000
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/empty-cue.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/empty-cue.vtt
new file mode 100644
index 0000000000..dbfde34b69
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/empty-cue.vtt
@@ -0,0 +1,11 @@
+WEBVTT
+Empty cues should not be discarded.
+
+1
+00:00:00.000 --> 00:00:30.500 align:start position:20%
+
+2
+00:00:31.000 --> 00:01:00.500 align:start position:20%
+
+3
+00:01:01.000 --> 00:02:00.500 align:start position:20%
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/entities-wrong.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/entities-wrong.vtt
new file mode 100644
index 0000000000..f45fee4793
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/entities-wrong.vtt
@@ -0,0 +1,15 @@
+WEBVTT
+Invalid use of < and > characters.
+
+2
+00:00:31.000 --> 00:01:00.500 align:start position:20%
+This cue has a less than < character.
+It turns everything from there on into an annotation
+for an empty tag and ends only at the next &gt; or &amp; character.
+
+
+3
+00:01:01.000 --> 00:02:00.500 align:start position:20%
+This cue has a greater than > character.
+Since it's not related to a &lt; character,
+it's just interpreted as text.
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/entities.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/entities.vtt
new file mode 100644
index 0000000000..a8817954a6
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/entities.vtt
@@ -0,0 +1,30 @@
+WEBVTT
+Cue content with escape characters for &, <, >, LRM, RLM and non-breaking space.
+
+1
+00:00:00.000 --> 00:00:30.500 align:start position:20%
+This cue has an ampersand &amp; character.
+
+2
+00:00:31.000 --> 00:01:00.500 align:start position:20%
+This cue has a less than &lt; character.
+
+3
+00:01:01.000 --> 00:02:00.500 align:start position:20%
+This cue has a greater than &gt; character.
+
+4
+00:02:01.000 --> 00:02:30.500 align:start position:20%
+This cue has a Left-to-Right Mark &lrm;.
+
+5
+00:02:31.000 --> 00:03:00.500 align:start position:20%
+This cue has a Right-to-Left Mark &rlm;.
+
+6
+00:03:01.000 --> 00:03:30.500 align:start position:20%
+This cue has a non-breaking space &nbsp;.
+
+7
+00:03:31.000 --> 00:04:00.500
+This & is parsed to the same as &amp;.
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/interspersed-non-cue.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/interspersed-non-cue.vtt
new file mode 100644
index 0000000000..c825ab32e2
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/interspersed-non-cue.vtt
@@ -0,0 +1,9 @@
+WEBVTT
+
+00:00.000 --> 00:01.000
+First
+
+Stray Id or other non-cue content
+
+00:02.000 --> 00:03.000
+Second
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/iso2022jp3.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/iso2022jp3.vtt
new file mode 100644
index 0000000000..10a1624386
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/iso2022jp3.vtt
@@ -0,0 +1,10 @@
+WEBVTT FILE
+Different encodings (iconv) should not be recognized as WebVTT a file.
+
+1
+00:00:00.000 --> 00:00:30.500
+$B7J5$H=CG(B
+
+2
+00:00:31.000 --> 00:20:00.500
+$BEENOITB-(B
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/large-timestamp.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/large-timestamp.vtt
new file mode 100644
index 0000000000..e6c18ce3bd
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/large-timestamp.vtt
@@ -0,0 +1,5 @@
+WEBVTT
+
+1
+1234567:00:00.000 --> 1234567890:00:00.000
+A very long cue.
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/line-position-bad.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/line-position-bad.vtt
new file mode 100644
index 0000000000..3d52175729
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/line-position-bad.vtt
@@ -0,0 +1,30 @@
+WEBVTT
+Invalid positioning values (all settings are ignored).
+
+1
+00:00:00.000 --> 00:00:15.000 line:-0%
+Bear is Coming!!!!!
+Negative percentages are not allowed.
+Line position is ignored.
+
+2
+00:00:31.000 --> 00:00:45.500 line:+50%
+I said Bear is coming!!!!
+Non-numbers are not allowed.
+Line position is ignored.
+
+00:00:46.000 --> 00:01:00.500 line:+5
+I said Bear is coming!!!!
+Plus sign is not allowed.
+Line position is ignored.
+
+3
+00:01:01.000 --> 00:01:30.000 line:10%0%
+I said Bear is coming now!!!!
+Doesn't parse into a percentage.
+Line position is ignored.
+
+00:01:31.000 --> 00:02:00.500 line:-10l
+I said Bear is coming now!!!!
+Doesn't parse into a number.
+Line position is ignored.
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/line-position.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/line-position.vtt
new file mode 100644
index 0000000000..82f7e2a523
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/line-position.vtt
@@ -0,0 +1,37 @@
+WEBVTT
+Cues with valid vertical line positioning values.
+
+1
+00:00:00.000 --> 00:00:15.000 line:0%
+Bear is Coming!!!!!
+Positioning on the top of the viewport, in the middle.
+
+00:00:15.500 --> 00:00:30.500 line:0
+Bear is Coming!!!!!
+This is line 0.
+Positioning on the top of the viewport, in the middle.
+
+2
+00:00:31.000 --> 00:00:45.500 line:50%
+I said Bear is coming!!!!
+Positioning on the center of the video.
+
+
+00:00:46.000 --> 00:01:00.500 line:5
+I said Bear is coming!!!!
+This is line 6 from the top of the video viewport.
+
+3
+00:01:01.000 --> 00:01:30.000 line:100%
+I said Bear is coming now!!!!
+Positioning on the bottom middle.
+
+00:01:31.000 --> 00:02:00.500 line:-1
+I said Bear is coming now!!!!
+This is the first line at the bottom of the video viewport.
+Positioning on the bottom middle. Only 1 line shows.
+
+00:02:01.000 --> 00:02:30.000 line:500
+I said Bear is coming now!!!!
+This is legal,
+even though the line will likely not be within the video viewport.
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/markup-bad.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/markup-bad.vtt
new file mode 100644
index 0000000000..4ff7add2d7
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/markup-bad.vtt
@@ -0,0 +1,22 @@
+WEBVTT
+Cue text has invalid markup of <b>, <i>, <u>, <rt> and <ruby>. Has a bad effect on the remainder of the cue.
+
+1
+00:00:00.000 --> 00:00:15.000 align:start position:20%
+The following bear starts bold but end is broken:
+<b>Bear</ b> is Coming!!!!!
+
+00:00:15.500 --> 00:00:30.500 align:start position:20%
+The following bear is not in italics but the markup is removed:
+< i>Bear</i> is Coming!!!!!
+
+2
+00:00:31.000 --> 00:01:00.500 align:start position:20%
+The following bear is not underlined and markup is removed:
+I said < u >Bear</u> is coming!!!!
+
+3
+00:01:01.000 --> 00:01:30.000 align:start position:20%
+The following bear is not ruby annotated and markup is removed:
+I said <ru by>Bear<rt>bear with me</rt></ruby> is coming!!!!
+
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/markup.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/markup.vtt
new file mode 100644
index 0000000000..252a599b5f
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/markup.vtt
@@ -0,0 +1,22 @@
+WEBVTT
+Cues with <b>, <i>, <u>, <rt> and <ruby> tags (all valid).
+
+1
+00:00:00.000 --> 00:00:15.000 align:start position:20%
+The following bear is bold:
+<b>Bear</b> is Coming!!!!!
+
+00:00:15.500 --> 00:00:30.500 align:start position:20%
+The following bear is in italics and has a class of "larger":
+<i.larger>Bear</i> is Coming!!!!!
+
+2
+00:00:31.000 --> 00:01:00.500 align:start position:20%
+The following bear is underlined even though the element has a blank:
+I said <u >Bear</u> is coming!!!!
+
+3
+00:01:01.000 --> 00:01:30.000 align:start position:20%
+The following bear is ruby annotated:
+I said <ruby>Bear<rt>bear with me</rt></ruby> is coming!!!!
+
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/metadata-area.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/metadata-area.vtt
new file mode 100644
index 0000000000..255298aeb0
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/metadata-area.vtt
@@ -0,0 +1,14 @@
+WEBVTT
+This is where metadata would go and these lines should be skipped.
+author = silviapf@google.com
+COMMENT-->
+this is a comment, that will parse as part of the header;
+the STYLE and DEFAULTS below are parsed as invalid cues
+
+1
+00:00:00.000 --> 00:00:30.500
+Bear is Coming!!!!!
+
+2
+00:00:31.000 --> 00:20:00.500
+I said Bear is coming!!!! \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/metadata.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/metadata.vtt
new file mode 100644
index 0000000000..03d8cf4a1c
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/metadata.vtt
@@ -0,0 +1,38 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:01.000
+Lorem ipsum dolor sit amet,
+
+00:00:02.000 --> 00:00:03.000
+consectetuer adipiscing elit,
+
+00:00:04.000 --> 00:00:05.000
+sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
+
+00:00:06.000 --> 00:00:07.000
+Ut wisi enim ad minim veniam,
+
+00:00:08.000 --> 00:00:09.000
+quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
+
+00:00:10.000 --> 00:00:11.000
+Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat,
+
+00:00:12.000 --> 00:00:13.000
+vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio
+
+00:00:14.000 --> 00:00:15.000
+dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
+
+00:00:16.000 --> 00:00:17.000
+Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id
+
+00:00:18.000 --> 00:00:19.000
+quod mazim placerat facer possim assum.
+
+00:00:20.000 --> 00:00:21.000
+Typi non habent claritatem insitam;
+
+00:00:22.000 --> 00:00:23.000
+est usus legentis in iis qui facit eorum claritatem.
+
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/missed-cues.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/missed-cues.vtt
new file mode 100644
index 0000000000..36e8366e90
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/missed-cues.vtt
@@ -0,0 +1,31 @@
+WEBVTT
+Events should be triggered for missed (skipped) cues during normal playback.
+
+1
+00:00:00.000 --> 00:00:01.500 align:start position:20%
+Bear is Coming!!!!!
+And what kind of a bear it is - just have look.
+
+2
+00:00:02.000 --> 00:00:02.500 align:start position:20%
+I said Bear is coming!!!!
+
+3
+00:00:05.500 --> 00:00:05.501 align:start position:20%
+I said Bear is coming now!!!!
+
+4
+00:00:05.700 --> 00:00:05.701 align:start position:20%
+This is the second missed cue in the test.
+
+5
+00:00:05.800 --> 00:00:05.800 align:start position:20%
+Third missed cue - zero-length cue.
+
+6
+00:00:05.850 --> 00:00:05.851 align:start position:20%
+Fourth missed cue.
+
+7
+00:00:05.950 --> 00:00:01.100
+Negative length cue. Should be treated correctly.
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/no-newline-at-eof.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/no-newline-at-eof.vtt
new file mode 100644
index 0000000000..49e4e9051a
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/no-newline-at-eof.vtt
@@ -0,0 +1,6 @@
+WEBVTT
+A file with no line terminator at the end should be fine (last cue should be recognized).
+
+1
+00:00:00.000 --> 00:00:30.500
+Bear is Coming!!!!! \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/no-timings.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/no-timings.vtt
new file mode 100644
index 0000000000..4cb85b6df2
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/no-timings.vtt
@@ -0,0 +1,13 @@
+WEBVTT
+Cues without timings are ignored.
+
+1
+00:00:00.000
+Bear is Coming!!!!!
+
+2
+00h:00m:31s.000ms
+I said Bear is coming!!!!
+
+3
+I said Bear is coming now!!!! \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/no-webvtt.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/no-webvtt.vtt
new file mode 100644
index 0000000000..12053b2703
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/no-webvtt.vtt
@@ -0,0 +1,10 @@
+AWEBVTT FILE
+A file with wrong file header should not be recognized as a webvtt file.
+
+1
+00:00:00.000 --> 00:00:30.500
+Bear is Coming!!!!!
+
+2
+00:00:31.000 --> 00:20:00.500
+I said Bear is coming!!!! \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/positioning-bad.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/positioning-bad.vtt
new file mode 100644
index 0000000000..58ca6792be
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/positioning-bad.vtt
@@ -0,0 +1,39 @@
+WEBVTT
+Invalid horizontal positioning values (all settings are ignored).
+
+1
+00:00:00.000 --> 00:00:15.500 position:-5%
+Bear is Coming!!!!!
+This would be off screen -> ignored.
+
+00:00:16.000 --> 00:00:30.500 position:150%
+Bear is Coming!!!!!
+This would be off screen -> ignored.
+
+2
+00:00:31.000 --> 00:00:45.500 position:50
+I said Bear is coming!!!!
+Missing percent sign -> ignored.
+
+2
+00:00:46.000 --> 00:01:00.500 position:50a%
+I said Bear is coming!!!!
+Surplus character between number and percent sign -> ignored.
+
+3
+00:01:01.000 --> 00:01:30.500 position:100%-fj
+I said Bear is coming now!!!!
+Surplus characters after percent sign -> ignored.
+
+
+00:01:31.000 --> 00:02:00.500 position:100asdf
+I said Bear is coming now!!!!
+Surplus characters and no percent sign -> ignored.
+
+00:02:01.000 --> 00:02:02.000 position:e50%
+I said Bear is coming now!!!!
+Surplus characters at beginning of size string -> ignored.
+
+00:02:02.100 --> 00:02:02.500 position:5g0%
+I said Bear is coming now!!!!
+Surplus characters in middle of size string -> ignored.
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/positioning-ltr.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/positioning-ltr.vtt
new file mode 100644
index 0000000000..b23a7446b7
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/positioning-ltr.vtt
@@ -0,0 +1,21 @@
+WEBVTT
+Valid horizontal positioning values.
+
+1
+00:00:00.000 --> 00:00:30.500 position:0%
+الدب قادم!!!!!
+تحديد المواقع في أسفل اليمين.
+
+2
+00:00:31.000 --> 00:00:45.500 position:50%
+قلت الدب قادم!!
+تحديد المواقع في منتصف القاع.
+
+00:00:46.000 --> 00:01:00.500
+قلت الدب قادم!!
+المواقع الافتراضية على منتصف أسفل تزال قائمة.
+
+3
+00:01:01.000 --> 00:02:00.500 position:100%
+قلت الدب قادم الآن!!
+غادر لتحديد المواقع في القاع.
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/positioning.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/positioning.vtt
new file mode 100644
index 0000000000..ccf6024da0
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/positioning.vtt
@@ -0,0 +1,21 @@
+WEBVTT
+Valid horizontal positioning values.
+
+1
+00:00:00.000 --> 00:00:30.500 position:0%
+Bear is Coming!!!!!
+Positioning on the left bottom.
+
+2
+00:00:31.000 --> 00:00:45.500 position:50%
+I said Bear is coming!!!!
+Positioning on the bottom middle.
+
+00:00:46.000 --> 00:01:00.500
+I said Bear is coming!!!!
+Default positioning on the bottom middle still.
+
+3
+00:01:01.000 --> 00:02:00.500 position:100%
+I said Bear is coming now!!!!
+Positioning on the bottom right.
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/settings-bad-separation.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/settings-bad-separation.vtt
new file mode 100644
index 0000000000..cbfe6ea6e9
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/settings-bad-separation.vtt
@@ -0,0 +1,20 @@
+WEBVTT
+Cues settings may only be separated by spaces or tabs, but illegal characters
+between settings are ignored.
+
+1
+00:00:00.000 --> 00:00:30.500 - line:43% position:10% -
+Bear is Coming!!!!! Bad separator ignored.
+
+2
+00:00:31.000 --> 00:01:00.500 --> position:50% Vertical:lr align:end
+I said Bear is coming!!!! Bad separator and setting ignored.
+
+3
+00:01:01.000 --> 00:02:00.500 <align:end> <position:90%>
+I said Bear is coming now!!!! Bad setting markup. Not ignored because the settings are
+not delimited by spaces or tabs.
+
+4
+00:02:01.000 --> 100:20:00.500 / vertical:lr | position:90%
+I said Bear is coming now!!!! Bad separator ignored.
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/settings.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/settings.vtt
new file mode 100644
index 0000000000..dd6b02296a
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/settings.vtt
@@ -0,0 +1,18 @@
+WEBVTT
+Cue settings may be separated by spaces or tabs.
+
+1
+00:00:00.000 --> 00:00:30.500 line:100% align:start
+Bear is Coming!!!!! One blank.
+
+2
+00:00:31.000 --> 00:01:00.500 position:40% vertical:rl line:15%
+I said Bear is coming!!!! Several blanks.
+
+3
+00:01:01.000 --> 00:02:00.500 align:middle position:10%
+I said Bear is coming now!!!! Tab separator.
+
+4
+00:02:01.000 --> 100:20:00.500 line:95% vertical:lr align:end
+I said Bear is coming now!!!! Tab separators. \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/simple-captions.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/simple-captions.vtt
new file mode 100644
index 0000000000..9815b111da
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/simple-captions.vtt
@@ -0,0 +1,17 @@
+WEBVTT
+
+0
+00:00:04.000 --> 00:00:04.500
+First cue
+
+1
+00:00:04.500 --> 00:00:05.000
+Lorem
+
+2
+00:00:05.000 --> 00:00:05.500
+ipsum
+
+3
+00:00:05.500 --> 00:00:05.501
+Missed cue with pause-on-exit
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/sorted-dispatch.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/sorted-dispatch.vtt
new file mode 100644
index 0000000000..438ea6abf9
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/sorted-dispatch.vtt
@@ -0,0 +1,34 @@
+WEBVTT
+Enter and exit events should be dispatched in a sorted order according to their times.
+
+0
+00:00:04.000 --> 00:00:04.500
+Missed cue that should not be considered because of seeking.
+
+1
+00:00:05.100 --> 00:00:05.800 align:start position:20%
+Bear is Coming!!!!!
+
+2
+00:00:05.100 --> 00:00:05.101
+Missed cue 1
+
+3
+00:00:05.100 --> 00:00:05.301
+And what kind of a bear it is - just have look.
+
+4
+00:00:05.100 --> 00:00:05.101
+Missed Cue 2
+
+5
+00:00:05.300 --> 00:00:05.800 align:start position:20%
+I said Bear is coming!!!!
+
+6
+00:00:05.990 --> 00:00:05.993 align:start position:20%
+I said Bear is coming now!!!!
+
+7
+00:00:05.994 --> 00:00:05.998 align:start position:20%
+Bear is already here
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timestamp-bad.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timestamp-bad.vtt
new file mode 100644
index 0000000000..4479cdb722
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timestamp-bad.vtt
@@ -0,0 +1,17 @@
+WEBVTT
+Invalid <timestamp> markup.
+
+1
+00:00:00.000 --> 00:00:30.500 align:start position:20%
+This <00:00:05.000>cue <00:00:10.000>is <00:00:12.000>painted <00:00:08.000>on.
+But since the last two timestamps are out of order, they are ignored.
+
+2
+00:00:31.000 --> 00:01:00.500 align:start position:20%
+I <00:00:20.000>said <00:00:22.000>Bear <00:00:24.000>is <00:00:26.000>coming!!!!
+All of these timestamps are before the start of the cue, so get ignored.
+
+3
+00:01:01.000 --> 00:02:00.500 align:start position:20%
+I <00:02:05.000>said <00:02:10.000>Bear <00:02:15.000>is <00:02:20.000>coming <00:02:25.000>now!!!!
+All of these timestamps are after the end of the cue, so get ignored.
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timestamp.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timestamp.vtt
new file mode 100644
index 0000000000..17d464bfed
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timestamp.vtt
@@ -0,0 +1,14 @@
+WEBVTT
+Paint-on text in cues with <timestamp> markup.
+
+1
+00:00:00.000 --> 00:00:30.500 align:start position:20%
+This <00:00:05.000>cue <00:00:10.000>is <00:00:15.000>painted <00:00:20.000>on.
+
+2
+00:00:31.000 --> 00:01:00.500 align:start position:20%
+I <00:00:35.000>said <00:00:40.000>Bear <00:00:45.000>is <00:00:50.000>coming!!!!
+
+3
+00:01:01.000 --> 00:02:00.500 align:start position:20%
+I <00:01:05.000>said <00:01:10.000>Bear <00:01:15.000>is <00:01:20.000>coming <00:01:25.000>now!!!!
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-hour-error.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-hour-error.vtt
new file mode 100644
index 0000000000..c33f8a96c3
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-hour-error.vtt
@@ -0,0 +1,22 @@
+WEBVTT
+These timings all have errors and all cues should be ignored.
+
+1
+00:00.00.000 --> 00:00:30.500
+Bear is Coming!!!!!
+
+2
+00:00:31.000 --> 00:01:00:500
+I said Bear is coming!!!!
+
+3
+00:01:01.000 --> 00:120:00.500
+I said Bear is coming now!!!!
+
+4
+00:02:01.000 - 00:03:00.500
+I said Bear is coming now!!!!
+
+5
+00h:03m:01s.000ms --> 00h:03m:00s.500ms
+I said Bear is coming now!!!!
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-hour.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-hour.vtt
new file mode 100644
index 0000000000..b708b83338
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-hour.vtt
@@ -0,0 +1,14 @@
+WEBVTT
+Timings can optionally contain an hour.
+
+1
+00:00:00.000 --> 00:00:30.500
+Bear is Coming!!!!!
+
+2
+00:00:31.000 --> 00:01:00.500
+I said Bear is coming!!!!
+
+3
+00:01:01.000 --> 100:20:00.500
+I said Bear is coming now!!!! \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-no-hour-errors.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-no-hour-errors.vtt
new file mode 100644
index 0000000000..e4bf27d4e6
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-no-hour-errors.vtt
@@ -0,0 +1,22 @@
+WEBVTT
+These timings all have errors and all cues should be ignored.
+
+1
+00.00.000 --> 00:30.500
+Bear is Coming!!!!!
+
+2
+00:31.000 --> 01:00:500
+I said Bear is coming!!!!
+
+3
+01:01.000 --> 120:00.500
+I said Bear is coming now!!!!
+
+4
+01:01.000 - 02:00.500
+I said Bear is coming now!!!!
+
+5
+02:01.000 --> 03m:00.500
+I said Bear is coming now!!!!
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-no-hour.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-no-hour.vtt
new file mode 100644
index 0000000000..745c34ff9f
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-no-hour.vtt
@@ -0,0 +1,18 @@
+WEBVTT
+The hour of a timestamp is optional.
+
+1
+00:00.000 --> 00:30.500
+Bear is Coming!!!!!
+
+2
+00:31.000 --> 01:00.500
+I said Bear is coming!!!!
+
+3
+01:01.000 --> 02:00.500
+I said Bear is coming now!!!!
+
+4
+02:01.000 --> 03:00.500
+tab separators \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-whitespace.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-whitespace.vtt
new file mode 100644
index 0000000000..9d9ac9a38a
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-whitespace.vtt
@@ -0,0 +1,51 @@
+WEBVTT
+Whitespace (U+0020, U+0009, U+000C) surrounding cue-timings separator ("-->") is optional
+
+1
+00:00:00.100 -->00:00:01.500
+Single U+0020 SPACE left of cue-timings separator
+
+2
+00:00:00.100--> 00:00:01.500
+Single U+0020 SPACE right of cue-timings separator
+
+3
+00:00:00.100 -->00:00:01.500
+Single U+0009 TAB left of cue-timings separator
+
+4
+00:00:00.100--> 00:00:01.500
+Single U+0009 TAB right of cue-timings separator
+
+5
+00:00:00.100 -->00:00:01.500
+Single U+000C FORM FEED left of cue-timings separator
+
+6
+00:00:00.100--> 00:00:01.500
+Single U+000C FORM FEED right of cue-timings separator
+
+7
+00:00:00.100 -->00:00:01.500
+Several U+0020 SPACE left of cue-timings separator
+
+8
+00:00:00.100--> 00:00:01.500
+Several U+0020 SPACE right of cue-timings separator
+
+9
+00:00:00.100 -->00:00:01.500
+Several U+0009 TAB left of cue-timings separator
+
+10
+00:00:00.100--> 00:00:01.500
+Several U+0009 TAB right of cue-timings separator
+
+11
+00:00:00.100 -->00:00:01.500
+Several U+000C FORM FEED left of cue-timings separator
+
+12
+00:00:00.100--> 00:00:01.500
+Several U+000C FORM FEED right of cue-timings separator
+
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/track.de.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/track.de.vtt
new file mode 100644
index 0000000000..9eaf3d31e4
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/track.de.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:01.000
+German
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/track.en.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/track.en.vtt
new file mode 100644
index 0000000000..4241f35b56
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/track.en.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:01.000
+English
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/track.fr.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/track.fr.vtt
new file mode 100644
index 0000000000..5523224e0d
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/track.fr.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:01.000
+french
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/track.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/track.vtt
new file mode 100644
index 0000000000..c916c0983b
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/track.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:01.000
+test
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/unsupported-markup.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/unsupported-markup.vtt
new file mode 100644
index 0000000000..b4ea7ea09b
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/unsupported-markup.vtt
@@ -0,0 +1,23 @@
+WEBVTT
+Any HTML markup that is not supported should be ignored.
+
+1
+00:00:00.000 --> 00:00:30.500 align:start position:20%
+<h1>Bear is Coming!!!!!</h1>
+<p>And what kind of a bear it is - just have <a href="webpage.html">look</a>.</p>
+
+2
+00:00:31.000 --> 00:01:00.500 align:start position:20%
+<ul>
+ <li>I said Bear is coming!!!!</li>
+ <li>I said Bear is still coming!!!!</li>
+</ul>
+
+
+3
+00:01:01.000 --> 00:02:00.500 align:start position:20%
+<ol>
+ <li>I said Bear is coming now!!!!</li>
+ <li><img src="bear.png" alt="mighty bear"></li>
+ <li><video src="bear_ad.webm" controls></video></li>
+</ol> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/utf8.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/utf8.vtt
new file mode 100644
index 0000000000..8dd8f27948
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/utf8.vtt
@@ -0,0 +1,10 @@
+WEBVTT
+UTF-8 encoded characters should be recognized.
+
+1
+00:00:00.000 --> 00:00:30.500
+景気判断
+
+2
+00:00:31.000 --> 00:20:00.500
+電力不足 \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/valign-bad.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/valign-bad.vtt
new file mode 100644
index 0000000000..8e7b3b738d
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/valign-bad.vtt
@@ -0,0 +1,17 @@
+WEBVTT
+Invalid vertical direction settings (all settings are ignored).
+
+1
+00:00:00.000 --> 00:00:30.500 vertical:#vertical
+Bear is Coming!!!!!
+Normal rendering - direction setting is ignored.
+
+2
+00:00:31.000 --> 00:01:00.500 vertical:verticallr
+I said Bear is coming!!!!
+Normal rendering - direction setting is ignored.
+
+3
+00:01:01.000 --> 00:02:00.500 vertical:vertical-rl
+I said Bear is coming now!!!!
+Normal rendering - direction setting is ignored.
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/valign-ltr.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/valign-ltr.vtt
new file mode 100644
index 0000000000..74838369d2
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/valign-ltr.vtt
@@ -0,0 +1,20 @@
+WEBVTT
+Valid vertical direction settings.
+
+1
+00:00:00.000 --> 00:00:30.500 vertical:rl
+الدب قادم!!!!!
+يجعل على الجانب الأيمن من المعاينة الفيديو والمتوسطة الانحياز ،
+أسفل إلى أعلى، وتزايد اليسار.
+
+2
+00:00:31.000 --> 00:01:00.500 vertical:lr
+قلت الدب قادم!!
+يجعل على الجانب الأيسر من المعاينة الفيديو والمتوسطة الانحياز ،
+أسفل إلى أعلى، وتنامي اليمين.
+
+3
+00:01:01.000 --> 00:02:00.500 vertical:rl align:start position:0%
+قلت الدب قادم الآن!!
+يجعل على الجانب الأيمن من المعاينة الفيديو ، على حد سواء أسفل محاذاة
+لمربع جديلة والنص داخل النص ، من أسفل إلى أعلى، وتزايد اليسار.
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/valign.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/valign.vtt
new file mode 100644
index 0000000000..f757a365e3
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/valign.vtt
@@ -0,0 +1,20 @@
+WEBVTT
+Valid vertical direction settings.
+
+1
+00:00:00.000 --> 00:00:30.500 vertical:rl
+Bear is Coming!!!!!
+Renders on the right side of the video viewport, middle aligned,
+top to bottom, growing left.
+
+2
+00:00:31.000 --> 00:01:00.500 vertical:lr
+I said Bear is coming!!!!
+Renders on the left side of the video viewport, middle aligned,
+top to bottom, growing right.
+
+3
+00:01:01.000 --> 00:02:00.500 vertical:rl align:start position:0%
+I said Bear is coming now!!!!
+Renders on the right side of the video viewport, top aligned both
+for the cue box and the text within, text from top to bottom, growing left.
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/voice-bad.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/voice-bad.vtt
new file mode 100644
index 0000000000..12ffdeb82e
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/voice-bad.vtt
@@ -0,0 +1,17 @@
+WEBVTT
+Invalid <v> voice markup.
+
+1
+00:00:00.000 --> 00:00:30.500 align:start position:20%
+< v Speaker>Bear is Coming!!!!!</v>
+This is two annotations for an empty tag.
+
+2
+00:00:31.000 --> 00:01:00.500 align:start position:20%
+<v&Doe Hunter>I said Bear is coming!!!!</v>
+This does not parse as a voice tag.
+
+3
+00:01:01.000 --> 00:02:00.500 align:start position:20%
+I said <v-Speaker>Bear is coming now</v>!!!!
+This does not parse as a voice tag.
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/voice.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/voice.vtt
new file mode 100644
index 0000000000..d6cfc6887f
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/voice.vtt
@@ -0,0 +1,15 @@
+WEBVTT
+Cue text fragment with <v> voice markup mapped to HTML <q> element with @title for annotation.
+
+1
+00:00:00.000 --> 00:00:30.500 align:start position:20%
+<v.blue Speaker>Bear is Coming!!!!!</v>
+Text span with a class and an annotation.
+
+2
+00:00:31.000 --> 00:01:00.500 align:start position:20%
+<v Doe Hunter>I said Bear is coming!!!!</v>
+
+3
+00:01:01.000 --> 00:02:00.500 align:start position:20%
+I said <v.blue Speaker>Bear is coming now</v>!!!!
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/vp8-vorbis-webvtt.webm b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/vp8-vorbis-webvtt.webm
new file mode 100644
index 0000000000..c626f86e33
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/vp8-vorbis-webvtt.webm
Binary files differ
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/webvtt-file.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/webvtt-file.vtt
new file mode 100644
index 0000000000..0c1a5fb158
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/webvtt-file.vtt
@@ -0,0 +1,9 @@
+WEBVTT FILE
+
+1
+00:00:00.000 --> 00:00:30.500
+Bear is Coming!!!!!
+
+2
+00:00:31.000 --> 00:20:00.500
+I said Bear is coming!!!! \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/webvtt-rubbish.vtt b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/webvtt-rubbish.vtt
new file mode 100644
index 0000000000..dacc215409
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/resources/webvtt-rubbish.vtt
@@ -0,0 +1,10 @@
+WEBVTT asdfasdfauhio
+Rubbish after the WEBVTT header should be ignored.
+
+1
+00:00:00.000 --> 00:00:30.500
+Bear is Coming!!!!!
+
+2
+00:00:31.000 --> 00:20:00.500
+I said Bear is coming!!!! \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/src-clear-cues.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/src-clear-cues.html
new file mode 100644
index 0000000000..3ba8c9db88
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/src-clear-cues.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<title>track element changing "track URL" and clearing cues</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+(async_test(document.title+', set mode, add cue, set src')).step(function(){
+ var track = document.createElement('track');
+ var c = new VTTCue(0, 1, 'foo');
+ c.id = 'id';
+ track.track.addCue(c);
+ assert_equals(track.track.cues, null, 'cues before setting src or mode');
+ track.track.mode = 'showing';
+ assert_equals(track.track.cues.length, 1, 'cues after setting mode');
+ var cues = track.track.cues;
+ track.src = 'data:,a';
+ assert_equals(track.track.cues.length, 0, 'cues.length after setting src');
+ assert_equals(track.track.cues, cues, 'track.track.cues sameness after setting src');
+ assert_equals(c.id, 'id', 'liveness of removed cue');
+ this.done();
+});
+
+(async_test(document.title+', set mode, set src, add cue, change src')).step(function(){
+ var track = document.createElement('track');
+ track.track.mode = 'showing';
+ track.src = 'data:,a';
+ var c = new VTTCue(0, 1, 'foo');
+ c.id = 'id';
+ track.track.addCue(c);
+ assert_equals(track.track.cues.length, 1, 'cues.length before changing src');
+ var cues = track.track.cues;
+ track.src = 'data:,b';
+ assert_equals(track.track.cues.length, 0, 'cues.length after changing src');
+ assert_equals(track.track.cues, cues, 'track.track.cues sameness after changing src');
+ assert_equals(c.id, 'id', 'liveness of removed cue');
+ this.done();
+});
+
+(async_test(document.title+', set mode, add cue, change mode to disabled, set src')).step(function(){
+ var track = document.createElement('track');
+ track.track.mode = 'showing';
+ var c = new VTTCue(0, 1, 'foo');
+ c.id = 'id';
+ track.track.addCue(c);
+ var cues = track.track.cues;
+ track.track.mode = 'disabled';
+ track.src = 'data:,a';
+ assert_equals(cues.length, 0, 'cues.length after changing src');
+ assert_equals(c.id, 'id', 'liveness of removed cue');
+ this.done();
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/src-empty-string.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/src-empty-string.html
new file mode 100644
index 0000000000..27c76b6be4
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/src-empty-string.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<title>Setting HTMLTrackElement.src to the empty string fires 'error' and sets readyState to ERROR</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/media.html#sourcing-out-of-band-text-tracks">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video></video>
+<script>
+async_test(t => {
+ let track = document.createElement("track");
+ track.src = '';
+ track.default = true;
+ track.onerror = t.step_func_done(() => {
+ assert_equals(track.readyState, HTMLTrackElement.ERROR);
+ });
+ track.onload = t.unreached_func('fired load');
+
+ assert_equals(track.readyState, HTMLTrackElement.NONE);
+
+ document.querySelector('video').appendChild(track);
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-active-cues.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-active-cues.html
new file mode 100644
index 0000000000..a7c08a2e3e
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-active-cues.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<title>Ensure that no text track cues are active after the video is unloaded</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+async_test(function(t) {
+ var eventCount = 0;
+
+ function eventCallback() {
+ eventCount++;
+ if (eventCount == 3) {
+ assert_equals(trackElement.track.activeCues.length, 1);
+ video.src = '';
+ }
+ }
+
+ var video = document.createElement('video');
+ video.src = getVideoURI('/media/movie_5');
+ // uanset media element's `show-poster` flag in order to run `time marches on`
+ // when we add new cues into media element's cues list.
+ video.play();
+ var trackElement = document.createElement('track');
+
+ trackElement.onload = t.step_func(eventCallback);
+ trackElement.oncuechange = t.step_func(eventCallback);
+ video.oncanplaythrough = t.step_func(eventCallback);
+
+ video.onerror = t.step_func_done(function(event) {
+ assert_equals(event.target, video);
+ assert_not_equals(video.error, null);
+ assert_equals(video.error.code, MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED);
+ assert_equals(video.networkState, HTMLMediaElement.NETWORK_NO_SOURCE);
+ assert_equals(trackElement.track.activeCues.length, 0);
+ });
+
+ trackElement.src = 'resources/captions-fast.vtt';
+ trackElement.kind = 'captions';
+ trackElement.default = true;
+ video.appendChild(trackElement);
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-add-remove-cue.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-add-remove-cue.html
new file mode 100644
index 0000000000..e738964001
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-add-remove-cue.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<title>TextTrack's addCue and removeCue</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+async_test(function(t) {
+ var video = document.createElement("video");
+ var trackElement = document.createElement("track");
+
+ trackElement.onload = t.step_func_done(function() {
+ var cues = trackElement.track.cues;
+ // Test cues loaded from the file.
+ assert_equals(cues.length, 4);
+ assert_equals(cues.getCueById("1").startTime, 0);
+ assert_equals(cues[1].startTime, 31);
+ assert_equals(cues[2].startTime, 61);
+ assert_equals(cues.getCueById("4").startTime, 121);
+ assert_equals(cues.getCueById("junk"), null);
+
+ // Create a new cue, check values.
+ var textCue = new VTTCue(33, 3.4, "Sausage?");
+ assert_equals(textCue.track, null);
+ assert_equals(textCue.id, "");
+ assert_equals(textCue.startTime, 33);
+ assert_equals(textCue.endTime, 3.4);
+ assert_equals(textCue.pauseOnExit, false);
+ assert_equals(textCue.vertical, "");
+ assert_equals(textCue.snapToLines, true);
+ assert_equals(textCue.line, "auto");
+ assert_equals(textCue.position, "auto");
+ assert_equals(textCue.size, 100);
+ assert_equals(textCue.align, "center");
+
+ // Remove the unadded track, make sure it throws correctly.
+ assert_throws_dom("NotFoundError", function() { trackElement.track.removeCue(textCue); });
+
+ // Add the new cue to a track, make sure it is inserted correctly.
+ trackElement.track.addCue(textCue);
+ assert_equals(textCue.track, trackElement.track);
+ assert_equals(cues[1].startTime, 31);
+ assert_equals(cues[2].startTime, 33);
+ assert_equals(cues[3].startTime, 61);
+
+ // create a new cue and add it to a track created with
+ // video.addTextTrack, make sure it is inserted correctly.
+ var newTrack = video.addTextTrack("subtitles", "French subtitles", "fr");
+ newTrack.mode = "showing";
+ var newCue = new VTTCue(0, 1, "Test!");
+ newTrack.addCue(newCue);
+ assert_equals(newCue, newTrack.cues[0])
+ assert_equals(newCue.track, newTrack);
+ assert_equals(newCue.id, "");
+ assert_equals(newCue.startTime, 0);
+ assert_equals(newCue.endTime, 1);
+ assert_equals(newCue.pauseOnExit, false);
+ assert_equals(newCue.vertical, "");
+ assert_equals(newCue.snapToLines, true);
+ assert_equals(newCue.line, "auto");
+ assert_equals(newCue.position, "auto");
+ assert_equals(newCue.size, 100);
+ assert_equals(newCue.align, "center");
+
+ trackElement.track.removeCue(textCue);
+ assert_equals(textCue.track, null);
+ assert_equals(cues[1].startTime, 31);
+ assert_equals(cues[2].startTime, 61);
+
+ // Remove a cue added from the WebVTT file.
+ textCue = cues[2];
+ trackElement.track.removeCue(textCue);
+ assert_equals(textCue.track, null);
+ assert_equals(cues[1].startTime, 31);
+ assert_equals(cues[2].startTime, 121);
+
+ // Try to remove the cue again.
+ assert_throws_dom("NotFoundError", function() { trackElement.track.removeCue(textCue); });
+
+ // Add a cue before all the existing cues.
+ trackElement.track.addCue(new VTTCue(0, 31, "I am first"));
+ assert_equals(cues[0].startTime, 0);
+ assert_equals(cues[0].endTime, 31);
+ assert_equals(cues[1].startTime, 0);
+ assert_equals(cues[1].endTime, 30.5);
+ assert_equals(cues[2].startTime, 31);
+ });
+
+ trackElement.src = "resources/settings.vtt";
+ trackElement.kind = "captions";
+ trackElement.default = true;
+ video.appendChild(trackElement);
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-add-track.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-add-track.html
new file mode 100644
index 0000000000..c924c92da9
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-add-track.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<title>'addtrack' event is fired when a TextTrack is created</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+async_test(function(t) {
+ var video = document.createElement('video');
+
+ var trackElement = document.createElement('track');
+ video.appendChild(trackElement);
+ var tracks = [];
+ tracks.push(trackElement.track);
+
+ // Register the 'addtrack' listener after creating the element
+ // to make sure the event is dispatched asynchronously.
+ video.textTracks.onaddtrack = t.step_func(function(event) {
+ assert_equals(event.target, video.textTracks);
+ assert_true(event instanceof TrackEvent, 'instanceof');
+ assert_equals(event.track, tracks[video.textTracks.length - 1]);
+
+ if (video.textTracks.length == 1) {
+ tracks.push(video.addTextTrack('captions', 'Caption Track', 'en'));
+ assert_equals(video.textTracks.length, 2);
+ } else {
+ t.done();
+ }
+ });
+
+ trackElement.src = 'resources/webvtt-file.vtt';
+ trackElement.track.mode = 'hidden';
+ assert_equals(video.textTracks.length, 1);
+ assert_equals(trackElement.readyState, HTMLTrackElement.NONE);
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-addtrack-kind.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-addtrack-kind.html
new file mode 100644
index 0000000000..d058bf2987
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-addtrack-kind.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>addTextTrack() only accepts known "kind" values</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+ var trackCount = 0;
+
+ function addTrack(type) {
+ video.addTextTrack(type);
+ assert_equals(video.textTracks.length, ++trackCount);
+ }
+
+ var video = document.createElement("video");
+ assert_equals(video.textTracks.length, 0);
+ assert_throws_js(TypeError, function() { video.addTextTrack("kaptions"); });
+ assert_equals(video.textTracks.length, 0);
+
+ addTrack("subtitles");
+ addTrack("captions");
+ addTrack("descriptions");
+ addTrack("chapters");
+ addTrack("metadata");
+});
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-api-texttracks.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-api-texttracks.html
new file mode 100644
index 0000000000..b2840d235a
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-api-texttracks.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Track element - text tracks API test</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#text-track-api">
+<link rel="author" title="Hyunjin Cho">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<h1>Track element and API Test</h1>
+<div style="display:none;">
+ <video id="tracktest" src="/media/movie_300.mp4">
+ <track kind="subtitles" src="resources/track.en.vtt" srclang="en" label="English">
+ <track kind="captions" src="resources/track.en.vtt" srclang="en" label="English with Captions">
+ <track id="french" kind="subtitles" src="resources/track.fr.vtt" srclang="fr" label="Francais">
+ <track kind="subtitles" src="resources/track.de.vtt" srclang="de" label="Deutsch">
+ </video>
+</div>
+<div id="log"></div>
+<script>
+test(function() {
+ var t1 = document.getElementById('tracktest').textTracks;
+ assert_not_equals(t1, undefined, "textTracks member should not be undefined");
+}, "Check the track elements");
+test(function() {
+ var t2 = document.getElementById('tracktest').textTracks.getTrackById("french");
+ assert_not_equals(t2, undefined, "textTracks member should not be undefined");
+}, "Check getTrackById method");
+test(function() {
+ var t3 = document.getElementById('tracktest').textTracks.length;
+ assert_equals(t3, 4, "textTracks List should be 4");
+}, "Count track list");
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-change-event.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-change-event.html
new file mode 100644
index 0000000000..7a17dee2a7
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-change-event.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<title>A 'change' event is fired when a TextTrack's mode changes</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+async_test(function(t) {
+ var video = document.createElement('video');
+ var track = video.addTextTrack('subtitles', 'test', 'en');
+
+ // addTextTrack() defaults to "hidden", so settings
+ // mode to "showing" should trigger a "change" event.
+ track.mode = 'showing';
+ assert_equals(video.textTracks.length, 1);
+
+ video.textTracks.onchange = t.step_func_done(function(event) {
+ assert_equals(event.target, video.textTracks);
+ assert_true(event instanceof Event, 'instanceof');
+ assert_false(event.hasOwnProperty('track'), 'unexpected property found: "track"');
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-css-cue-pseudo-class.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-css-cue-pseudo-class.html
new file mode 100644
index 0000000000..d18f8b55cd
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-css-cue-pseudo-class.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+:cue { color: red; }
+:cue(i) { color: red; }
+</style>
+<script>
+test(function() {
+ assert_equals(document.styleSheets[0].cssRules.length, 0);
+}, ":cue pseudo-class is not supported and dropped during parsing");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-empty.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-empty.html
new file mode 100644
index 0000000000..59f8fc6c7b
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-empty.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title>Invoke getCueAsHTML() on an empty cue</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+ var emptyCue = new VTTCue(0, 0, "");
+ var fragment = emptyCue.getCueAsHTML();
+
+ // The getCueAsHTML() method should return a document fragment.
+ assert_true(fragment instanceof DocumentFragment);
+
+ // The document fragment should have one child, an empty Text node.
+ assert_equals(fragment.childNodes.length, 1);
+ assert_equals(fragment.childNodes[0].constructor.name, Text.name);
+ assert_equals(fragment.childNodes[0].length, 0);
+ assert_equals(fragment.childNodes[0].data, "");
+});
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-inline.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-inline.html
new file mode 100644
index 0000000000..3b4c3542a9
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-inline.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>Add a track and change its mode through JS</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <source src="/media/test.mp4" type="video/mp4">
+ <source src="/media/test.ogv" type="video/ogg">
+</video>
+<script>
+test(function() {
+ var video = document.querySelector('video');
+ var track = video.addTextTrack('captions', 'English', 'en');
+ track.addCue(new VTTCue(0.0, 10.0, 'wow wow'));
+ track.mode = 'showing';
+});
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-mutable-fragment.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-mutable-fragment.html
new file mode 100644
index 0000000000..713e781996
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-mutable-fragment.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<title>Cue fragment is mutable</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+p, div { display: none; }
+</style>
+<video>
+ <track src="resources/captions-html.vtt" kind="captions" default>
+ <script>
+ async_test(function(t) {
+ var video = document.querySelector("video");
+ var testTrack = document.querySelector("track");
+
+ video.oncanplaythrough = t.step_func(testMutability);
+ testTrack.onload = t.step_func(testMutability);
+
+ var fragment;
+ var eventCount = 0;
+ function testMutability() {
+ eventCount++;
+ if (eventCount != 2)
+ return;
+
+ var testCue = testTrack.track.cues[0];
+
+ // Test initial cue contents.
+ assert_equals(testCue.text, "Lorem <b>ipsum</b> <u>dolor</u> <i.sit>sit</i> amet,");
+
+ // Cue getCueAsHTML() should return a correct fragment.
+ createExpectedFragment(document.createDocumentFragment());
+ assert_true(fragment.isEqualNode(testCue.getCueAsHTML()));
+
+ // Appending getCuesAsHTML() twice to the DOM should be succesful.
+ document.getElementsByTagName("div")[0].appendChild(testCue.getCueAsHTML());
+ document.getElementsByTagName("div")[1].appendChild(testCue.getCueAsHTML());
+
+ createExpectedFragment(document.createElement("div"));
+ assert_true(fragment.isEqualNode(document.getElementsByTagName("div")[0]));
+ assert_true(fragment.isEqualNode(document.getElementsByTagName("div")[1]));
+
+ // The fragment returned by getCuesAsHTML() should be independently mutable.
+ document.getElementsByTagName("div")[0].firstChild.textContent = "Different text ";
+ assert_false(fragment.isEqualNode(document.getElementsByTagName("div")[0]));
+ assert_true(fragment.isEqualNode(document.getElementsByTagName("div")[1]));
+
+ // Calling twice getCueAsHTML() should not return the same fragment.
+ assert_not_equals(testCue.getCueAsHTML(), testCue.getCueAsHTML());
+
+ t.done();
+ }
+
+ function createExpectedFragment(rootNode) {
+ fragment = rootNode;
+ fragment.appendChild(document.createTextNode("Lorem "));
+
+ var bold = document.createElement("b");
+ bold.appendChild(document.createTextNode("ipsum"));
+ fragment.appendChild(bold);
+
+ fragment.appendChild(document.createTextNode(" "));
+
+ var underline = document.createElement("u");
+ underline.appendChild(document.createTextNode("dolor"));
+ fragment.appendChild(underline);
+
+ fragment.appendChild(document.createTextNode(" "));
+
+ var italics = document.createElement("i");
+ italics.className = "sit";
+ italics.appendChild(document.createTextNode("sit"));
+ fragment.appendChild(italics);
+
+ fragment.appendChild(document.createTextNode(" amet,"));
+ }
+
+ video.src = getVideoURI("/media/counting");
+ });
+ </script>
+</video>
+<p>Fragment 1</p>
+<div></div>
+<p>Fragment 2</p>
+<div></div> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-mutable.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-mutable.html
new file mode 100644
index 0000000000..26a6b84f8a
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-mutable.html
@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<title>Modifying attributes of a VTTCue</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track id="captions" src="resources/captions.vtt" kind="captions" default>
+ <script>
+ async_test(function(t) {
+ var track = document.querySelector("track");
+
+ track.onload = t.step_func_done(function() {
+ var cues = track.track.cues;
+
+ // Test initial values.
+ textCue = cues.getCueById("1");
+
+ assert_equals(textCue.startTime, 0);
+ assert_equals(textCue.endTime, 1.0);
+ assert_equals(textCue.pauseOnExit, false);
+ assert_equals(textCue.vertical, "");
+ assert_equals(textCue.snapToLines, true);
+ assert_equals(textCue.line, "auto");
+ assert_equals(textCue.position, "auto");
+ assert_equals(textCue.size, 100);
+ assert_equals(textCue.align, "center");
+
+ // Modify cue values.
+ textCue.startTime = 1.1;
+ assert_equals(textCue.startTime, 1.1);
+
+ textCue.endTime = 3.9;
+ assert_equals(textCue.endTime, 3.9);
+
+ textCue.pauseOnExit = true;
+ assert_equals(textCue.pauseOnExit, true);
+
+ // http://dev.w3.org/html5/webvtt/#dfn-dom-vttcue-vertical
+ // On setting, the text track cue writing direction must be
+ // set to the value given in the first cell of the row in
+ // the table above whose second cell is a case-sensitive
+ // match for the new value.
+ textCue.vertical = "RL";
+ assert_equals(textCue.vertical, "");
+ textCue.vertical = "rl";
+ assert_equals(textCue.vertical, "rl");
+
+ textCue.snapToLines = false;
+ assert_equals(textCue.snapToLines, false);
+
+ // http://dev.w3.org/html5/webvtt/#dfn-vttcue-line
+ // On setting, the text track cue line position must be set
+ // to the new value; if the new value is the string "auto",
+ // then it must be interpreted as the special value auto.
+ assert_equals(textCue.line, "auto");
+ assert_throws_js(TypeError, function() { textCue.line = "gazonk"; });
+ assert_equals(textCue.line, "auto");
+ textCue.line = 42;
+ assert_equals(textCue.line, 42);
+ textCue.line = -2;
+ assert_equals(textCue.line, -2);
+ textCue.line = 102;
+ assert_equals(textCue.line, 102);
+ textCue.snapToLines = true;
+ textCue.line = -2;
+ assert_equals(textCue.line, -2);
+ textCue.line = 102;
+ assert_equals(textCue.line, 102);
+
+ // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#dom-texttrackcue-line
+ // On setting, if the new value is negative or greater than 100,
+ // then throw an IndexSizeError exception.
+ // Otherwise, set the text track cue text position to the new value.
+ assert_throws_dom("IndexSizeError", function() { textCue.position = -200; });
+ assert_throws_dom("IndexSizeError", function() { textCue.position = 110; });
+ textCue.position = 11;
+ assert_equals(textCue.position, 11);
+
+ // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#dom-texttrackcue-size
+ // On setting, if the new value is negative or greater than 100,
+ // then throw an IndexSizeError exception.
+ // Otherwise, set the text track cue size to the new value.
+ assert_throws_dom("IndexSizeError", function() { textCue.size = -200 });
+ assert_throws_dom("IndexSizeError", function() { textCue.size = 110 });
+ textCue.size = 57;
+ assert_equals(textCue.size, 57);
+
+ // http://dev.w3.org/html5/webvtt/#dfn-dom-vttcue-align
+ // On setting, the text track cue text alignment must be
+ // set to the value given in the first cell of the row
+ // in the table above whose second cell is a case-sensitive
+ // match for the new value.
+ textCue.align = "End";
+ assert_equals(textCue.align, "center");
+ textCue.align = "end";
+ assert_equals(textCue.align, "end");
+ });
+ });
+ </script>
+</video>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-negative-duration.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-negative-duration.html
new file mode 100644
index 0000000000..e2f78900a7
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-negative-duration.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Enter, Exit events for a cue with negative duration</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <script>
+ async_test(function(t) {
+ var video = document.querySelector("video");
+ var track = video.addTextTrack("subtitles");
+
+ // Add a cue with negative duration.
+ var cue = new VTTCue(1, -10, "Sausage?");
+ track.addCue(cue);
+ assert_equals(track.cues.length, 1);
+
+ // Verify that enter and exit events are fired.
+ var enterEvent = false;
+ cue.onenter = t.step_func(function() {
+ enterEvent = true;
+ });
+ cue.onexit = t.step_func_done(function() {
+ assert_true(enterEvent);
+ });
+
+ video.src = getVideoURI("/media/test");
+ video.play();
+ });
+ </script>
+</video> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-negative-timestamp-events.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-negative-timestamp-events.html
new file mode 100644
index 0000000000..ebd7877f78
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-negative-timestamp-events.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<title>Enter, Exit events for cues with negative timestamps</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <script>
+ async_test(function(t) {
+ var video = document.querySelector("video");
+ var track = video.addTextTrack("subtitles");
+
+ // Add cue with negative startTime.
+ var cue = new VTTCue(-10, 1, "Sausage?");
+ track.addCue(cue);
+ assert_equals(track.cues.length, 1);
+ cue.onenter = t.step_func(function() {
+ cue.onexit = t.step_func_done();
+ });
+
+ // Add cue with negative startTime and negative endTime.
+ // This cue should never be active.
+ var missedCue = new VTTCue(-110, -3.4, "Pepperoni?");
+ track.addCue(missedCue);
+ assert_equals(track.cues.length, 2);
+ missedCue.onenter = t.unreached_func();
+ missedCue.onexit = t.unreached_func();
+
+ video.src = getVideoURI("/media/test");
+ video.play();
+ });
+ </script>
+</video> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-negative-timestamp.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-negative-timestamp.html
new file mode 100644
index 0000000000..5dc54ed25b
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-negative-timestamp.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<title>Negative timestamps</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/settings.vtt" default>
+ <script>
+ async_test(function(t) {
+ var testTrack = document.querySelector("track");
+
+ testTrack.onload = t.step_func_done(function() {
+ var cues = testTrack.track.cues;
+ assert_equals(testTrack.track.cues.length, 4);
+ // Add cue with negative startTime.
+ var cue = new VTTCue(-3439332606, 3.4, "Sausage?");
+ testTrack.track.addCue(cue);
+ assert_equals(cues.length, 5);
+
+ // Add cue with negative startTime and negative endTime.
+ cue = new VTTCue(-110, -3.4, "Pepperoni?");
+ testTrack.track.addCue(cue);
+ assert_equals(cues.length, 6);
+
+ // Set startTime and endTime to negative values.
+ var testCue = cues[2];
+ assert_equals(testCue.startTime, 0);
+ testCue.startTime = -5;
+ assert_equals(testCue.startTime, -5);
+ assert_equals(testCue.endTime, 30.5);
+ testCue.endTime = -3439332606;
+ assert_equals(testCue.endTime, -3439332606);
+
+ // Check negative cues ordering.
+ testCue = cues[3];
+ assert_equals(testCue.startTime, 31);
+ testCue.startTime = -200;
+ // Verify that this cue is moved to 2nd position.
+ assert_equals(cues[1].startTime, -200);
+ });
+ });
+ </script>
+</video> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-order.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-order.html
new file mode 100644
index 0000000000..58e11ebe70
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-order.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<title>Text track cue order</title>
+<link rel="help" href="https://html.spec.whatwg.org/#text-track-cue-order">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+function concat_cuetext(cues) {
+ return Array.prototype.reduce.call(cues, function(acc, value) {
+ return acc + value.text;
+ }, "");
+}
+
+setup(function() {
+ window.video = document.createElement('video');
+});
+
+test(function() {
+ let track = video.addTextTrack('subtitles');
+ track.addCue(new VTTCue(8, 9, '1'));
+ track.addCue(new VTTCue(4, 5, '2'));
+ track.addCue(new VTTCue(2, 3, '3'));
+ assert_equals(concat_cuetext(track.cues), '321');
+}, document.title + ', decreasing start times.');
+
+test(function() {
+ let track = video.addTextTrack('subtitles');
+ track.addCue(new VTTCue(2, 9, '1'));
+ track.addCue(new VTTCue(2, 3, '2'));
+ track.addCue(new VTTCue(2, 5, '3'));
+ assert_equals(concat_cuetext(track.cues), '132');
+}, document.title + ', equal start times varying end times.');
+
+test(function() {
+ let track = video.addTextTrack('subtitles');
+ track.addCue(new VTTCue(2, 3, '1'));
+ track.addCue(new VTTCue(2, 3, '2'));
+ track.addCue(new VTTCue(2, 3, '3'));
+ assert_equals(concat_cuetext(track.cues), '123');
+}, document.title + ', equal start and end times.');
+
+test(function() {
+ let track = video.addTextTrack('subtitles');
+ track.addCue(new VTTCue(2, 5, '1'));
+ track.addCue(new VTTCue(2, 5, '2'));
+ track.addCue(new VTTCue(2, 5, '3'));
+ assert_equals(concat_cuetext(track.cues), '123', 'initial order');
+
+ let cue = track.cues[0];
+ track.removeCue(cue);
+ assert_equals(concat_cuetext(track.cues), '23', '"1" removed');
+
+ track.addCue(cue);
+ assert_equals(concat_cuetext(track.cues), '231', '"1" reinserted');
+}, document.title + ', after re-insertion.');
+
+test(function() {
+ let track = video.addTextTrack('subtitles');
+ track.addCue(new VTTCue(2, 5, '1'));
+ track.addCue(new VTTCue(2, 5, '2'));
+ track.addCue(new VTTCue(2, 5, '3'));
+ assert_equals(concat_cuetext(track.cues), '123', 'initial order');
+
+ track.cues[0].startTime = 4;
+ assert_equals(concat_cuetext(track.cues), '231', '"1" moved last');
+
+ track.cues[2].startTime = 2;
+ assert_equals(concat_cuetext(track.cues), '123', '"1" moved first');
+}, document.title + ', equal start and end times with startTime mutations.');
+
+test(function() {
+ let track = video.addTextTrack('subtitles');
+ track.addCue(new VTTCue(2, 5, '1'));
+ track.addCue(new VTTCue(2, 5, '2'));
+ track.addCue(new VTTCue(2, 5, '3'));
+ assert_equals(concat_cuetext(track.cues), '123', 'initial order');
+
+ track.cues[2].endTime = 9;
+ assert_equals(concat_cuetext(track.cues), '312', '"3" moved first');
+
+ track.cues[1].endTime = 3;
+ assert_equals(concat_cuetext(track.cues), '321', '"1" moved last');
+}, document.title + ', equal start and end times with endTime mutations.');
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-after-controls-added-ref.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-after-controls-added-ref.html
new file mode 100644
index 0000000000..bd43c462dd
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-after-controls-added-ref.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<script src="/common/reftest-wait.js"></script>
+<title>Text track cue layout after controls are added (reference)</title>
+<style>
+::cue {
+ font-size: 50px;
+}
+
+/* Video width should be large enough to display all of the media controls. */
+video {
+ border: 1px solid gray;
+ width: 500px;
+}
+</style>
+<video controls onloadeddata="this.onloadeddata = null; takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+</video>
+<script>
+// Add a single cue at line -2, where it would be if there were controls visible
+// at the bottom. (This assumes that those controls are less than 50px high.)
+// cue at line -1.
+var video = document.querySelector("video");
+var track = video.addTextTrack("captions");
+var cue = new VTTCue(0, 1, "text");
+cue.line = -2;
+track.addCue(cue);
+track.mode = "showing";
+</script>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-after-controls-added.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-after-controls-added.html
new file mode 100644
index 0000000000..23c27e418e
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-after-controls-added.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<script src="/common/reftest-wait.js"></script>
+<link rel="match" href="track-cue-rendering-after-controls-added-ref.html">
+<title>Text track cue layout after controls are added</title>
+<style>
+::cue {
+ font-size: 50px;
+}
+</style>
+<!-- Width should be large enough to display all of the media controls. -->
+<video style="border:1px solid gray; width: 500px;">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+</video>
+<script>
+// Add a cue that will overlap with the video controls.
+var video = document.querySelector("video");
+var track = video.addTextTrack("captions");
+track.addCue(new VTTCue(0, 1, "text"));
+track.mode = "showing";
+
+video.onloadeddata = function() {
+ // Double nesting of requestAnimationFrame to
+ // make sure cue layout and paint happens.
+ window.requestAnimationFrame(function() {
+ window.requestAnimationFrame(function() {
+ video.controls = true;
+ // Wait for the relayout before screenshot.
+ window.requestAnimationFrame(function() {
+ takeScreenshot();
+ });
+ });
+ });
+};
+</script>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-after-controls-removed-ref.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-after-controls-removed-ref.html
new file mode 100644
index 0000000000..96afaef346
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-after-controls-removed-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<script src="/common/reftest-wait.js"></script>
+<title>Text track cue layout after controls are removed (reference)</title>
+<style>
+::cue {
+ font-size: 50px;
+}
+
+video {
+ border: 1px solid gray;
+}
+</style>
+<video onloadeddata="this.onloadeddata = null; takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+</video>
+<script>
+// Add a single cue at line -2, where it would be if there were controls visible
+// at the bottom. (This assumes that those controls are less than 50px high.)
+// cue at line -1.
+var video = document.querySelector("video");
+var track = video.addTextTrack("captions");
+var cue = new VTTCue(0, 1, "text");
+cue.line = -2;
+track.addCue(cue);
+track.mode = "showing";
+</script>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-after-controls-removed.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-after-controls-removed.html
new file mode 100644
index 0000000000..76019c9b41
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-after-controls-removed.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<script src="/common/reftest-wait.js"></script>
+<link rel="match" href="track-cue-rendering-after-controls-removed-ref.html">
+<title>Text track cue layout after controls are removed</title>
+<style>
+::cue {
+ font-size: 50px;
+}
+</style>
+<video controls style="border:1px solid gray">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+</video>
+<script>
+// Add a cue that will overlap with the video controls.
+var video = document.querySelector("video");
+var track = video.addTextTrack("captions");
+track.addCue(new VTTCue(0, 1, "text"));
+track.mode = "showing";
+
+video.onloadeddata = function() {
+ // Double nesting of requestAnimationFrame to
+ // make sure cue layout and paint happens.
+ window.requestAnimationFrame(function() {
+ window.requestAnimationFrame(function() {
+ // Remove the controls. The cue should not move.
+ video.controls = false;
+ takeScreenshot();
+ });
+ });
+};
+</script>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-empty-cue.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-empty-cue.html
new file mode 100644
index 0000000000..427189f6fc
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-empty-cue.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>Empty cues</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+async_test(function(t) {
+ var video = document.createElement("video");
+ video.src = getVideoURI("/media/test");
+ video.addTextTrack("captions", "regular captions track", "en");
+ video.textTracks[0].addCue(new VTTCue(0, 4, ""));
+
+ video.onplaying = t.step_func_done();
+ video.play();
+});
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-line-doesnt-fit-ref.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-line-doesnt-fit-ref.html
new file mode 100644
index 0000000000..8354041eb2
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-line-doesnt-fit-ref.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<script src="/common/reftest-wait.js"></script>
+<style>
+.container {
+ position: relative;
+ display: inline-block;
+ width: 320px;
+ height: 240px;
+}
+.cue {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ overflow: hidden;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: green;
+ color: green;
+ font-size: 120px;
+ padding: 2px;
+}
+</style>
+<div class="container">
+ <video autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ </video>
+ <div class="cue"><span>PAS</span></div>
+</div>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-line-doesnt-fit.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-line-doesnt-fit.html
new file mode 100644
index 0000000000..d3dcee1037
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-line-doesnt-fit.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<script src="/common/reftest-wait.js"></script>
+<link rel="match" href="track-cue-rendering-line-doesnt-fit-ref.html">
+<script>
+function addCue(track, cueData) {
+ var cue = new VTTCue(0, 10, 'XXX');
+ for (var prop in cueData)
+ cue[prop] = cueData[prop];
+ track.addCue(cue);
+}
+</script>
+<style>
+video::cue {
+ font-size: 120px;
+ color: green;
+ background-color: green;
+}
+</style>
+<video autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <script>
+ var video = document.querySelector("video");
+ var track = video.addTextTrack('subtitles');
+ addCue(track, { line: 0, align: 'start', text: 'PAS' });
+ // This cue will not fit, and will not be displayed.
+ addCue(track, { line: 1, align: 'start', text: 'FAI' });
+ track.mode = 'showing';
+ </script>
+</video>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-transformed-video-ref.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-transformed-video-ref.html
new file mode 100644
index 0000000000..39461350b0
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-transformed-video-ref.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<script src="/common/reftest-wait.js"></script>
+<style>
+.container {
+ transform: translate(1px, 0px);
+ position: relative;
+ display: inline-block;
+ width: 320px;
+ height: 240px;
+}
+.cue {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ overflow: hidden;
+ text-align: start;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: green;
+ color: green;
+ font-size: 50px;
+ padding: 2px;
+}
+</style>
+<div class="container">
+ <video autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ </video>
+ <div class="cue"><span>XXX</span></div>
+</div>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-transformed-video.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-transformed-video.html
new file mode 100644
index 0000000000..69ca92e845
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-transformed-video.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<script src="/common/reftest-wait.js"></script>
+<link rel="match" href="track-cue-rendering-transformed-video-ref.html">
+<style>
+video {
+ transform: translate(1px, 0px);
+}
+video::cue {
+ font-size: 50px;
+ color: green;
+ background-color: green;
+}
+</style>
+<video autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <script>
+ var video = document.querySelector('video');
+ var track = video.addTextTrack('subtitles');
+ var cue = new VTTCue(0, 10, 'XXX');
+ cue.align = 'start';
+ cue.line = 0;
+ track.addCue(cue);
+ track.mode = 'showing';
+ </script>
+</video>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-cuechange-dynamically-created-track-element.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-cuechange-dynamically-created-track-element.html
new file mode 100644
index 0000000000..f990bc8c72
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-cuechange-dynamically-created-track-element.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>'cuechange' event on dynamically created track element</title>
+<meta name="timeout" content="long">
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+<script>
+/**
+ * 'cuechange' event should be correctly dispatched on the dynamically created
+ * track element.
+ */
+promise_test(function(t) {
+ const video = document.querySelector("video");
+ const track = document.createElement("track");
+ track.src = "resources/cues-chrono-order.vtt";
+ track.track.mode = "hidden";
+ video.appendChild(track);
+
+ const cueChangedPromise = new Promise(r => track.oncuechange = r);
+ video.src = getVideoURI("/media/test");
+ // 'TimeMarchesOn' algorithm will be run after calling 'play()', from which
+ // the 'cuechange' event would be dispatched.
+ video.play();
+ return cueChangedPromise;
+});
+</script>
+</video>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-cuechange.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-cuechange.html
new file mode 100644
index 0000000000..2593401771
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-cuechange.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<title>TextTrack's cues are indexed and updated in order during video playback</title>
+<meta name="timeout" content="long">
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/cues-chrono-order.vtt" kind="captions" default>
+ <script>
+ // Use the cuechange event on TextTrack.
+ async_test(function(t) {
+ var video = document.querySelector("video");
+ var testTrack = document.querySelector("track");
+
+ video.src = getVideoURI("/media/test");
+ video.oncanplaythrough = t.step_func(attemptTests);
+
+ function attemptTests() {
+ assert_equals(testTrack.track.cues.length, 3);
+ testTrack.oncuechange = t.step_func(cueChangedFromTrackElement);
+ video.play();
+ }
+
+ var currentCueIndex;
+ var cueChangeCount = 0;
+ function cueChangedFromTrackElement() {
+ currentCueIndex = Math.floor(cueChangeCount / 2);
+ currentCue = event.target.track.cues[currentCueIndex];
+ if (cueChangeCount % 2 == 0) {
+ // Cue entered.
+ assert_equals(currentCue, testTrack.track.activeCues[0]);
+ assert_equals(currentCue.id, (currentCueIndex + 1).toString());
+ }
+
+ ++cueChangeCount;
+ if (cueChangeCount == testTrack.track.cues.length * 2)
+ t.done();
+ }
+ });
+ </script>
+</video> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-enter-exit.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-enter-exit.html
new file mode 100644
index 0000000000..2d49c21178
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-enter-exit.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<title>TextTrack's cues are indexed and updated in order during video playback</title>
+<meta name="timeout" content="long">
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/cues-chrono-order.vtt" kind="captions" default>
+ <script>
+ // Use the enter and exit events on TextTrackCue.
+ async_test(function(t) {
+ var video = document.querySelector("video");
+ var testTrack = document.querySelector("track");
+
+ video.src = getVideoURI("/media/test");
+
+ video.oncanplaythrough = t.step_func(attemptTests);
+
+ function attemptTests() {
+ assert_equals(testTrack.track.cues.length, 3);
+ for (var i = 0; i < testTrack.track.cues.length; i++) {
+ testTrack.track.cues[i].onenter = t.step_func(cueEntered);
+ testTrack.track.cues[i].onexit = t.step_func(cueExited);
+ }
+ video.play();
+ }
+
+ var cueCount = 0;
+ function cueEntered(event) {
+ var currentCue = event.target;
+
+ // This cue is the currently active cue.
+ assert_equals(currentCue, testTrack.track.activeCues[0]);
+ assert_equals(currentCue.id, (cueCount + 1).toString());
+ }
+
+ function cueExited() {
+ ++cueCount;
+ if (cueCount == testTrack.track.cues.length)
+ t.done();
+ }
+ });
+ </script>
+</video> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-enter-seeking.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-enter-seeking.html
new file mode 100644
index 0000000000..ae56e16205
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-enter-seeking.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<title>TextTrack's cue onenter handler called when seeked onto</title>
+<meta name="timeout" content="long">
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/cues-chrono-order.vtt" kind="captions" default>
+ <script>
+ // Check that the onenter event is called for the right cue when seeking on the video element.
+ // Based on the spec step 4 [1], after a seek happens, the missed cues should be empty,
+ // so any cues before the target time should not receive enter event.
+ // [1] https://html.spec.whatwg.org/multipage/media.html#time-marches-on
+ async_test(function(t) {
+ var video = document.querySelector("video");
+ var testTrack = document.querySelector("track");
+
+ video.src = getVideoURI("/media/test");
+
+ video.oncanplaythrough = t.step_func(attemptTests);
+
+ function attemptTests() {
+ assert_equals(testTrack.track.cues.length, 3);
+ const targetTime = 4.0000000004;
+
+ for (let cue of testTrack.track.cues) {
+ if (cue.endTime > targetTime) {
+ cue.onenter = t.step_func(_=>t.done());
+ } else {
+ cue.onenter = t.unreached_func("onenter called for wrong cue");
+ }
+ }
+
+ video.currentTime = targetTime;
+ }
+ });
+ </script>
+</video>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-missed.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-missed.html
new file mode 100644
index 0000000000..2acae212d2
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-missed.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<title>Events are triggered for missed (skipped) cues during normal playback</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/missed-cues.vtt" default>
+ <script>
+ async_test(function(t) {
+ var video = document.querySelector("video");
+ var testTrack = document.querySelector("track");
+
+ video.src = getVideoURI("/media/test");
+
+ video.onended = t.step_func_done();
+
+ video.oncanplaythrough = t.step_func(function() {
+ video.oncanplaythrough = null;
+ video.currentTime = 5.00;
+ runTests();
+ });
+
+ testTrack.onload = t.step_func(runTests);
+
+ var cueCount;
+ var eventCount = 0;
+ function runTests() {
+ eventCount++;
+
+ if(eventCount != 2)
+ return;
+
+ assert_equals(testTrack.track.cues.length, 7);
+
+ for (cueCount = 2; cueCount < testTrack.track.cues.length; cueCount++) {
+ var cue = testTrack.track.cues[cueCount];
+
+ cue.onenter = t.step_func(cueEnteredOrExited);
+ cue.onexit = t.step_func(cueEnteredOrExited);
+ }
+
+ // Test events for missed cues, which are cues with ids
+ // from 3 to 7 in the file resources/missed-cues.vtt.
+ cueCount = 3;
+ video.play();
+ }
+
+ function cueEnteredOrExited(event) {
+ var currentCue = event.target;
+ assert_equals(testTrack.track.cues.getCueById(cueCount).text, currentCue.text);
+ assert_equals(currentCue.id, cueCount.toString());
+
+ if (event.type == "exit")
+ cueCount++;
+ }
+
+ });
+ </script>
+</video>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-pause-on-exit.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-pause-on-exit.html
new file mode 100644
index 0000000000..eaf7e2a1d4
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-pause-on-exit.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<title>Video is paused after cues having pause-on-exit flag are processed</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/simple-captions.vtt" default>
+ <script>
+ async_test(function(t) {
+ var video = document.querySelector("video");
+ var track = document.querySelector("track");
+ track.onload = t.step_func(function() {
+ assert_equals(track.track.cues.length, 4);
+ for (var i = 0; i < track.track.cues.length; ++i) {
+ var cue = track.track.cues[i];
+ if (i % 2 == 0) {
+ cue.pauseOnExit = true;
+ cue.onexit = t.step_func(function(event) {
+ assert_true(video.paused);
+
+ video.play();
+
+ if (event.target.id == 2)
+ t.done();
+ });
+ }
+ }
+ video.src = getVideoURI("/media/test");
+ video.currentTime = 4.00;
+ video.play();
+ assert_false(video.paused);
+ });
+ });
+ </script>
+</video> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-seeking.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-seeking.html
new file mode 100644
index 0000000000..99cd2d550e
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-seeking.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<title>TextTrack's activeCues are indexed and updated during video playback</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/cues-overlapping.vtt" kind="subtitles" default>
+ <script>
+ async_test(function(t) {
+ var video = document.querySelector("video");
+ var track = document.querySelector("track");
+ track.onload = t.step_func(function() {
+ assert_equals(track.track.cues.length, 3);
+ video.src = getVideoURI("/media/test");
+ video.currentTime = 0.5;
+ });
+
+ var seekedCount = 0;
+ video.onseeked = t.step_func(function() {
+ ++seekedCount;
+
+ assert_equals(video.currentTime, seekedCount * 0.5);
+ assert_equals(track.track.activeCues.length, seekedCount - 1);
+ video.currentTime = (seekedCount + 1) * 0.5;
+
+ if (seekedCount == 4)
+ t.done();
+ });
+ });
+ </script>
+</video> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-sorted-before-dispatch.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-sorted-before-dispatch.html
new file mode 100644
index 0000000000..edc202f435
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-sorted-before-dispatch.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<title>All events are triggered in chronological order</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/sorted-dispatch.vtt" default>
+ <script>
+ async_test(function(t) {
+ var video = document.querySelector("video");
+ video.src = getVideoURI("/media/test");
+ var track = document.querySelector("track");
+
+ track.onload = t.step_func(function() {
+ var cues = track.track.cues;
+ assert_equals(cues.length, 8);
+
+ for (var i = 0; i < cues.length; ++i) {
+ cues[i].onenter = t.step_func(cueEnteredOrExited);
+ cues[i].onexit = t.step_func(cueEnteredOrExited);
+ }
+
+ video.play();
+ });
+
+ var cueTimings = [];
+ function cueEnteredOrExited(event) {
+ var currentCue = event.target;
+
+ if (event.type == "exit")
+ cueTimings.push(currentCue.endTime);
+ else
+ cueTimings.push(currentCue.startTime);
+ }
+
+ video.onended = t.step_func_done(function() {
+ assert_equals(cueTimings.length, 14);
+ var time = 0;
+ for (var i = 0; i < cueTimings.length; ++i) {
+ assert_less_than_equal(time, cueTimings[i], "cueTimings[" + i + "]");
+ time = cueTimings[i];
+ }
+ });
+
+ video.currentTime = 5;
+ });
+ </script>
+</video> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-data-url.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-data-url.html
new file mode 100644
index 0000000000..26ff90d56d
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-data-url.html
@@ -0,0 +1,30 @@
+<!doctype html>
+<title>track element data: URL</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+[null, "anonymous", "use-credentials"].forEach(function(crossOriginValue) {
+ async_test(function() {
+ var video = document.createElement('video');
+ if (crossOriginValue !== null) {
+ video.setAttribute('crossorigin', crossOriginValue);
+ }
+ document.body.appendChild(video);
+ var t = document.createElement('track');
+ t.onload = this.step_func_done(function() {
+ assert_equals(t.track.cues.length, 1);
+ assert_equals(t.track.cues[0].startTime, 1);
+ assert_equals(t.track.cues[0].endTime, 2);
+ assert_equals(t.track.cues[0].id, 'x');
+ assert_equals(t.track.cues[0].text, 'test');
+ });
+ t.onerror = this.step_func(function() {
+ assert_unreached('got error event');
+ });
+ t.src = 'data:text/vtt,'+encodeURIComponent('WEBVTT\n\nx\n00:00:01.000 --> 00:00:02.000\ntest\n\n');
+ t.track.mode = 'showing';
+ video.appendChild(t);
+ }, document.title + ' ' + (crossOriginValue ? crossOriginValue : 'No CORS'));
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-default-attribute.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-default-attribute.html
new file mode 100644
index 0000000000..3e8c547fc3
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-default-attribute.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>A track with the "default" attribute loads automatically</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track kind="captions" src="resources/default-styles.vtt">
+ <track kind="captions" src="resources/metadata-area.vtt">
+ <track kind="captions" src="resources/webvtt-file.vtt" id="default" default>
+ <script>
+ async_test(function(t) {
+ var timer = null;
+ var tracks = document.querySelectorAll("track");
+ for (var track of tracks) {
+ track.onload = t.step_func(function() {
+ assert_equals(event.target.readyState, HTMLTrackElement.LOADED);
+ assert_equals(event.target.id, "default");
+ assert_true(event.target.default);
+ // End the test after a brief pause so we allow other tracks to load if they will.
+ if (timer)
+ clearTimeout(timer);
+ timer = t.step_timeout(t.step_func_done(), 200);
+ });
+ }
+ });
+ </script>
+</video>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-delete-during-setup.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-delete-during-setup.html
new file mode 100644
index 0000000000..ce9f73335a
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-delete-during-setup.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Track deletion during setup</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/metadata.vtt">
+</video>
+<script>
+async_test(function(t) {
+ var video = document.querySelector("video");
+ var track = document.querySelector("track");
+ t.step_timeout(function() {
+ video.parentNode.removeChild(video);
+ }, 61);
+
+ track.onload = t.step_func(function() {
+ var track2 = document.createElement("track");
+ video.appendChild(track2);
+ t.step_timeout(t.step_func_done(), 100);
+ });
+
+ assert_equals(track.readyState, HTMLTrackElement.NONE);
+ assert_equals(track.track.mode, "disabled");
+ track.track.mode = "hidden";
+
+ video.src = getVideoURI("/media/test");
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-disabled-addcue.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-disabled-addcue.html
new file mode 100644
index 0000000000..038e6f6ba7
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-disabled-addcue.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<title>Adding cues to a disabled text track</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+async_test(function(t) {
+ var cueDuration = 0.1;
+ var video = document.createElement("video");
+ var track = video.addTextTrack("subtitles");
+ track.mode = "disabled";
+
+ for (var i = 0; i < 10; ++i) {
+ var start = i * cueDuration;
+ var end = start + cueDuration;
+ track.addCue(new VTTCue(start, end, "Test Cue " + i));
+ }
+
+ // Waiting for 2 cue durations to elapse.
+ video.ontimeupdate = t.step_func(function(event) {
+ if (event.target.currentTime < (2 * cueDuration))
+ return;
+
+ // End test after at least 2 cueDurations to make sure the test
+ // would have gone through the period where the first 2 cues would
+ // have been rendered if the track was not disabled.
+ t.done();
+ });
+
+ video.src = getVideoURI("/media/test");
+ video.play();
+});
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-disabled.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-disabled.html
new file mode 100644
index 0000000000..d517b9d12c
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-disabled.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Disabling a track</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track kind="subtitles" src="resources/captions.vtt"/>
+</video>
+<script>
+async_test(function(t) {
+ var video = document.querySelector("video");
+ video.textTracks[0].mode = "disabled";
+
+ // Waiting for the duration of the first cue to elapse.
+ video.ontimeupdate = t.step_func(function (event) {
+ if (event.target.currentTime < 1)
+ return;
+
+ // End test after the duration of the first cue to make sure
+ // the test would have gone through the period where this cue
+ // would have been rendered if the track was not disabled.
+ t.done();
+ });
+
+ video.src = getVideoURI("/media/test");
+ video.play();
+});
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-element-dom-change.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-element-dom-change.html
new file mode 100644
index 0000000000..ff447f33f2
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-element-dom-change.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>Simple DOM mutations with track element</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+ var video = document.createElement("video");
+ var testTrack = document.createElement("track");
+
+ // Append the track element to the video element.
+ video.appendChild(testTrack);
+
+ // Set the mode of the text track to "showing".
+ testTrack.track.mode = "showing";
+});
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-aborted-load.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-aborted-load.html
new file mode 100644
index 0000000000..234e087313
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-aborted-load.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title>HTMLTrackElement 'src' attribute changed, load pending</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/media.html#start-the-track-processing-model">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video></video>
+<script>
+async_test(t => {
+ const track = document.createElement('track');
+ track.onload = t.unreached_func('first source should not load');
+ track.onerror = t.step_func_done();
+ track.src = 'resources/settings.vtt?pipe=trickle(d3600)';
+ track.track.mode = 'hidden';
+ document.querySelector('video').appendChild(track);
+ t.step_timeout(() => {
+ track.src = 'resources/entities.vtt';
+ }, 0);
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change-error.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change-error.html
new file mode 100644
index 0000000000..dd97d0522d
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change-error.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<title>HTMLTrackElement 'src' attribute mutations</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/settings.vtt" default>
+ <script>
+ async_test(function(t) {
+ var cues = null;
+ var testTrack = document.querySelector("track");
+ var stage = 0;
+ var timer = null;
+ function step_onLoad() {
+ switch (stage) {
+ case 0:
+ cues = testTrack.track.cues;
+ assert_equals(testTrack.readyState, HTMLTrackElement.LOADED, "readyState after first loading of the track");
+ assert_equals(cues.length, 4, "Number of cues after first loading of the track");
+ ++stage;
+ testTrack.src = "resources/non-existing-file.vtt"; // this should fail
+ break;
+ case 1:
+ case 3:
+ case 4:
+ assert_unreached("'error' event did not fire, stage = " + stage);
+ break;
+ case 2:
+ assert_equals(testTrack.readyState, HTMLTrackElement.LOADED, "readyState after loading of the second track");
+ assert_equals(cues.length, 4, "Number of cues after loading of the second track");
+ assert_equals(cues[cues.length-1].text, 'I said Bear is coming now!!!! Tab separators.', "Last cue content check");
+ ++stage;
+ testTrack.src = ""; // this should fail
+ assert_equals(cues.length, 0, "cues list is reset immediately after 'src' mutation with the new URL");
+ // This should raise onError event. If no, we'll know about this after some time.
+ timer = t.step_timeout(t.unreached_func("'error' event is not fired when an empty URL is set"), 100);
+ break;
+ default:
+ assert_unreached("unexpected stage number = " + stage);
+ break;
+ }
+ }
+
+ function step_onError() {
+ switch (stage) {
+ case 0:
+ case 2:
+ assert_unreached("'error' event fired, stage = " + stage);
+ break;
+ case 1:
+ assert_equals(cues, testTrack.track.cues, ".cues object are the same after 'src' attr mutation");
+ assert_equals(cues.length, 0, "Number of cues after trying to load non-existing url");
+ assert_equals(testTrack.readyState, HTMLTrackElement.ERROR, "readyState after trying to load non-existing url");
+ ++stage;
+ testTrack.src = "resources/settings.vtt";
+ break;
+ case 3:
+ clearTimeout(timer);
+ assert_equals(testTrack.readyState, HTMLTrackElement.ERROR, "readyState after setting an empty URL");
+ assert_equals(cues, testTrack.track.cues, ".cues object are the same after 'src' attr mutation");
+ assert_equals(cues.length, 0, "Number of cues with an empty URL set");
+ ++stage;
+ testTrack.src = "resources/settings.vtt";
+ // error should happen when we remove `src` during loading, so we have to wait a task because loading starts asynchronously.
+ t.step_timeout(() => {
+ testTrack.removeAttribute('src');
+ // This should raise onError event, so we'll wait for it for some time
+ timer = t.step_timeout(t.unreached_func("'error' event is not fired when an empty URL is set"), 100);
+ }, 0);
+ break;
+ case 4:
+ clearTimeout(timer);
+ assert_equals(testTrack.readyState, HTMLTrackElement.ERROR, "readyState after removing 'src' attr");
+ assert_equals(cues.length, 0, "Number of cues after removing 'src' attr");
+ t.done();
+ break;
+ default:
+ assert_unreached("unexpected stage number = " + stage);
+ break;
+ }
+ }
+
+ testTrack.onload = t.step_func(step_onLoad);
+ testTrack.onerror = t.step_func(step_onError);
+ });
+ </script>
+</video>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change.html
new file mode 100644
index 0000000000..f3c78668b4
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<title>HTMLTrackElement 'src' attribute mutations</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/settings.vtt" default>
+ <script>
+ async_test(function(t) {
+ var cues = null;
+ var testTrack = document.querySelector("track");
+ var stage = 0;
+ function step_onLoad() {
+ switch (stage) {
+ case 0:
+ cues = testTrack.track.cues;
+ assert_equals(testTrack.readyState, HTMLTrackElement.LOADED, "readyState after first loading of the track");
+ assert_equals(cues.length, 4, "Number of cues after first loading of the track");
+ assert_equals(cues[cues.length-1].text, 'I said Bear is coming now!!!! Tab separators.', "Last cue content check");
+ ++stage;
+ testTrack.src = "resources/entities.vtt";
+ assert_equals(cues.length, 0, "cues list is reset immediately after 'src' mutation with the new URL");
+ break;
+ case 1:
+ assert_equals(testTrack.readyState, HTMLTrackElement.LOADED), "readyState after loading of the second track";
+ assert_equals(cues, testTrack.track.cues, ".cues object are the same after 'src' attr mutation");
+ assert_equals(cues.length, 7, "Number of cues after loading of the second track");
+ assert_equals(cues[cues.length-1].text, 'This & is parsed to the same as &amp;.', "Last cue content check");
+ ++stage;
+ testTrack.src = "resources/settings.vtt";
+ break;
+ case 2:
+ assert_equals(testTrack.readyState, HTMLTrackElement.LOADED, "readyState after after loading of the first track again");
+ assert_equals(cues[cues.length-1].text, 'I said Bear is coming now!!!! Tab separators.', "Last cue content check");
+ assert_equals(cues, testTrack.track.cues, ".cues object are the same after 'src' attr mutation");
+ assert_equals(cues.length, 4, "Number of cues after loading of the first track");
+ ++stage;
+ testTrack.src = "resources/settings.vtt";
+ // This should not raise onLoad or onError event, so we'll wait for it for some time
+ t.step_timeout(t.step_func_done(function() {
+ assert_equals(testTrack.readyState, HTMLTrackElement.LOADED, "readyState after changing 'src' to the same value");
+ assert_equals(cues, testTrack.track.cues, ".cues object are the same after 'src' attr mutation");
+ assert_equals(cues.length, 4, "Number of cues after changing 'src' to the same value");
+ }, 100));
+ break;
+ case 3:
+ assert_unreached("'load' event should not fire, stage = " + stage);
+ break;
+ }
+ }
+
+ testTrack.onload = t.step_func(step_onLoad);
+ testTrack.onerror = t.unreached_func("'error' event should not fire");
+ });
+ </script>
+</video>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-helpers.js b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-helpers.js
new file mode 100644
index 0000000000..09c85dd7bc
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-helpers.js
@@ -0,0 +1,83 @@
+function enableAllTextTracks(textTracks) {
+ for (var i = 0; i < textTracks.length; i++) {
+ var track = textTracks[i];
+ if (track.mode == "disabled")
+ track.mode = "hidden";
+ }
+}
+
+function assert_cues_equal(cues, expected) {
+ assert_equals(cues.length, expected.length);
+ for (var i = 0; i < cues.length; i++) {
+ assert_equals(cues[i].id, expected[i].id);
+ assert_equals(cues[i].startTime, expected[i].startTime);
+ assert_equals(cues[i].endTime, expected[i].endTime);
+ assert_equals(cues[i].text, expected[i].text);
+ }
+}
+
+function assert_cues_match(cues, expected) {
+ assert_equals(cues.length, expected.length);
+ for (var i = 0; i < cues.length; i++) {
+ var cue = cues[i];
+ var expectedItem = expected[i];
+ for (var property of Object.getOwnPropertyNames(expectedItem))
+ assert_equals(cue[property], expectedItem[property]);
+ }
+}
+
+function assert_cues_html_content(cues, expected) {
+ assert_equals(cues.length, expected.length);
+ for (var i = 0; i < cues.length; i++) {
+ var expectedItem = expected[i];
+ var property = Object.getOwnPropertyNames(expectedItem)[0];
+ var propertyValue = expectedItem[property];
+ assert_equals(propertyValue(cues[i]), expectedItem.expected);
+ }
+}
+
+function check_cues_from_track(src, func) {
+ async_test(function(t) {
+ var video = document.createElement("video");
+ var trackElement = document.createElement("track");
+ trackElement.src = src;
+ trackElement.default = true;
+ video.appendChild(trackElement);
+
+ trackElement.onload = t.step_func_done(function() {
+ func(trackElement.track);
+ });
+ }, "Check cues from " + src);
+}
+
+function assert_cue_fragment(cue, children) {
+ var fragment = createFragment(children);
+ assert_true(fragment.isEqualNode(cue.getCueAsHTML()));
+}
+
+function assert_cue_fragment_as_textcontent(cue, children) {
+ var fragment = createFragment(children);
+ assert_equals(cue.getCueAsHTML().textContent, fragment.textContent);
+}
+
+function createFragment(children) {
+ var fragment = document.createDocumentFragment();
+ cloneChildrenToFragment(fragment, children);
+ return fragment;
+}
+
+function cloneChildrenToFragment(root, children) {
+ for (var child of children) {
+ var childElement;
+ if (child.type == "text") {
+ childElement = document.createTextNode(child.value);
+ } else {
+ childElement = document.createElement(child.type);
+ var styles = child.style || {};
+ for (var attr of Object.getOwnPropertyNames(styles))
+ childElement[attr] = styles[attr];
+ cloneChildrenToFragment(childElement, child.value);
+ }
+ root.appendChild(childElement);
+ }
+} \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-id.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-id.html
new file mode 100644
index 0000000000..f0223fda64
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-id.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>TextTrack "id" attribute</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track id="LoremIpsum" src="resources/captions-fast.vtt" default>
+ <script>
+ test(function() {
+ var video = document.querySelector("video");
+ var track = document.querySelector("track");
+ var textTrack = track.track;
+
+ // Test default attribute value.
+ assert_equals(textTrack.id, "LoremIpsum");
+ assert_equals(video.textTracks[0].id, "LoremIpsum");
+
+ // Make sure we can look up tracks by id.
+ assert_equals(video.textTracks.getTrackById("LoremIpsum"), textTrack);
+
+ // Test that it's readonly.
+ textTrack.id = "newvalue";
+ assert_equals(textTrack.id, "LoremIpsum");
+ });
+ </script>
+</video> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-insert-after-load.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-insert-after-load.html
new file mode 100644
index 0000000000..28b4f82688
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-insert-after-load.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<title>Inserting a track element immediately after video load</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+async_test(function(t) {
+ var video = document.createElement('video');
+ video.src = getVideoURI('/media/test');
+ video.load();
+ video.appendChild(document.createElement('track'));
+ video.onloadedmetadata = t.step_func_done();
+});
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-large-timestamp.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-large-timestamp.html
new file mode 100644
index 0000000000..bae1852cf8
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-large-timestamp.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title>Very large timestamp is parsed correctly</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/large-timestamp.vtt" default>
+ <script>
+ async_test(function(t) {
+ var testTrack = document.querySelector("track");
+ testTrack.onload = t.step_func_done(function() {
+ assert_equals(testTrack.track.cues.length, 1);
+ var cue = testTrack.track.cues[0];
+ assert_equals(parseInt(cue.id), 1);
+ assert_equals(cue.startTime / 3600, 1234567);
+ assert_equals(cue.endTime / 3600, 1234567890);
+ });
+ });
+ </script>
+</video> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-load-error-readyState.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-load-error-readyState.html
new file mode 100644
index 0000000000..8e232bff53
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-load-error-readyState.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>Error event on HTMLTrackElement and ERROR readyState on TextTrack</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="junk" default>
+ <script>
+ async_test(function(t) {
+ var track = document.querySelector("track");
+ track.onerror = t.step_func_done(function() {
+ assert_equals(track.readyState, HTMLTrackElement.ERROR);
+ });
+ });
+ </script>
+</video>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-load-from-element-readyState.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-load-from-element-readyState.html
new file mode 100644
index 0000000000..62a68f6543
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-load-from-element-readyState.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>Load event on HTMLTrackElement and LOADED readyState on TextTrack when src is set on the element</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/webvtt-file.vtt" default>
+ <script>
+ async_test(function(t) {
+ var track = document.querySelector("track");
+ track.onload = t.step_func_done(function() {
+ assert_equals(track.readyState, HTMLTrackElement.LOADED);
+ });
+ });
+ </script>
+</video>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-load-from-src-readyState.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-load-from-src-readyState.html
new file mode 100644
index 0000000000..e569eeb96f
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-load-from-src-readyState.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<title>Load event on HTMLTrackElement and LOADED readyState on TextTrack when src is set from JavaScript</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track>
+</video>
+<script>
+async_test(function(t) {
+ var track = document.querySelector("track");
+ assert_equals(track.readyState, HTMLTrackElement.NONE);
+
+ track.onload = t.step_func_done(function() {
+ assert_equals(track.readyState, HTMLTrackElement.LOADED);
+ });
+
+ track.src = "resources/webvtt-file.vtt";
+ track.track.mode = "hidden";
+});
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-mode-disabled.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-mode-disabled.html
new file mode 100644
index 0000000000..6b46bf4e34
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-mode-disabled.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<title>Cues are properly removed from the active cue list when their track changes mode to disabled</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/captions-gaps.vtt" kind="captions" default >
+ <script>
+ async_test(function(t) {
+ var video = document.querySelector("video");
+ var testTrack = document.querySelector("track");
+
+ video.src = getVideoURI("/media/counting");
+ video.oncanplaythrough = t.step_func(startTest);
+ video.onseeked = t.step_func_done(seeked);
+
+ function startTest() {
+ // Set the mode of the text track to "showing".
+ testTrack.track.mode = "showing";
+ // Seek to a time with a caption.
+ video.currentTime = 1.5;
+ }
+
+ function seeked() {
+ // Set the mode of the text track to "hidden", then to "showing" again.
+ testTrack.track.mode = "hidden";
+ testTrack.track.mode = "showing";
+
+ // Set the mode of the text track to "disabled".
+ testTrack.track.mode = "disabled";
+ }
+ });
+ </script>
+</video> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-mode-not-changed-by-new-track.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-mode-not-changed-by-new-track.html
new file mode 100644
index 0000000000..3ec47a39e2
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-mode-not-changed-by-new-track.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<title>A track appended after the initial track configuration does not change other tracks</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track kind="metadata" src="resources/metadata.vtt">
+</video>
+<script>
+async_test(function(t) {
+ var video = document.querySelector('video');
+
+ var track1 = document.querySelectorAll('track')[0];
+ assert_equals(track1.readyState, HTMLTrackElement.NONE);
+ assert_equals(track1.track.mode, 'disabled');
+
+ video.src = getVideoURI('/media/test');
+ video.oncanplaythrough = t.step_func(canplaythrough);
+ track1.onload = t.step_func(metadataTrackLoaded);
+
+ function canplaythrough() {
+ // check initial metadata track state.
+ assert_equals(track1.readyState, HTMLTrackElement.NONE);
+ assert_equals(track1.track.mode, 'disabled');
+ assert_equals(track1.track.cues, null);
+ track1.track.mode = 'hidden';
+ }
+
+ function metadataTrackLoaded() {
+ // check metadata track state.
+ assert_equals(track1.readyState, HTMLTrackElement.LOADED);
+ assert_equals(track1.track.mode, 'hidden');
+ assert_equals(track1.track.cues.length, 12);
+ assert_equals(track1.track.cues[11].startTime, 22);
+
+ // Add a caption track, and explicitly enable it.
+ track2 = document.createElement('track');
+ track2.setAttribute('kind', 'captions');
+ track2.setAttribute('default', 'default');
+ track2.setAttribute('src', 'resources/webvtt-file.vtt');
+ track2.track.mode = 'showing';
+ track2.onload = t.step_func(captionsTrackLoaded);
+ video.appendChild(track2);
+ }
+
+ function captionsTrackLoaded() {
+ // Check that metadata track state has not changed.
+ assert_equals(track1.readyState, HTMLTrackElement.LOADED);
+ assert_equals(track1.track.mode, 'hidden');
+ // and that the caption track state is correct.
+ assert_equals(track2.readyState, HTMLTrackElement.LOADED);
+ assert_equals(track2.track.mode, 'showing');
+
+ video.textTracks.onaddtrack = t.step_func_done(trackAdded);
+ // add a subtitle track with video.addTextTrack().
+ track3 = video.addTextTrack('subtitles', 'Subtitle Track', 'en');
+ track3.mode = 'showing';
+ }
+
+ function trackAdded(event) {
+ // Check that metadata track state has not changed.
+ assert_equals(track1.readyState, HTMLTrackElement.LOADED);
+ assert_equals(track1.track.mode, 'hidden');
+ // and that the caption track state has not changed.
+ assert_equals(track2.readyState, HTMLTrackElement.LOADED);
+ assert_equals(track2.track.mode, 'showing');
+ // and that the subtitle track state is correct.
+ assert_equals(event.target, video.textTracks);
+ assert_true(event instanceof window.TrackEvent);
+ assert_equals(event.track, video.textTracks[video.textTracks.length - 1]);
+ assert_equals(track3.mode, 'showing');
+ }
+});
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-mode-triggers-loading.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-mode-triggers-loading.html
new file mode 100644
index 0000000000..2e29d70469
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-mode-triggers-loading.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<title>A "metadata" track does not load automatically, but it does load when the mode is changed</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track kind="metadata" src="resources/metadata.vtt">
+</video>
+<script>
+async_test(function(t) {
+ var video = document.querySelector("video");
+
+ // Check initial metadata track state.
+ var track = document.querySelectorAll("track")[0];
+ assert_equals(track.readyState, HTMLTrackElement.NONE);
+ assert_equals(video.textTracks[0].mode, "disabled");
+
+ video.src = getVideoURI("/media/test");
+ video.oncanplaythrough = t.step_func(canplaythrough);
+ track.onload = t.step_func_done(trackLoaded);
+
+ function trackLoaded() {
+ assert_equals(track.readyState, HTMLTrackElement.LOADED);
+ assert_equals(track.track.mode, "hidden");
+ assert_equals(video.textTracks[0].cues.length, 12);
+ assert_equals(video.textTracks[0].cues[11].startTime, 22);
+ }
+
+ function canplaythrough() {
+ assert_equals(track.readyState, HTMLTrackElement.NONE);
+ assert_equals(video.textTracks[0].mode, "disabled");
+ assert_equals(video.textTracks[0].cues, null);
+ // Change metadata track mode so it loads.
+ video.textTracks[0].mode = "hidden";
+ }
+});
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-mode.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-mode.html
new file mode 100644
index 0000000000..206ac9968f
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-mode.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<title>TextTrack mode attribute</title>
+<meta name="timeout" content="long">
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/captions-fast.vtt" default>
+ <script>
+ async_test(function(t) {
+ var video = document.querySelector("video");
+ var track = document.querySelector("track");
+ if (track.readyState != HTMLTrackElement.LOADED) {
+ assert_not_equals(track.readyState, HTMLTrackElement.ERROR,
+ "track failed to load resource.");
+ track.onload = t.step_func(trackLoaded);
+ } else {
+ trackLoaded();
+ }
+
+ var cueCount = 0;
+ var textTrack;
+ function trackLoaded() {
+ textTrack = track.track;
+ // Test default attribute value.
+ assert_equals(textTrack.mode, "showing");
+ assert_equals(video.textTracks[0].mode, "showing");
+ // Set to bogus value, should return default.
+ var value = "bogus";
+ textTrack.mode = value;
+ assert_equals(textTrack.mode, "showing");
+ assert_equals(video.textTracks[0].mode, "showing");
+
+ // Set to numeric value (no longer supported), should return default.
+ textTrack.mode = 2;
+ assert_equals(textTrack.mode, "showing");
+ assert_equals(video.textTracks[0].mode, "showing");
+
+ // Set to known values.
+ setModeAndCheck("disabled");
+
+ video.src = getVideoURI("/media/test");
+ video.play();
+
+ // Wait for end of first cue (no events should fire while track is disabled).
+ video.ontimeupdate = () => {
+ if (video.currentTime > 0.4) {
+ testHiddenAndShowing();
+ video.ontimeupdate = null;
+ }
+ }
+ }
+
+ track.oncuechange = t.step_func(function(event) {
+ cueCount++;
+ // As the 'enter' and the 'exit' event would be fired for the second
+ // and the third cue, so there would be 4 times 'oncuechange' event.
+ if (cueCount == 4)
+ t.done();
+ });
+
+ function setModeAndCheck(value) {
+ textTrack.mode = value;
+ assert_equals(textTrack.mode, value);
+ assert_equals(video.textTracks[0].mode, value);
+ if (value == "disabled")
+ assert_equals(textTrack.cues, null);
+ }
+
+ function testHiddenAndShowing() {
+ setModeAndCheck("hidden");
+ setModeAndCheck("showing");
+ }
+ });
+ </script>
+</video> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-node-add-remove.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-node-add-remove.html
new file mode 100644
index 0000000000..2708879424
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-node-add-remove.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<title>Add and remove track node</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<script>
+test(function() {
+ var video = document.createElement('video');
+ var tracka = document.createElement('track');
+ video.appendChild(tracka);
+ var trackb = document.createElement('track');
+ video.appendChild(trackb);
+
+ // Adding tracks outside the DOM tree.
+ assert_array_equals(video.textTracks, [tracka.track, trackb.track]);
+
+ // Inserting the parent video element into the document.
+ document.body.appendChild(video);
+ assert_array_equals(video.textTracks, [tracka.track, trackb.track]);
+
+ // Inserting and removing another track in the document.
+ var trackc = document.createElement('track');
+ video.appendChild(trackc);
+ assert_array_equals(video.textTracks, [tracka.track, trackb.track, trackc.track]);
+
+ trackb.parentNode.removeChild(trackb);
+ assert_array_equals(video.textTracks, [tracka.track, trackc.track]);
+
+ // Removing the video from the document.
+ document.body.removeChild(video);
+ assert_array_equals(video.textTracks, [tracka.track, trackc.track]);
+
+ tracka.parentNode.removeChild(tracka);
+ assert_array_equals(video.textTracks, [trackc.track]);
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-active-cue.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-active-cue.html
new file mode 100644
index 0000000000..176e0065c5
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-active-cue.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<title>Removing an active cue</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video></video>
+<script>
+async_test(function(t) {
+ var video = document.querySelector("video");
+ video.src = getVideoURI("/media/test");
+
+ // Add a text track to the video element.
+ video.addTextTrack("captions", "regular captions track", "en");
+
+ // Add a cue to the track with enter event listener.
+ var cue = new VTTCue(0, 4, "Random");
+ cue.onenter = t.step_func_done(removeActiveCue);
+
+ var track = video.textTracks[0];
+ track.addCue(cue);
+
+ function removeActiveCue() {
+ assert_equals(track.activeCues.length, 1);
+
+ // Remove the cue while it is active.
+ track.removeCue(track.activeCues[0]);
+
+ // No crash. PASS.
+ }
+
+ // Play the video and remove cue when it becomes active.
+ video.play();
+ track.mode = "showing";
+});
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-by-setting-innerHTML.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-by-setting-innerHTML.html
new file mode 100644
index 0000000000..95929bc83f
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-by-setting-innerHTML.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<title>Removing a track by setting video.innerHTML doesn't crash</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track default src="resources/captions-gaps.vtt">
+ <script>
+ // https://bugs.webkit.org/show_bug.cgi?id=100981
+ async_test(function(t) {
+ var firstSeek = true;
+ var video = document.querySelector('video');
+ video.onseeked = t.step_func(function() {
+ if (!firstSeek) {
+ t.done();
+ return;
+ }
+
+ // Remove the text track
+ video.innerHTML = '';
+
+ // Seek again to force a repaint.
+ video.currentTime = 7.9;
+ firstSeek = false;
+ });
+
+ video.currentTime = 0.5;
+ video.src = getVideoURI('/media/counting');
+ });
+ </script>
+</video> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-insert-ready-state.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-insert-ready-state.html
new file mode 100644
index 0000000000..91375f579e
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-insert-ready-state.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<title>Attaching a media element again to the document, having a child track that failed loading doesn't block video from playing</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/no-webvtt.vtt" kind="captions" default>
+</video>
+<script>
+ async_test(function(t) {
+ var video = document.querySelector('video');
+ video.src = getVideoURI('/media/test');
+ video.oncanplaythrough = t.step_func(canplaythrough);
+
+ function canplaythrough() {
+ video.oncanplaythrough = null;
+ var track = document.querySelector('track');
+
+ // Track should have error as ready state.
+ assert_equals(track.readyState, HTMLTrackElement.ERROR);
+
+ // Remove the video element from body.
+ document.body.removeChild(video);
+
+ // Reset the video src attribute to re-trigger resource selection for tracks.
+ video.src = getVideoURI('/media/test');
+
+ // Append the video element back to the body.
+ document.body.appendChild(video);
+
+ assert_equals(track.readyState, HTMLTrackElement.ERROR);
+
+ video.onplaying = t.step_func_done();
+ video.play();
+ // The video should start playing.
+ }
+ });
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-quickly.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-quickly.html
new file mode 100644
index 0000000000..4be040c5f8
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-quickly.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<title>Removing a track element before it has been processed doesn't crash</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="video_container"></div>
+<script>
+var mediaFile = getVideoURI("/media/test");
+document.getElementById("video_container").innerHTML = "<video src='" + mediaFile + "' controls ><track kind='captions' src='resources/simple-captions.vtt' default ></video>";
+test(function() {
+// https://bugs.webkit.org/show_bug.cgi?id=85095
+// Test passes if it doesn't crash.
+});
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-track-inband.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-track-inband.html
new file mode 100644
index 0000000000..7dcfe68318
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-track-inband.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+ <script src="/common/media.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <script>
+ async_test(function(test)
+ {
+ var video = document.createElement("video");
+
+ // Create an out-of-band text track by adding a track element.
+ var trackElement = document.createElement('track');
+
+ trackElement.addEventListener("error", test.step_func(function()
+ {
+ assert_unreached("'error' event on track element should not fire.")
+ }));
+
+ video.appendChild(trackElement);
+ trackElement.src = 'resources/webvtt-file.vtt';
+ trackElement.track.mode = 'hidden';
+
+ assert_equals(video.textTracks.length, 1);
+ var outOfBandTrack = video.textTracks[0];
+
+ // Load a media file with an inband text track.
+ var inbandTrack = null;
+ var url = "resources/vp8-vorbis-webvtt.webm"
+
+ var firstAddTrackHandler = test.step_func(function()
+ {
+ assert_equals(event.target, video.textTracks);
+ assert_equals(event instanceof window.TrackEvent, true);
+ if (event.track == outOfBandTrack) {
+ return;
+ }
+
+ assert_equals(inbandTrack, null);
+ assert_equals(video.textTracks.length, 2);
+ assert_equals(event.track, video.textTracks[1]);
+ inbandTrack = event.track;
+
+ video.textTracks.removeEventListener("addtrack", firstAddTrackHandler);
+
+ // Clear .src to force the inband track to get destroyed.
+ video.src = "";
+
+ // Verify that the inband track was removed.
+ assert_not_equals(inbandTrack, null);
+ assert_equals(video.textTracks.length, 1);
+ assert_equals(video.textTracks[0], outOfBandTrack);
+
+ // Load the URL again to trigger another 'addtrack' event to make sure
+ // no 'removetrack' event was queued.
+ video.src = url;
+ video.textTracks.addEventListener("addtrack", test.step_func(function()
+ {
+ assert_equals(video.textTracks.length, 2);
+ test.done();
+ }));
+ });
+ video.textTracks.addEventListener("addtrack", firstAddTrackHandler);
+
+ video.textTracks.addEventListener("removetrack", test.step_func(function()
+ {
+ assert_unreached("'removetrack' event should not fire.")
+ }));
+
+ video.src = url;
+ }, "Tests that the 'removetrack' event is NOT fired for inband TextTrack on a failed load.");
+
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-track.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-track.html
new file mode 100644
index 0000000000..d5695cd302
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-track.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+ <script src="/common/media.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <script>
+ async_test(function(test)
+ {
+ var video = document.createElement("video");
+ var track;
+
+ function trackRemoved()
+ {
+ assert_equals(event.target, video.textTracks);
+ assert_equals(event instanceof window.TrackEvent, true);
+ assert_equals(event.track, track);
+ test.done();
+ }
+
+ var trackElement = document.createElement('track');
+ video.appendChild(trackElement);
+
+ trackElement.src = 'resources/webvtt-file.vtt';
+ trackElement.track.mode = 'hidden';
+
+ assert_equals(video.textTracks.length, 1);
+
+ track = video.textTracks[0];
+ video.removeChild(trackElement);
+ video.textTracks.addEventListener("removetrack", test.step_func(trackRemoved));
+ }, "Tests that the 'removetrack' event is fired when an out-of-band TextTrack is removed.");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-selection-metadata.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-selection-metadata.html
new file mode 100644
index 0000000000..c4d88a35f0
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-selection-metadata.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<title>Multiple 'metadata' tracks with 'default'</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track kind="metadata" src="resources/default-styles.vtt" id="t1">
+ <track kind="metadata" src="resources/class.vtt" default id="t2hidden">
+ <track kind="metadata" src="resources/metadata-area.vtt" id="t3">
+ <track kind="metadata" src="resources/webvtt-file.vtt" default id="t4hidden">
+</video>
+<script>
+async_test(function() {
+ var video = document.querySelector('video');
+ video.onloadstart = this.step_func_done(function() {
+ assert_equals(video.textTracks.length, 4);
+ for (var track of video.textTracks) {
+ assert_equals(track.kind, 'metadata');
+
+ var trackElement = document.getElementById(track.id);
+ if (track.id.indexOf('hidden') != -1) {
+ assert_true(trackElement.default);
+ assert_equals(track.mode, 'hidden');
+ } else {
+ assert_false(trackElement.default);
+ assert_equals(track.mode, 'disabled');
+ }
+ }
+ });
+
+ video.src = getVideoURI("/media/test");
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-selection-task-order.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-selection-task-order.html
new file mode 100644
index 0000000000..522d067adf
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-selection-task-order.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<title>HTMLTrackElement Text Track Selection Task Order</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+/**
+ * This test is used to ensure that we queue 'honor user preferences for automatic
+ * text track selection' as a macro task, not a micro task. In this test, we
+ * trigger a media event before queuing a text track selection task, and check
+ * the text track's mode to know whether the text track selection runs after the
+ * task for media event.
+ */
+async_test(function(t) {
+ let video = document.createElement("video");
+ video.play();
+ video.onplay = t.step_func(startedPlay);
+
+ // When we create a text track element, it queue a task to run automatic
+ // text track selection later.
+ let track = document.createElement("track");
+ track.default = true;
+ video.appendChild(track);
+ assert_equals(track.track.mode, "disabled", "Text track's mode is disabled by default.");
+
+ function startedPlay() {
+ assert_equals(track.track.mode, "disabled", "Text track selection hasn't started yet.");
+ track.onerror = t.step_func_done(trackError);
+ }
+
+ function trackError() {
+ assert_equals(track.track.mode, "showing", "Text track selection modified track's mode.");
+ t.done();
+ }
+});
+
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-text-track-cue-list.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-text-track-cue-list.html
new file mode 100644
index 0000000000..73241ce0d4
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-text-track-cue-list.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>TextTrackCueList functionality: length, operator[], and getCueById()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/settings.vtt" kind="captions" default>
+ <script>
+ async_test(function(t) {
+ var testTrack = document.querySelector("track");
+
+ testTrack.onload = t.step_func_done(function() {
+ var cues = testTrack.track.cues;
+
+ // Testing TextTrackCueList length.
+ assert_equals(cues.length, 4);
+
+ // Testing TextTrackCueList [] operator.
+ assert_equals(cues[0].id, "1");
+ assert_equals(cues[3].id, "4");
+ assert_equals(cues[4], undefined);
+
+ // Testing TextTrackCueList getCueById().
+ assert_equals(cues.getCueById("1").startTime, 0);
+ assert_equals(cues.getCueById("4").startTime, 121);
+ assert_equals(cues.getCueById("junk"), null);
+ });
+ });
+ </script>
+</video>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-texttracks.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-texttracks.html
new file mode 100644
index 0000000000..4d006fcefb
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-texttracks.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<title>TextTracks in a TextTrackList are kept in the correct order</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track kind="captions" src="resources/webvtt-file.vtt">
+</video>
+<script>
+test(function() {
+ var video = document.querySelector("video");
+
+ // Add a track with video.addTextTrack().
+ video.addTextTrack("descriptions", "Descriptions Track", "en");
+
+ // Add a track element with DOM API.
+ var trackElement = document.createElement("track");
+ trackElement.setAttribute("kind", "chapters");
+ video.appendChild(trackElement);
+
+ // Verify track order.
+ assert_equals(video.textTracks.length, 3);
+ assert_equals(video.textTracks[0].kind, "captions");
+ assert_equals(video.textTracks[1].kind, "chapters");
+ assert_equals(video.textTracks[2].kind, "descriptions");
+
+ // Verify the default parameters of the text track object
+ // returned by addTextTrack().
+ assert_equals(video.textTracks[2].mode, "hidden");
+ assert_not_equals(video.textTracks[2].cues, null);
+ assert_equals(video.textTracks[2].cues.length, 0);
+
+ // Add another track element, it should insert
+ // before the addTextTrack() track.
+ trackElement = document.createElement("track");
+ trackElement.setAttribute("kind", "metadata");
+ video.appendChild(trackElement);
+
+ assert_equals(video.textTracks.length, 4);
+ assert_equals(video.textTracks[0].kind, "captions");
+ assert_equals(video.textTracks[1].kind, "chapters");
+ assert_equals(video.textTracks[2].kind, "metadata");
+ assert_equals(video.textTracks[3].kind, "descriptions");
+});
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-align-positioning.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-align-positioning.html
new file mode 100644
index 0000000000..07ebfd622b
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-align-positioning.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<title>Cue text position and alignment from settings</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/align-positioning.vtt">
+ <track src="resources/align-positioning-bad.vtt">
+</video>
+<script>
+async_test(function(t) {
+ var video = document.querySelector("video");
+
+ var trackElements = document.querySelectorAll("track");
+ assert_equals(trackElements.length, video.textTracks.length);
+ for (var i = 0; i < trackElements.length; i++)
+ trackElements[i].onload = t.step_func(trackLoaded);
+
+ enableAllTextTracks(video.textTracks);
+
+ var numberOfTracksLoaded = 0;
+ function trackLoaded() {
+ numberOfTracksLoaded++;
+ if (numberOfTracksLoaded != 2)
+ return;
+
+ testTrack(0);
+ testTrackError(1);
+ t.done();
+ }
+
+ function testTrack(index) {
+ var expected = [
+ { position : 10, align : "start" },
+ { position : 20, align : "center" },
+ { position : 80, align : "end" }
+ ];
+
+ assert_cues_match(video.textTracks[index].cues, expected);
+ }
+
+ function testTrackError(index) {
+ var expected = [
+ { position : 10, align : "center" },
+ { position : "auto", align : "center" },
+ { position : "auto", align : "center" }
+ ];
+
+ assert_cues_match(video.textTracks[index].cues, expected);
+ }
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-align-text-line-position.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-align-text-line-position.html
new file mode 100644
index 0000000000..deb389916a
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-align-text-line-position.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<title>Cue alignment, line and text position from settings</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/align-text-line-position.vtt">
+ <track src="resources/align-text-line-position-bad.vtt">
+</video>
+<script>
+async_test(function(t) {
+ var video = document.querySelector("video");
+
+ var trackElements = document.querySelectorAll("track");
+ assert_equals(trackElements.length, video.textTracks.length);
+ for (var i = 0; i < trackElements.length; i++)
+ trackElements[i].onload = t.step_func(trackLoaded);
+
+ enableAllTextTracks(video.textTracks);
+
+ var numberOfTracksLoaded = 0;
+ function trackLoaded() {
+ numberOfTracksLoaded++;
+ if (numberOfTracksLoaded != 2)
+ return;
+
+ testTrack(0);
+ testTrackError(1);
+ t.done();
+ }
+
+ function testTrack(index) {
+ var expected = [
+ { align : "start", position : 10, line : 0, snapToLines : false },
+ { align : "start", position : "auto", line : 0, snapToLines : true },
+ { align : "center", position : 80, line : 80, snapToLines : false },
+ { align : "end", position : 30, line : 5, snapToLines : true },
+ { align : "center", position : 60, line : -3, snapToLines : true }
+ ];
+
+ assert_cues_match(video.textTracks[index].cues, expected);
+ }
+
+ function testTrackError(index) {
+ var expected = [
+ { align : "center", position : "auto", line : "auto", snapToLines : true },
+ { align : "end", position : 0, line : "auto", snapToLines : true },
+ { align : "center", position : 60, line : -3, snapToLines : true }
+ ];
+
+ assert_cues_match(video.textTracks[index].cues, expected);
+ }
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-alignment.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-alignment.html
new file mode 100644
index 0000000000..e8f47e876a
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-alignment.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<title>Cue alignment from settings</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/alignment.vtt", testTrack);
+check_cues_from_track("resources/alignment-ltr.vtt", testTrack);
+
+check_cues_from_track("resources/alignment-bad.vtt", function(track) {
+ var expected = [
+ { align: "center" },
+ { align: "center" },
+ { align: "center" },
+ { align: "center" }
+ ];
+
+ assert_cues_match(track.cues, expected);
+});
+
+function testTrack(track) {
+ var expected = [
+ { align: "start" },
+ { align: "center" },
+ { align: "end" },
+ { align: "center" }
+ ];
+
+ assert_cues_match(track.cues, expected);
+}
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-blank-lines.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-blank-lines.html
new file mode 100644
index 0000000000..114aebc38c
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-blank-lines.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Cues are affected neither by multiple newlines \n, \r, and \r\n nor by the absence of a seperating line</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/cues.vtt", function(track) {
+ var expected = [
+ { id: "1", startTime: 0, endTime: 30.5, text: "Bear is Coming!!!!!" },
+ { id: "2", startTime: 31, endTime: 60.5, text: "I said Bear is coming!!!!" },
+ { id: "3", startTime: 61, endTime: 361200.5, text: "I said Bear is coming now!!!!" }
+ ];
+
+ assert_cues_match(track.cues, expected);
+});
+
+check_cues_from_track("resources/cues-no-separation.vtt", function(track) {
+ var expected = [
+ { id: "1", startTime: 0, endTime: 30.5, text: "Bear is Coming!!!!!\n2" },
+ { id: "", startTime: 31, endTime: 60.5, text: "I said Bear is coming!!!!" },
+ { id: "", startTime: 61, endTime: 361200.5, text: "I said Bear is coming now!!!!" }
+ ];
+
+ assert_cues_match(track.cues, expected);
+});
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-bom.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-bom.html
new file mode 100644
index 0000000000..c138f96af5
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-bom.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<title>Parser properly ignores a UTF-8 BOM character at the beginning of a file and all other cues are properly parsed</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/bom.vtt" default>
+ <script>
+ async_test(function(t) {
+ var track = document.querySelector("track");
+
+ track.onload = t.step_func_done(function() {
+ var expected = [
+ {
+ id : "1",
+ startTime : 0,
+ endTime : 30.5,
+ text : "Bear is Coming!!!!!"
+ },
+ {
+ id : "2",
+ startTime : 31,
+ endTime : 1200.5,
+ text : "I said Bear is coming!!!!"
+ }
+ ];
+
+ var cues = track.track.cues;
+ assert_equals(cues.length, 2);
+ assert_cues_equal(cues, expected);
+ });
+ });
+ </script>
+</video> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-class-markup.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-class-markup.html
new file mode 100644
index 0000000000..ecc5a57497
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-class-markup.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<title>Tests cues with class markup &lt;c&gt;.</title>
+<meta name="timeout" content="long">
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/class.vtt", function(track) {
+ assert_equals(track.cues.length, 3);
+
+ var children = [
+ { type: "span", style: { className: "black" },
+ value: [ { type: "text", value: "Bear is Coming!!!!!" } ] }
+ ];
+ assert_cue_fragment(track.cues[0], children);
+
+ children = [
+ { type: "span", style: { className: "green" },
+ value: [ { type: "text", value: "I said Bear is coming!!!!" } ] }
+ ];
+ assert_cue_fragment(track.cues[1], children);
+
+ children = [
+ { type: "text", value: "I said " },
+ { type: "span", style: { className: "red uppercase" },
+ value: [ { type: "text", value: "Bear is coming now" } ] },
+ { type: "text", value: "!!!!" }
+ ];
+ assert_cue_fragment(track.cues[2], children);
+});
+
+check_cues_from_track("resources/class-bad.vtt", function(track) {
+ assert_equals(track.cues.length, 3);
+
+ var children = [
+ { type: "span", value: [ { type: "text", value: "Bear is Coming!!!!!" } ] },
+ { type: "text", value: "\nThe space signified an annotation start." }
+ ];
+ assert_cue_fragment(track.cues[0], children);
+
+ children = [
+ { type: "span", style: { className: "red&large" },
+ value: [ { type: "text", value: "I said Bear is coming!!!!" } ] },
+ { type: "text", value: "\nProbably should only allow characters that CSS allows in class names." }
+ ];
+ assert_cue_fragment(track.cues[1], children);
+
+ children = [
+ { type: "text", value: "I said " },
+ { type: "span", style: { className: "9red upper+case" },
+ value: [ { type: "text", value: "Bear is coming now" } ] },
+ { type: "text", value: "!!!!\nProbably should only allow characters that CSS allows in class names." }
+ ];
+ assert_cue_fragment(track.cues[2], children);
+});
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-identifiers.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-identifiers.html
new file mode 100644
index 0000000000..02b0a15187
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-identifiers.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Any text other than "-->" is recognized as optional cue identifier</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/cue-id.vtt", function(track) {
+ var expected = [
+ { id: "random_id", startTime: 0, endTime: 30.5, text: "Bear is Coming!!!!!" },
+ { id: "another random identifier", startTime: 31, endTime: 60.5, text: "I said Bear is coming!!!!" },
+ { id: "identifier--too", startTime: 61, endTime: 120.5, text: "I said Bear is coming now!!!!" },
+ { id: "identifier--too", startTime: 121, endTime: 180.5, text: "Duplicate identifier" }
+ ];
+
+ assert_cues_match(track.cues, expected);
+});
+
+check_cues_from_track("resources/cue-id-error.vtt", function(track) {
+ var expected = [
+ { id: "", startTime: 0, endTime: 30.5, text: "Bear is Coming!!!!!" },
+ { id: "", startTime: 31, endTime: 60.5, text: "I said Bear is coming!!!!" },
+ { id: "", startTime: 61, endTime: 1200.5, text: "I said Bear is coming now!!!!" }
+ ];
+
+ assert_cues_match(track.cues, expected);
+});
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-no-id.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-no-id.html
new file mode 100644
index 0000000000..b2f4b77083
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-no-id.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title>Empty cue identifiers, but having "-->" leads to discarded cue</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/cue-no-id.vtt", testTrack);
+check_cues_from_track("resources/cue-no-id-error.vtt", testTrack);
+
+function testTrack(track) {
+ var expected = [
+ { id: "", startTime: 0, endTime: 30.5, text: "Bear is Coming!!!!!" },
+ { id: "", startTime: 31, endTime: 60.5, text: "I said Bear is coming!!!!" },
+ { id: "", startTime: 61, endTime: 1200.5, text: "I said Bear is coming now!!!!" }
+ ];
+
+ assert_cues_match(track.cues, expected);
+}
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-recovery.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-recovery.html
new file mode 100644
index 0000000000..6a104916b7
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-recovery.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title>A cue is recovered when a line with a "-->" is encountered without blank line separator</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/cue-recovery-header.vtt", testTrack);
+check_cues_from_track("resources/cue-recovery-note.vtt", testTrack);
+check_cues_from_track("resources/cue-recovery-cuetext.vtt", testTrack);
+
+function testTrack(track) {
+ var expected = [
+ { startTime: 0, endTime: 1, text: "Valid cue 1" },
+ { startTime: 2, endTime: 3, text: "Valid cue 2" }
+ ];
+
+ assert_cues_match(track.cues, expected);
+}
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-size-align.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-size-align.html
new file mode 100644
index 0000000000..a1243a95e7
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-size-align.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Cue size and alignment from settings</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/cue-size-align.vtt", function(track) {
+ var expected = [
+ { size: 100, align: "start" },
+ { size: 10, align: "end" },
+ { size: 0, align: "center" }
+ ];
+
+ assert_cues_match(track.cues, expected);
+});
+
+check_cues_from_track("resources/cue-size-align-bad.vtt", function(track) {
+ var expected = [
+ { size: 100, align: "center" },
+ { size: 100, align: "end" },
+ { size: 100, align: "center" }
+ ];
+
+ assert_cues_match(track.cues, expected);
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-size.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-size.html
new file mode 100644
index 0000000000..d8e03edce7
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-size.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Cue size from settings</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/cue-size.vtt", function(track) {
+ var expected = [
+ { size: 100 },
+ { size: 10 },
+ { size: 0 }
+ ];
+
+ assert_cues_match(track.cues, expected);
+});
+
+check_cues_from_track("resources/cue-size-bad.vtt", function(track) {
+ var expected = [
+ { size: 100 },
+ { size: 100 },
+ { size: 100 }
+ ];
+
+ assert_cues_match(track.cues, expected);
+});
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-degenerate-cues.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-degenerate-cues.html
new file mode 100644
index 0000000000..8d2569993c
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-degenerate-cues.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>Degenerate cues without separating blank lines</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/degenerate-cues.vtt", function(track) {
+ var expected = [
+ { startTime: 0, endTime: 1, text: "" },
+ { startTime: 2, endTime: 3, text: "" },
+ { startTime: 4, endTime: 5, text: "" }
+ ];
+
+ assert_cues_match(track.cues, expected);
+});
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-empty-cue.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-empty-cue.html
new file mode 100644
index 0000000000..e1f5570250
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-empty-cue.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<title>Empty cues should not be discarded</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/empty-cue.vtt", function(track) {
+ assert_equals(track.cues.length, 3);
+});
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-entities.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-entities.html
new file mode 100644
index 0000000000..a5295795ef
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-entities.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<title>Entities in the cue text</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+var getCueAsHTMLContent = function(cue) {
+ return cue.getCueAsHTML().textContent;
+};
+
+check_cues_from_track("resources/entities.vtt", function(track) {
+ var expected = [
+ { innerHTML: getCueAsHTMLContent,
+ expected: "This cue has an ampersand & character." },
+ { innerHTML: getCueAsHTMLContent,
+ expected: "This cue has a less than < character." },
+ { innerHTML: getCueAsHTMLContent,
+ expected: "This cue has a greater than > character." },
+ { innerHTML: getCueAsHTMLContent,
+ expected: "This cue has a Left-to-Right Mark \u200e." },
+ { innerHTML: getCueAsHTMLContent,
+ expected: "This cue has a Right-to-Left Mark \u200f." },
+ { innerHTML: getCueAsHTMLContent,
+ expected: "This cue has a non-breaking space \u00a0." },
+ { innerHTML: getCueAsHTMLContent,
+ expected: "This & is parsed to the same as &." }
+ ];
+
+ assert_cues_html_content(track.cues, expected);
+});
+
+check_cues_from_track("resources/entities-wrong.vtt", function(track) {
+ var expected = [
+ { innerHTML: getCueAsHTMLContent,
+ expected: "This cue has a less than ", },
+ { innerHTML: getCueAsHTMLContent,
+ expected: "This cue has a greater than > character.\nSince it's not related to a < character,\nit's just interpreted as text.", }
+ ];
+
+ assert_cues_html_content(track.cues, expected);
+});
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-header-comment.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-header-comment.html
new file mode 100644
index 0000000000..f9b35576f3
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-header-comment.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<title>Optional comment area under the "WEBVTT" file header is properly ignored and also, default settings and styling are currently ignored (treated as faulty cues)</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/default-styles.vtt">
+ <track src="resources/metadata-area.vtt">
+</video>
+<script>
+async_test(function(t) {
+ var video = document.querySelector("video");
+
+ var trackElements = document.querySelectorAll("track");
+ for (var i = 0; i < video.textTracks.length; i++)
+ trackElements[i].onload = t.step_func(trackLoaded);
+
+ enableAllTextTracks(video.textTracks);
+
+ var numberOfTracksLoaded = 0;
+ function trackLoaded() {
+ numberOfTracksLoaded++;
+ if (numberOfTracksLoaded != 2)
+ return;
+
+ testTrack(0);
+ testTrack(1);
+ t.done();
+ }
+
+ function testTrack(index) {
+ var expected = [
+ {
+ id : "1",
+ startTime : 0,
+ endTime : 30.5,
+ text : "Bear is Coming!!!!!"
+ },
+ {
+ id : "2",
+ startTime : 31,
+ endTime : 1200.5,
+ text : "I said Bear is coming!!!!"
+ }
+ ];
+
+ assert_cues_equal(video.textTracks[index].cues, expected);
+ }
+});
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-interspersed-non-cue.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-interspersed-non-cue.html
new file mode 100644
index 0000000000..2287cc2830
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-interspersed-non-cue.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>An empty line after an identifier line discards the current cue and restarts the cue loop</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/interspersed-non-cue.vtt", function(track) {
+ var expected = [
+ { text: "First" },
+ { text: "Second" }
+ ];
+
+ assert_cues_match(track.cues, expected);
+});
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-line-position.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-line-position.html
new file mode 100644
index 0000000000..bea4acb917
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-line-position.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<title>Cue line position from settings</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/line-position.vtt">
+ <track src="resources/line-position-bad.vtt">
+</video>
+<script>
+async_test(function(t) {
+ var video = document.querySelector("video");
+
+ var trackElements = document.querySelectorAll("track");
+ assert_equals(trackElements.length, video.textTracks.length);
+ for (var i = 0; i < trackElements.length; i++)
+ trackElements[i].onload = t.step_func(trackLoaded);
+
+ enableAllTextTracks(video.textTracks);
+
+ var numberOfTracksLoaded = 0;
+ function trackLoaded() {
+ numberOfTracksLoaded++;
+ if (numberOfTracksLoaded != 2)
+ return;
+
+ testTrack(0);
+ testTrackError(1);
+ t.done();
+ }
+
+ function testTrack(index) {
+ var expected = [
+ { line : 0, snapToLines : false },
+ { line : 0, snapToLines : true },
+ { line : 50, snapToLines : false },
+ { line : 5, snapToLines : true },
+ { line : 100, snapToLines : false },
+ { line : -1, snapToLines : true },
+ { line : 500, snapToLines : true }
+ ];
+
+ assert_cues_match(video.textTracks[index].cues, expected);
+ }
+
+ function testTrackError(index) {
+ var expected = [
+ { line : "auto", snapToLines : true },
+ { line : "auto", snapToLines : true },
+ { line : "auto", snapToLines : true },
+ { line : "auto", snapToLines : true },
+ { line : "auto", snapToLines : true }
+ ];
+
+ assert_cues_match(video.textTracks[index].cues, expected);
+ }
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-magic-header.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-magic-header.html
new file mode 100644
index 0000000000..ff4637a8a5
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-magic-header.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<title>Magic file header "WEBVTT" leads to the file properly recognized as a WebVTT file</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/webvtt-file.vtt">
+ <track src="resources/webvtt-rubbish.vtt">
+ <track src="resources/no-webvtt.vtt">
+</video>
+<script>
+async_test(function(t) {
+ var video = document.querySelector("video");
+
+ var trackElements = document.querySelectorAll("track");
+ trackElements[0].onload = t.step_func(trackLoaded);
+ trackElements[1].onload = t.step_func(trackLoaded);
+ trackElements[2].onerror = t.step_func(trackLoaded);
+
+ enableAllTextTracks(video.textTracks);
+
+ var numberOfTracksLoaded = 0;
+ function trackLoaded() {
+ numberOfTracksLoaded++;
+ if (numberOfTracksLoaded != 3)
+ return;
+
+ testTrack(0);
+ testTrack(1);
+ testTrackError(2);
+ t.done();
+ }
+
+ function testTrack(index) {
+ var expected = [
+ {
+ id : "1",
+ startTime : 0,
+ endTime : 30.5,
+ text : "Bear is Coming!!!!!"
+ },
+ {
+ id : "2",
+ startTime : 31,
+ endTime : 1200.5,
+ text : "I said Bear is coming!!!!"
+ }
+ ];
+
+ assert_cues_equal(video.textTracks[index].cues, expected);
+ }
+
+ function testTrackError(index) {
+ assert_cues_equal(video.textTracks[index].cues, []);
+ }
+});
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-markup.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-markup.html
new file mode 100644
index 0000000000..ceb05dd450
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-markup.html
@@ -0,0 +1,90 @@
+<!DOCTYPE html>
+<title>Cues with &lt;b&gt;, &lt;i&gt;, &lt;u&gt;, &lt;rt&gt; and &lt;ruby&gt; tags</title>
+<meta name="timeout" content="long">
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/markup.vtt", function(track) {
+ assert_equals(track.cues.length, 4);
+
+ var children = [
+ { type: "text", value: "The following bear is bold:\n" },
+ { type: "b", value: [ { type: "text", value: "Bear" } ] },
+ { type: "text", value: " is Coming!!!!!" }
+ ];
+ assert_cue_fragment(track.cues[0], children);
+
+ children = [
+ { type: "text", value: "The following bear is in italics and has a class of \"larger\":\n" },
+ { type: "i", value: [ { type: "text", value: "Bear" } ] },
+ { type: "text", value: " is Coming!!!!!" }
+ ];
+
+ var fragment = createFragment(children);
+ fragment.querySelector("i").className = "larger";
+ assert_true(fragment.isEqualNode(track.cues[1].getCueAsHTML()));
+
+ children = [
+ { type: "text", value: "The following bear is underlined even though the element has a blank:\nI said " },
+ { type: "u", value: [ { type: "text", value: "Bear" } ] },
+ { type: "text", value: " is coming!!!!" }
+ ];
+ assert_cue_fragment(track.cues[2], children);
+
+ children = [
+ { type: "text", value: "The following bear is ruby annotated:\nI said " },
+ {
+ type: "ruby",
+ value: [
+ { type: "text", value: "Bear" },
+ {
+ type: "rt",
+ value: [ { type: "text", value: "bear with me" } ]
+ }
+ ]
+ },
+ { type: "text", value: " is coming!!!!" }
+ ];
+ assert_cue_fragment(track.cues[3], children);
+});
+
+check_cues_from_track("resources/markup-bad.vtt", function(track) {
+ assert_equals(track.cues.length, 4);
+
+ var children = [
+ { type: "text", value: "The following bear starts bold but end is broken:\n" },
+ {
+ type: "b",
+ value:
+ [
+ { type: "text", value: "Bear" },
+ { type: "text", value: " is Coming!!!!!" }
+ ]
+ }
+ ];
+ assert_cue_fragment(track.cues[0], children);
+
+ children = [
+ { type: "text", value: "The following bear is not in italics but the markup is removed:\n" },
+ { type: "text", value: "Bear" },
+ { type: "text", value: " is Coming!!!!!" }
+ ];
+ assert_cue_fragment(track.cues[1], children);
+
+ children = [
+ { type: "text", value: "The following bear is not underlined and markup is removed:\nI said " },
+ { type: "text", value : "Bear" },
+ { type: "text", value : " is coming!!!!" }
+ ];
+ assert_cue_fragment(track.cues[2], children);
+
+ children = [
+ { type: "text", value: "The following bear is not ruby annotated and markup is removed:\nI said " },
+ { type: "text", value: "Bear" },
+ { type: "text", value: "bear with me" },
+ { type: "text", value: " is coming!!!!" }
+ ];
+ assert_cue_fragment(track.cues[3], children);
+});
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-newlines.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-newlines.html
new file mode 100644
index 0000000000..4da7e6b1b9
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-newlines.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>A cue with no newline at eof is parsed properly</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/no-newline-at-eof.vtt" default>
+ <script>
+ async_test(function(t) {
+ var track = document.querySelector("track");
+
+ track.onload = t.step_func_done(function() {
+ var expected = [
+ {
+ id : "1",
+ startTime : 0,
+ endTime : 30.5,
+ text : "Bear is Coming!!!!!"
+ }
+ ];
+
+ assert_cues_equal(track.track.cues, expected);
+ });
+ });
+ </script>
+</video> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-no-timings.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-no-timings.html
new file mode 100644
index 0000000000..a39a2c37aa
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-no-timings.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<title>Cue without timings are ignored</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/no-timings.vtt" default>
+ <script>
+ async_test(function(t) {
+ var track = document.querySelector("track");
+
+ track.onload = t.step_func_done(function() {
+ assert_cues_equal(track.track.cues, []);
+ });
+ });
+ </script>
+</video> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-non-snap-to-lines-ref.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-non-snap-to-lines-ref.html
new file mode 100644
index 0000000000..137a9334f2
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-non-snap-to-lines-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Reference test for track-webvtt-non-snap-to-lines.html</title>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/media.js"></script>
+<style>
+.container {
+ position: relative;
+ display: inline-block;
+}
+.cue {
+ position: absolute;
+ top: 30px;
+ left: 0px;
+ font-family: sans-serif;
+ background: green;
+ color: rgba(255, 255, 255, 1);
+ font-size: 7.5px;
+}
+</style>
+<div class="container">
+ <video autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <script>
+ document.currentScript.parentNode.src = getVideoURI("/media/test");
+ </script>
+ </video>
+ <span class="cue">Bear is Coming!!!!!</span>
+</div>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-non-snap-to-lines.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-non-snap-to-lines.html
new file mode 100644
index 0000000000..ec350ff44d
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-non-snap-to-lines.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Position is not adjusted for non snap-to-lines cues</title>
+<link rel="match" href="track-webvtt-non-snap-to-lines-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/media.js"></script>
+<style>
+::cue {
+ background: green;
+}
+</style>
+<video autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();"></video>
+<script>
+var video = document.querySelector("video");
+var track = video.addTextTrack("captions");
+var cue = new VTTCue(0, 1, "Bear is Coming!!!!!");
+cue.snapToLines = false;
+cue.line = 20;
+cue.align = "left";
+track.addCue(cue);
+track.mode = "showing";
+video.src = getVideoURI("/media/test");
+</script>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-positioning.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-positioning.html
new file mode 100644
index 0000000000..d14a5768d3
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-positioning.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<title>Cue text position from settings</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/positioning.vtt", testTrack);
+check_cues_from_track("resources/positioning-ltr.vtt", testTrack);
+
+check_cues_from_track("resources/positioning-bad.vtt", function(track) {
+ var expected = [
+ { position: "auto" },
+ { position: "auto" },
+ { position: "auto" },
+ { position: "auto" },
+ { position: "auto" },
+ { position: "auto" },
+ { position: "auto" },
+ { position: "auto" }
+ ];
+
+ assert_cues_match(track.cues, expected);
+});
+
+function testTrack(track) {
+ var expected = [
+ { position: 0 },
+ { position: 50 },
+ { position: "auto" },
+ { position: 100 }
+ ];
+
+ assert_cues_match(track.cues, expected);
+}
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-settings.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-settings.html
new file mode 100644
index 0000000000..9ad98ffa1a
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-settings.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>WebVTT settings</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/settings.vtt", function(track) {
+ var expected = [
+ { line: 100, position: "auto", align: "start", vertical: "" },
+ { line: 15, position: 40, align: "center", vertical: "rl" },
+ { line: "auto", position: 10, align: "center", vertical: "" },
+ { line: 95, position: "auto", align: "end", vertical: "lr" }
+ ];
+
+ assert_cues_match(track.cues, expected);
+});
+
+check_cues_from_track("resources/settings-bad-separation.vtt", function(track) {
+ var expected = [
+ { line: 43, position: 10, align: "center", vertical: "" },
+ { line: "auto", position: 50, align: "end", vertical: "" },
+ { line: "auto", position: "auto", align: "center", vertical: "" },
+ { line: "auto", position: 90, align: "center", vertical: "lr" }
+ ];
+
+ assert_cues_match(track.cues, expected);
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timestamp.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timestamp.html
new file mode 100644
index 0000000000..e311f121f2
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timestamp.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<title>Cues with &lt;timestamps&gt; tags</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/timestamp.vtt", function(track) {
+ assert_equals(track.cues.length, 3);
+
+ // TODO(srirama.m): Timestamps are handled as ProcessingInstructions,
+ // but because ProcessingInstructions are used in XML and not HTML,
+ // they are ignored here. This should later be tested with oncuechange events.
+
+ var children = [ { type: "text", value: "This cue is painted on." } ];
+ assert_cue_fragment_as_textcontent(track.cues[0], children);
+
+ children = [ { type: "text", value: "I said Bear is coming!!!!" } ];
+ assert_cue_fragment_as_textcontent(track.cues[1], children);
+
+ children = [ { type: "text", value: "I said Bear is coming now!!!!" } ];
+ assert_cue_fragment_as_textcontent(track.cues[2], children);
+});
+
+check_cues_from_track("resources/timestamp-bad.vtt", function(track) {
+ assert_equals(track.cues.length, 3);
+
+ var children = [ { type: "text", value: "This cue is painted on.\nBut since the last two timestamps are out of order, they are ignored." } ];
+ assert_cue_fragment_as_textcontent(track.cues[0], children);
+
+ children = [ { type: "text", value: "I said Bear is coming!!!!\nAll of these timestamps are before the start of the cue, so get ignored." } ];
+ assert_cue_fragment_as_textcontent(track.cues[1], children);
+
+ children = [ { type: "text", value: "I said Bear is coming now!!!!\nAll of these timestamps are after the end of the cue, so get ignored." } ];
+ assert_cue_fragment_as_textcontent(track.cues[2], children);
+});
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-hour.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-hour.html
new file mode 100644
index 0000000000..c03e182c79
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-hour.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<title>Cue timings and various syntax errors in timings, with hours</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/timings-hour.vtt">
+ <track src="resources/timings-hour-error.vtt">
+</video>
+<script>
+async_test(function(t) {
+ var video = document.querySelector("video");
+
+ var trackElements = document.querySelectorAll("track");
+ for (var i = 0; i < video.textTracks.length; i++)
+ trackElements[i].onload = t.step_func(trackLoaded);
+
+ enableAllTextTracks(video.textTracks);
+
+ var numberOfTracksLoaded = 0;
+ function trackLoaded() {
+ numberOfTracksLoaded++;
+ if (numberOfTracksLoaded != 2)
+ return;
+
+ testTrack0();
+ testTrack1();
+ t.done();
+ }
+
+ function testTrack0() {
+ var expected = [
+ {
+ id : "1",
+ startTime : 0,
+ endTime : 30.5,
+ text : "Bear is Coming!!!!!"
+ },
+ {
+ id : "2",
+ startTime : 31,
+ endTime : 60.5,
+ text : "I said Bear is coming!!!!"
+ },
+ {
+ id : "3",
+ startTime : 61,
+ endTime : 361200.5,
+ text : "I said Bear is coming now!!!!"
+ }
+ ];
+
+ assert_cues_equal(video.textTracks[0].cues, expected);
+ }
+
+ function testTrack1() {
+ // Test that all the cues are ignored.
+ assert_cues_equal(video.textTracks[1].cues, []);
+ }
+});
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-no-hours.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-no-hours.html
new file mode 100644
index 0000000000..e81ae03cc2
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-no-hours.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<title>Cue timings and various syntax errors in timings, without hours</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/timings-no-hour.vtt">
+ <track src="resources/timings-no-hour-errors.vtt">
+</video>
+<script>
+async_test(function(t) {
+ var video = document.querySelector("video");
+
+ var trackElements = document.querySelectorAll("track");
+ for (var i = 0; i < video.textTracks.length; i++)
+ trackElements[i].onload = t.step_func(trackLoaded);
+
+ enableAllTextTracks(video.textTracks);
+
+ var numberOfTracksLoaded = 0;
+ function trackLoaded() {
+ numberOfTracksLoaded++;
+ if (numberOfTracksLoaded != 2)
+ return;
+
+ testTrack0();
+ testTrack1();
+ t.done();
+ }
+
+ function testTrack0() {
+ var expected = [
+ {
+ id : "1",
+ startTime : 0,
+ endTime : 30.5,
+ text : "Bear is Coming!!!!!"
+ },
+ {
+ id : "2",
+ startTime : 31,
+ endTime : 60.5,
+ text : "I said Bear is coming!!!!"
+ },
+ {
+ id : "3",
+ startTime : 61,
+ endTime : 120.5,
+ text : "I said Bear is coming now!!!!"
+ },
+ {
+ id : "4",
+ startTime : 121,
+ endTime : 180.5,
+ text : "tab separators"
+ }
+ ];
+
+ assert_cues_equal(video.textTracks[0].cues, expected);
+ }
+
+ function testTrack1() {
+ // Test that all the cues are ignored.
+ assert_cues_equal(video.textTracks[1].cues, []);
+ }
+});
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-whitespace.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-whitespace.html
new file mode 100644
index 0000000000..db1346d23a
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-whitespace.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>"Skip whitespace" step around cue-timings separator</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/timings-whitespace.vtt", function(track) {
+ var expected = [
+ { id: "1", startTime: 0.1, endTime: 1.5, text: "Single U+0020 SPACE left of cue-timings separator" },
+ { id: "2", startTime: 0.1, endTime: 1.5, text: "Single U+0020 SPACE right of cue-timings separator" },
+ { id: "3", startTime: 0.1, endTime: 1.5, text: "Single U+0009 TAB left of cue-timings separator" },
+ { id: "4", startTime: 0.1, endTime: 1.5, text: "Single U+0009 TAB right of cue-timings separator" },
+ { id: "5", startTime: 0.1, endTime: 1.5, text: "Single U+000C FORM FEED left of cue-timings separator" },
+ { id: "6", startTime: 0.1, endTime: 1.5, text: "Single U+000C FORM FEED right of cue-timings separator" },
+ { id: "7", startTime: 0.1, endTime: 1.5, text: "Several U+0020 SPACE left of cue-timings separator" },
+ { id: "8", startTime: 0.1, endTime: 1.5, text: "Several U+0020 SPACE right of cue-timings separator" },
+ { id: "9", startTime: 0.1, endTime: 1.5, text: "Several U+0009 TAB left of cue-timings separator" },
+ { id: "10", startTime: 0.1, endTime: 1.5, text: "Several U+0009 TAB right of cue-timings separator" },
+ { id: "11", startTime: 0.1, endTime: 1.5, text: "Several U+000C FORM FEED left of cue-timings separator" },
+ { id: "12", startTime: 0.1, endTime: 1.5, text: "Several U+000C FORM FEED right of cue-timings separator" }
+ ];
+
+ assert_cues_match(track.cues, expected);
+});
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-two-cue-layout-after-first-end-ref.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-two-cue-layout-after-first-end-ref.html
new file mode 100644
index 0000000000..1c8f751c2c
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-two-cue-layout-after-first-end-ref.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT two-cue layout after the first cue has ended (reference)</title>
+<script src="/common/reftest-wait.js"></script>
+<video style="border:1px solid gray">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+</video>
+<script>
+// Add a single cue at line -2, where it would be if there was a first
+// cue at line -1.
+var video = document.querySelector("video");
+var track = video.addTextTrack("captions");
+var cue = new VTTCue(0, 3, "cue 2");
+cue.line = -2;
+track.addCue(cue);
+track.mode = "showing";
+video.play();
+video.onplaying = function() {
+ video.onplaying=null;
+ video.pause();
+ takeScreenshot();
+};
+</script>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-two-cue-layout-after-first-end.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-two-cue-layout-after-first-end.html
new file mode 100644
index 0000000000..df816ffe2b
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-two-cue-layout-after-first-end.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT two-cue layout after the first cue has ended</title>
+<link rel="match" href="track-webvtt-two-cue-layout-after-first-end-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<video style="border:1px solid gray">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+</video>
+<script>
+// Add two cues, where the first cue ends before the second.
+var video = document.querySelector("video");
+var track = video.addTextTrack("captions");
+let cue1 = new VTTCue(-1, 1, "cue 1");
+track.addCue(cue1);
+// As video's duration is 10s, it ensures that this cue would always be displayed.
+track.addCue(new VTTCue(0, 10, "cue 2"));
+track.mode = "showing";
+video.play();
+cue1.onexit = () => {
+ cue1.onexit = null;
+ video.pause();
+ takeScreenshot();
+};
+</script>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-unsupported-markup.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-unsupported-markup.html
new file mode 100644
index 0000000000..ed3107f89b
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-unsupported-markup.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<title>Unsupported markup is properly ignored</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+var getCueAsHTMLContent = function(cue) {
+ return cue.getCueAsHTML().textContent;
+};
+
+check_cues_from_track("resources/unsupported-markup.vtt", function(track) {
+ var expected = [
+ {
+ innerHTML: getCueAsHTMLContent,
+ expected: "Bear is Coming!!!!!\nAnd what kind of a bear it is - just have look."
+ },
+ {
+ innerHTML: getCueAsHTMLContent,
+ expected: "\n I said Bear is coming!!!!\n I said Bear is still coming!!!!\n",
+ },
+ {
+ innerHTML: getCueAsHTMLContent,
+ expected: "\n I said Bear is coming now!!!!\n \n \n",
+ }
+ ];
+
+ assert_cues_html_content(track.cues, expected);
+
+ var expected_text = [
+ { text: "<h1>Bear is Coming!!!!!</h1>\n<p>And what kind of a bear it is - just have <a href=\"webpage.html\">look</a>.</p>" },
+ { text: "<ul>\n <li>I said Bear is coming!!!!</li>\n <li>I said Bear is still coming!!!!</li>\n</ul>" },
+ { text: "<ol>\n <li>I said Bear is coming now!!!!</li>\n <li><img src=\"bear.png\" alt=\"mighty bear\"></li>\n <li><video src=\"bear_ad.webm\" controls></video></li>\n</ol>" }
+ ];
+
+ assert_cues_match(track.cues, expected_text);
+});
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-utf8.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-utf8.html
new file mode 100644
index 0000000000..eb44c85ba8
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-utf8.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<title>UTF-8 encoded characters are recognized properly and different encodings (iconv) are not recognized as a WebVTT file</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/utf8.vtt">
+ <track src="resources/iso2022jp3.vtt">
+</video>
+<script>
+async_test(function(t) {
+ var video = document.querySelector("video");
+
+ var trackElements = document.querySelectorAll("track");
+ for (var i = 0; i < video.textTracks.length; i++)
+ trackElements[i].onload = t.step_func(trackLoaded);
+
+ enableAllTextTracks(video.textTracks);
+
+ var numberOfTracksLoaded = 0;
+ function trackLoaded() {
+ numberOfTracksLoaded++;
+ if (numberOfTracksLoaded != 2)
+ return;
+
+ testTrack0();
+ testTrack1();
+ t.done();
+ }
+
+ function testTrack0() {
+ var expected = [
+ {
+ id : "1",
+ startTime : 0,
+ endTime : 30.5,
+ text : "景気判断"
+ },
+ {
+ id : "2",
+ startTime : 31,
+ endTime : 1200.5,
+ text : "電力不足"
+ }
+ ];
+
+ var cues = video.textTracks[0].cues;
+ assert_equals(cues.length, 2);
+ assert_cues_equal(cues, expected);
+ }
+
+ function testTrack1() {
+ assert_equals(video.textTracks[1].cues.length, 2);
+ }
+});
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-valign.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-valign.html
new file mode 100644
index 0000000000..ace0760740
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-valign.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Cue vertical alignment (direction) from settings</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/valign.vtt", testTrack);
+check_cues_from_track("resources/valign-ltr.vtt", testTrack);
+check_cues_from_track("resources/valign-bad.vtt", function(track) {
+ var expected = [
+ { vertical: "" },
+ { vertical: "" },
+ { vertical: "" }
+ ];
+
+ assert_cues_match(track.cues, expected);
+});
+
+function testTrack(track) {
+ var expected = [
+ { vertical: "rl", align: "center", position: "auto" },
+ { vertical: "lr", align: "center", position: "auto" },
+ { vertical: "rl", align: "start", position: 0 }
+ ];
+
+ assert_cues_match(track.cues, expected);
+}
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-voice.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-voice.html
new file mode 100644
index 0000000000..5df8b4057a
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-voice.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<title>Cues with voice markup &lt;v&gt;</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/voice.vtt", function(track) {
+ assert_equals(track.cues.length, 3);
+
+ var children = [
+ { type: "span", style: { className: "blue", title: "Speaker" },
+ value: [ { type: "text", value: "Bear is Coming!!!!!" } ] },
+ { type: "text", value: "\nText span with a class and an annotation." }
+ ];
+ assert_cue_fragment(track.cues[0], children);
+
+ children = [
+ { type: "span", style: { title: "Doe Hunter" },
+ value: [ { type: "text", value: "I said Bear is coming!!!!" } ] }
+ ];
+ assert_cue_fragment(track.cues[1], children);
+
+ children = [
+ { type: "text", value: "I said " },
+ { type: "span", style: { className: "blue", title: "Speaker" },
+ value: [ { type: "text", value: "Bear is coming now" } ] },
+ { type: "text", value: "!!!!" }
+ ];
+ assert_cue_fragment(track.cues[2], children);
+});
+
+check_cues_from_track("resources/voice-bad.vtt", function(track) {
+ assert_equals(track.cues.length, 3);
+
+ var children = [
+ { type: "text", value: "Bear is Coming!!!!!" },
+ { type: "text", value: "\nThis is two annotations for an empty tag." }
+ ];
+ assert_cue_fragment(track.cues[0], children);
+
+ children = [
+ { type: "text", value: "I said Bear is coming!!!!" },
+ { type: "text", value: "\nThis does not parse as a voice tag." }
+ ];
+ assert_cue_fragment(track.cues[1], children);
+
+ children = [
+ { type: "text", value: "I said " },
+ { type: "text", value: "Bear is coming now" },
+ { type: "text", value: "!!!!\nThis does not parse as a voice tag." }
+ ];
+ assert_cue_fragment(track.cues[2], children);
+});
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/vtt-cue-float-precision.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/vtt-cue-float-precision.html
new file mode 100644
index 0000000000..9cb5824279
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/vtt-cue-float-precision.html
@@ -0,0 +1,28 @@
+<!doctype html>
+<title>Float precision of VTTCue attributes line, position and size</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+ var cue = new VTTCue(0, 1, 'text');
+
+ // Assign a value which is exactly representable as double but not float.
+ var doubleValue = 1.000000000000004;
+ cue.line = doubleValue;
+ assert_equals(cue.line, doubleValue);
+ cue.position = doubleValue;
+ assert_equals(cue.position, doubleValue);
+ cue.size = doubleValue;
+ assert_equals(cue.size, doubleValue);
+
+ // Assign a value which is exactly representable as float but is non-integral.
+ var floatValue = 1.5;
+ cue.line = floatValue;
+ assert_equals(cue.line, floatValue);
+ cue.position = floatValue;
+ assert_equals(cue.position, floatValue);
+ cue.size = floatValue;
+ assert_equals(cue.size, floatValue);
+}, document.title+', stored as floats');
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/user-interface/muted.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/user-interface/muted.html
new file mode 100644
index 0000000000..eb6d2ac688
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/user-interface/muted.html
@@ -0,0 +1,169 @@
+<!doctype html>
+<title>muted</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<style>video { display: none; }</style>
+<div id=log></div>
+
+<script>
+function test_setting(e, muted, hasAttribute) {
+ assert_equals(e.muted, muted);
+ assert_equals(e.hasAttribute('muted'), hasAttribute);
+
+ e.muted = !e.muted;
+ assert_equals(e.muted, !muted);
+ assert_equals(e.hasAttribute('muted'), hasAttribute);
+
+ e.muted = !e.muted;
+ assert_equals(e.muted, muted);
+ assert_equals(e.hasAttribute('muted'), hasAttribute);
+}
+</script>
+
+<!-- These tests are inside <audio>/<video> so that the steps for updating the
+ muted IDL attribute cannot be delayed until the end tag is parsed. -->
+
+<audio id=a1>
+<script>
+var a1 = document.getElementById('a1');
+
+test(function() {
+ assert_false(a1.muted);
+}, 'getting audio.muted (parser-created)');
+
+test(function() {
+ test_setting(a1, false, false);
+}, 'setting audio.muted (parser-created)');
+</script>
+</audio>
+
+<audio id=a2 muted>
+<script>
+var a2 = document.getElementById('a2');
+
+test(function() {
+ assert_true(a2.muted);
+}, 'getting audio.muted with muted="" (parser-created)');
+
+test(function() {
+ test_setting(a2, true, true);
+}, 'setting audio.muted with muted="" (parser-created)');
+</script>
+</audio>
+
+<video id=v1>
+<script>
+var v1 = document.getElementById('v1');
+
+test(function() {
+ assert_false(v1.muted);
+}, 'getting video.muted (parser-created)');
+
+test(function() {
+ test_setting(v1, false, false);
+}, 'setting video.muted (parser-created)');
+</script>
+</video>
+
+<video id=v2 muted>
+<script>
+var v2 = document.getElementById('v2');
+
+test(function() {
+ assert_true(v2.muted);
+}, 'getting video.muted with muted="" (parser-created)');
+
+test(function() {
+ test_setting(v2, true, true);
+}, 'setting video.muted with muted="" (parser-created)');
+</script>
+</video>
+
+<!-- Negative test to ensure that the load algorithm does not update the
+ muted IDL attribute to match the content attribute. -->
+
+<video id=v3 muted></video>
+<script>
+async_test(function(t) {
+ var v = document.getElementById('v3');
+ assert_true(v.muted);
+ v.muted = false;
+ v.src = 'data:,'; // invokes load()
+ v.addEventListener('error', t.step_func(function() {
+ assert_false(v.muted);
+ t.done();
+ }));
+}, 'getting video.muted with muted="" after load (parser-created)');
+</script>
+
+<script>
+['audio', 'video'].forEach(function(tagName) {
+ test(function() {
+ var m = document.createElement(tagName);
+ assert_false(m.muted);
+ }, 'getting ' + tagName + '.muted (script-created)');
+
+ test(function() {
+ var m = document.createElement(tagName);
+ test_setting(m, false, false);
+ }, 'setting ' + tagName + '.muted (script-created)');
+
+ test(function() {
+ var m = document.createElement(tagName);
+ m.setAttribute('muted', '');
+ assert_false(m.muted);
+ }, 'getting ' + tagName + '.muted with muted="" (script-created)');
+
+ test(function() {
+ var m = document.createElement(tagName);
+ m.setAttribute('muted', '');
+ test_setting(m, false, true);
+ }, 'setting ' + tagName + '.muted with muted="" (script-created)');
+
+ // Spec bug: https://www.w3.org/Bugs/Public/show_bug.cgi?id=25153
+ /*
+ test(function() {
+ var m = document.createElement(tagName);
+ m.setAttribute('muted', '');
+ m = m.cloneNode(false);
+ assert_true(m.hasAttribute('muted'));
+ assert_false(m.muted);
+ }, 'getting ' + tagName + '.muted with muted="" (cloneNode-created)');
+ */
+
+ test(function() {
+ var div = document.createElement('div');
+ div.innerHTML = '<' + tagName + ' muted>';
+ m = div.firstChild;
+ assert_true(m.hasAttribute('muted'));
+ assert_true(m.muted);
+ }, 'getting ' + tagName + '.muted with muted="" (innerHTML-created)');
+
+ test(function() {
+ var id = tagName;
+ assert_equals(document.getElementById(id), null);
+ document.write('<' + tagName + ' id=' + id + ' muted>');
+ m = document.getElementById(id);
+ assert_true(m.hasAttribute('muted'));
+ assert_true(m.muted);
+ }, 'getting ' + tagName + '.muted with muted="" (document.write-created)');
+
+ test(function() {
+ var m = document.createElement(tagName);
+ m.setAttribute('muted', '');
+
+ var c = m.cloneNode(true);
+ assert_true(c.muted);
+ }, 'cloning ' + tagName + ' propagates muted (script-created)');
+
+ test(function() {
+ var div = document.createElement('div');
+ div.innerHTML = '<' + tagName + ' muted>';
+ m = div.firstChild;
+
+ var c = m.cloneNode(true);
+ assert_true(c.muted);
+ }, 'cloning ' + tagName + ' propagates muted (innerHTML-created)');
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/video_controls_present-manual.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/video_controls_present-manual.html
new file mode 100644
index 0000000000..8e44951d7a
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/video_controls_present-manual.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Video Test: video_controls_present.html</title>
+ <link rel="author" title="Intel" href="http://www.intel.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-media-controls" />
+ <meta name="flags" content="" />
+ <meta name="assert" content="Check if the controls attribute is present in the video element that expecting the user agent exposes a controller user interface" />
+ </head>
+ <body>
+ <p>Test passes if a controller user interface appears below and the text 'The user agent doesn't support media element.' does not appear anywhere on this page</p>
+ <video id="m" controls>The user agent doesn't support media element.</video>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/video_loop_base.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/video_loop_base.html
new file mode 100644
index 0000000000..9b5d69b31a
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/video_loop_base.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Video Test: video_loop_base</title>
+ <link rel="author" title="Intel" href="http://www.intel.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-media-loop" />
+ <meta name="flags" content="" />
+ <meta name="assert" content="Check if video.loop is set to true that expecting the seeking event is fired more than once" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <video id="m" controls>The user agent doesn't support media element.</video>
+ <script type="text/javascript">
+ var media = document.getElementById("m");
+ var name = document.getElementsByName("assert")[0].content;
+ var t = async_test(name);
+ var looped = false;
+
+ function startTest() {
+ if (looped) {
+ t.step(function() {
+ assert_true(true, "looped");
+ });
+ t.done();
+ media.pause();
+ }
+
+ looped = true;
+ }
+
+ media.addEventListener("seeking", startTest, false);
+ media.loop = true;
+ media.src = getVideoURI("/media/2x2-green") + "?" + new Date() + Math.random();
+ media.play();
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/video_muted_overriding_volume-manual.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/video_muted_overriding_volume-manual.html
new file mode 100644
index 0000000000..6d770666cc
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/video_muted_overriding_volume-manual.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Video Test: video_muted_overriding_volume</title>
+ <link rel="author" title="Intel" href="http://www.intel.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-media-muted" />
+ <meta name="flags" content="" />
+ <meta name="assert" content="Check if the muted attribute is present in the video element with volume is set to loudest that expecting the user hears no sound" />
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p>Test passes if the video is playing without sound output and the text 'The user agent doesn't support media element.' does not appear anywhere on this page</p>
+ <video id="m" controls muted>The user agent doesn't support media element.</video>
+ <script type="text/javascript">
+ var media = document.getElementById("m");
+ media.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+ media.volume = 1.0;
+ media.play();
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/video_muted_present-manual.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/video_muted_present-manual.html
new file mode 100644
index 0000000000..bc80827775
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/video_muted_present-manual.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Video Test: video_muted_present</title>
+ <link rel="author" title="Intel" href="http://www.intel.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-media-muted" />
+ <meta name="flags" content="" />
+ <meta name="assert" content="Check if the muted attribute is present in the video element that expecting the user hears no sound" />
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p>Test passes if the video is playing without sound output and the text 'The user agent doesn't support media element.' does not appear anywhere on this page</p>
+ <video id="m" controls muted>The user agent doesn't support media element.</video>
+ <script type="text/javascript">
+ var media = document.getElementById("m");
+ media.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+ media.play();
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/video_volume_check.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/video_volume_check.html
new file mode 100644
index 0000000000..1a45358a76
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/video_volume_check.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Video Test: video_volume_check</title>
+ <link rel="author" title="Intel" href="http://www.intel.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-media-volume" />
+ <meta name="flags" content="" />
+ <meta name="assert" content="Check that video.volume returns the value of the muted content attribute" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <video id="m">The user agent doesn't support media element.</video>
+ <script type="text/javascript">
+ var media = document.getElementById("m");
+ var VOLUME = {
+ 'SILENT' : 0.0,
+ 'NORMAL' : 0.5,
+ 'LOUDEST' : 1.0,
+ 'LOWER' : -1.1,
+ 'UPPER' : 1.1,
+ };
+
+ test(function() {
+ assert_false(media.volume < VOLUME.SILENT || media.volume > VOLUME.LOUDEST, "media.volume outside the range 0.0 to 1.0 inclusive");
+ }, "Check if the intial value of the video.volume is in the range 0.0 to 1.0 inclusive");
+
+ function volume_setting(vol, name)
+ {
+ if (vol < VOLUME.SILENT || vol > VOLUME.LOUDEST) {
+ try {
+ media.volume = vol;
+ test(function() {
+ assert_true(false, "media.volume setting exception");
+ }, name);
+ } catch(e) {
+ test(function() {
+ // 1 should be e.IndexSizeError or e.INDEX_SIZE_ERR in previous spec
+ assert_equals(e.code, 1, "media.volume setting exception");
+ }, name);
+ }
+ } else {
+ media.volume = vol;
+ test(function() {
+ assert_equals(media.volume, vol, "media.volume new value");
+ }, name);
+ }
+ }
+
+ volume_setting(VOLUME.NORMAL, "Check if video.volume is able to set to new value in the range 0.0 to 1.0");
+ volume_setting(VOLUME.SILENT, "Check if media.volume is able to set to new value 0.0 as silent");
+ volume_setting(VOLUME.LOUDEST, "Check if media.volume is able to set to new value 1.0 as loudest");
+ volume_setting(VOLUME.LOWER, "Check if media.volume is set to new value less than 0.0 that expecting an IndexSizeError exception is to be thrown");
+ volume_setting(VOLUME.UPPER, "Check if video.volume is set to new value greater than 1.0 that expecting an IndexSizeError exception is to be thrown");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/video_volume_loudest-manual.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/video_volume_loudest-manual.html
new file mode 100644
index 0000000000..7475781201
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/video_volume_loudest-manual.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Video Test: video_volume_loudest</title>
+ <link rel="author" title="Intel" href="http://www.intel.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-media-volume" />
+ <meta name="flags" content="" />
+ <meta name="assert" content="Check if the volume attribute is set to 1.0 as loudest in the video element that expecting the user hears sound loudly" />
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p>Test passes if the video is playing with sound heard and the text 'The user agent doesn't support media element.' does not appear anywhere on this page</p>
+ <video id="m" controls>The user agent doesn't support media element.</video>
+ <script type="text/javascript">
+ var media = document.getElementById("m");
+ media.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+ media.volume = 1.0;
+ media.play();
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/video_volume_silent-manual.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/video_volume_silent-manual.html
new file mode 100644
index 0000000000..1768dd4d4c
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/video_volume_silent-manual.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Video Test: video_volume_silent</title>
+ <link rel="author" title="Intel" href="http://www.intel.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-media-volume" />
+ <meta name="flags" content="" />
+ <meta name="assert" content="Check if the volume attribute is set to 0.0 as silent in the video element that expecting the user hears no sound" />
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p>Test passes if the video is playing without sound heard and the text 'The user agent doesn't support media element.' does not appear anywhere on this page</p>
+ <video id="m" controls volume=0.0>The user agent doesn't support media element.</video>
+ <script type="text/javascript">
+ var media = document.getElementById("m");
+ media.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+ media.volume = 0.0;
+ media.play();
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/volume_nonfinite.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/volume_nonfinite.html
new file mode 100644
index 0000000000..fce50c2e20
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/volume_nonfinite.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Setting HTMLMediaElement.volume to non-finite numbers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+["audio", "video"].forEach(function(aElement) {
+ [NaN, Infinity, -Infinity].forEach(function(aValue) {
+ test(function() {
+ var el = document.createElement(aElement);
+ assert_throws_js(TypeError, function() {
+ el.volume = aValue;
+ });
+ }, "Setting " + aElement + ".volume to " + String(aValue) + " should throw a TypeError");
+ });
+});
+</script>