@gcorevideo/player 2.22.30 → 2.22.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/assets/media-control/container.scss +2 -3
  2. package/assets/poster/poster.ejs +3 -1
  3. package/assets/poster/poster.scss +3 -3
  4. package/assets/style/main.scss +1 -1
  5. package/dist/core.js +1 -1
  6. package/dist/index.css +670 -671
  7. package/dist/index.js +68 -98
  8. package/dist/player.d.ts +63 -33
  9. package/docs/api/{player.seektime.bindevents.md → player.clapprstats.clearmetrics.md} +3 -3
  10. package/docs/api/player.clapprstats.md +14 -0
  11. package/docs/api/player.extendedevents.md +14 -0
  12. package/docs/api/player.md +13 -2
  13. package/docs/api/player.seektime.attributes.md +0 -1
  14. package/docs/api/player.seektime.md +6 -197
  15. package/docs/api/{player.seektime.render.md → player.seektimesettings.md} +7 -7
  16. package/docs/api/player.skiptime.md +3 -184
  17. package/lib/plugins/poster/Poster.d.ts +24 -14
  18. package/lib/plugins/poster/Poster.d.ts.map +1 -1
  19. package/lib/plugins/poster/Poster.js +67 -97
  20. package/lib/testUtils.d.ts +13 -39
  21. package/lib/testUtils.d.ts.map +1 -1
  22. package/lib/testUtils.js +14 -65
  23. package/package.json +1 -1
  24. package/src/plugins/media-control/__tests__/__snapshots__/MediaControl.test.ts.snap +1 -1
  25. package/src/plugins/poster/Poster.ts +91 -110
  26. package/src/plugins/poster/__tests__/Poster.test.ts +119 -0
  27. package/src/plugins/poster/__tests__/__snapshots__/Poster.test.ts.snap +8 -0
  28. package/src/plugins/source-controller/__tests__/SourceController.test.ts +1 -2
  29. package/src/testUtils.ts +14 -86
  30. package/temp/player.api.json +295 -829
  31. package/tsconfig.tsbuildinfo +1 -1
  32. package/docs/api/player.seektime.durationshown.md +0 -14
  33. package/docs/api/player.seektime.getseektime.md +0 -20
  34. package/docs/api/player.seektime.islivestreamwithdvr.md +0 -14
  35. package/docs/api/player.seektime.mediacontrol.md +0 -14
  36. package/docs/api/player.seektime.mediacontrolcontainer.md +0 -14
  37. package/docs/api/player.seektime.shouldbevisible.md +0 -18
  38. package/docs/api/player.seektime.template.md +0 -14
  39. package/docs/api/player.seektime.update.md +0 -18
  40. package/docs/api/player.skiptime.attributes.md +0 -17
  41. package/docs/api/player.skiptime.bindevents.md +0 -18
  42. package/docs/api/player.skiptime.events.md +0 -18
  43. package/docs/api/player.skiptime.handlerewindclicks.md +0 -18
  44. package/docs/api/player.skiptime.render.md +0 -18
  45. package/docs/api/player.skiptime.setback.md +0 -18
  46. package/docs/api/player.skiptime.setforward.md +0 -18
  47. package/docs/api/player.skiptime.setmidclick.md +0 -18
  48. package/docs/api/player.skiptime.template.md +0 -14
  49. package/docs/api/player.skiptime.togglefullscreen.md +0 -18
@@ -8,7 +8,6 @@ import {
8
8
  PlayerError,
9
9
  UIContainerPlugin,
10
10
  template,
11
- $,
12
11
  } from '@clappr/core'
13
12
  import { trace } from '@gcorevideo/utils'
14
13
 
@@ -20,25 +19,38 @@ import posterHTML from '../../../assets/poster/poster.ejs'
20
19
  import playIcon from '../../../assets/icons/new/play.svg'
21
20
  import { PlaybackError } from '../../playback.types.js'
22
21
 
22
+ export type PosterPluginSettings = {
23
+ /**
24
+ * Custom CSS background
25
+ */
26
+ custom?: string
27
+ /**
28
+ * Whether to show the poster image when the playback is noop (i.e., when there is no appropriate video playback engine for current media sources set or the media sources are not set at all)
29
+ */
30
+ showForNoOp?: boolean
31
+ /**
32
+ * Poster image URL
33
+ */
34
+ url?: string
35
+ /**
36
+ * Whether to show the poster after playback has ended @default true
37
+ */
38
+ showOnVideoEnd?: boolean
39
+ }
40
+
23
41
  const T = 'plugins.poster'
24
42
 
25
43
  /**
26
44
  * `PLUGIN` that displays a poster image in the background and a big play button on top when playback is stopped
27
45
  * @beta
28
46
  * @remarks
29
- * When the playback is stopped, media control UI is disabled.
47
+ * When the playback is stopped or not yet started, the media control UI is disabled and hidden.
48
+ * Media control gets activated once the metadata is loaded after playback is initiated.
49
+ * This plugin displays a big play button on top of the poster image to allow user to start playback.
30
50
  * Note that the poster image, if specified via the player config, will be used to update video element's poster attribute by the
31
51
  * HTML5-video-based playback module.
32
52
  *
33
- * Configuration options:
34
- *
35
- * - `poster.custom` - custom CSS background
36
- *
37
- * - `poster.showForNoOp` - whether to show the poster when the playback is not started
38
- *
39
- * - `poster.url` - the URL of the poster image
40
- *
41
- * - `poster.showOnVideoEnd` - whether to show the poster when the playback is ended
53
+ * Configuration options - {@link PosterPluginSettings}
42
54
  *
43
55
  * @example
44
56
  * ```ts
@@ -56,14 +68,12 @@ export class Poster extends UIContainerPlugin {
56
68
 
57
69
  private hasFatalError = false
58
70
 
59
- private hasStartedPlaying = false
71
+ private playing = false
60
72
 
61
73
  private playRequested = false
62
74
 
63
75
  private $playButton: ZeptoResult | null = null
64
76
 
65
- private $playWrapper: ZeptoResult | null = null
66
-
67
77
  /**
68
78
  * @internal
69
79
  */
@@ -87,18 +97,20 @@ export class Poster extends UIContainerPlugin {
87
97
  const showForNoOp = !!this.options.poster?.showForNoOp
88
98
  return (
89
99
  this.container.playback.name !== 'html_img' &&
90
- (this.container.playback.getPlaybackType() !== Playback.NO_OP ||
91
- showForNoOp)
100
+ (!this.isNoOp || showForNoOp)
92
101
  )
93
102
  }
94
103
 
104
+ private get isNoOp() {
105
+ return this.container.playback.getPlaybackType() === Playback.NO_OP
106
+ }
107
+
95
108
  /**
96
109
  * @internal
97
110
  */
98
111
  override get attributes() {
99
112
  return {
100
113
  class: 'player-poster',
101
- 'data-poster': '',
102
114
  }
103
115
  }
104
116
 
@@ -111,10 +123,6 @@ export class Poster extends UIContainerPlugin {
111
123
  }
112
124
  }
113
125
 
114
- private get showOnVideoEnd() {
115
- return this.options.poster?.showOnVideoEnd !== false
116
- }
117
-
118
126
  /**
119
127
  * @internal
120
128
  */
@@ -127,20 +135,27 @@ export class Poster extends UIContainerPlugin {
127
135
  Events.CONTAINER_STATE_BUFFERFULL,
128
136
  this.update,
129
137
  )
130
- this.listenTo(this.container, Events.CONTAINER_OPTIONS_CHANGE, this.render)
138
+ this.listenTo(this.container, Events.CONTAINER_OPTIONS_CHANGE, this.update)
131
139
  this.listenTo(this.container, Events.CONTAINER_ERROR, this.onError)
132
- this.showOnVideoEnd &&
140
+ // TODO check if this event is always accompanied with the CONTAINER_STOP
141
+ if (this.options.poster?.showOnVideoEnd !== false) {
133
142
  this.listenTo(this.container, Events.CONTAINER_ENDED, this.onStop)
143
+ }
134
144
  this.listenTo(this.container, Events.CONTAINER_READY, this.render)
135
- this.listenTo(this.container, Events.PLAYBACK_PLAY_INTENT, this.onPlayIntent)
145
+ this.listenTo(
146
+ this.container.playback,
147
+ Events.PLAYBACK_PLAY_INTENT,
148
+ this.onPlayIntent,
149
+ )
136
150
  }
137
151
 
138
152
  /**
139
153
  * Reenables earlier disabled plugin
140
154
  */
141
155
  override enable() {
156
+ trace(`${T} enable`)
142
157
  super.enable()
143
- this.hasStartedPlaying = this.container.playback.isPlaying()
158
+ this.playing = this.container.playback.isPlaying()
144
159
  this.update()
145
160
  }
146
161
 
@@ -149,7 +164,7 @@ export class Poster extends UIContainerPlugin {
149
164
  */
150
165
  override disable() {
151
166
  trace(`${T} disable`)
152
- this.hasStartedPlaying = false
167
+ this.playing = false
153
168
  this.playRequested = false
154
169
  super.disable()
155
170
  }
@@ -159,19 +174,16 @@ export class Poster extends UIContainerPlugin {
159
174
  error,
160
175
  enabled: this.enabled,
161
176
  })
162
- this.hasFatalError = error.level === PlayerError.Levels.FATAL
163
-
164
177
  if (this.hasFatalError) {
165
- this.hasStartedPlaying = false
166
- if (!this.playRequested) {
167
- this.showPlayButton()
168
- }
178
+ return
169
179
  }
180
+ this.hasFatalError = error.level === PlayerError.Levels.FATAL
181
+ // this.hasFatalError is reset on container recreate
170
182
  }
171
183
 
172
184
  private onPlay() {
173
185
  trace(`${T} onPlay`)
174
- this.hasStartedPlaying = true
186
+ this.playing = true
175
187
  this.playRequested = false
176
188
  this.update()
177
189
  }
@@ -183,24 +195,23 @@ export class Poster extends UIContainerPlugin {
183
195
  }
184
196
 
185
197
  private onStop() {
186
- trace(`${T} onStop`, {
187
- enabled: this.enabled,
188
- })
189
- this.hasStartedPlaying = false
198
+ trace(`${T} onStop`)
199
+ this.playing = false
190
200
  this.playRequested = false
191
201
  this.update()
192
202
  }
193
203
 
194
- private updatePlayButton(show: boolean) {
195
- trace(`${T} updatePlayButton`, {
196
- show,
197
- chromeless: this.options.chromeless,
198
- allowUserInteraction: this.options.allowUserInteraction,
199
- })
200
- if (
201
- show &&
202
- (!this.options.chromeless || this.options.allowUserInteraction)
203
- ) {
204
+ private updatePlayButton() {
205
+ trace(`${T} updatePlayButton`)
206
+ const show =
207
+ !this.isNoOp &&
208
+ !(this.options.chromeless && !this.options.allowUserInteraction) &&
209
+ !this.playRequested &&
210
+ !this.playing &&
211
+ !this.container.buffering &&
212
+ !this.hasFatalError &&
213
+ !this.options.disableMediaControl
214
+ if (show) {
204
215
  this.showPlayButton()
205
216
  } else {
206
217
  this.hidePlayButton()
@@ -208,40 +219,31 @@ export class Poster extends UIContainerPlugin {
208
219
  }
209
220
 
210
221
  private showPlayButton() {
211
- if (this.options.disableMediaControl) {
212
- return
213
- }
214
- if (this.hasFatalError && !this.options.disableErrorScreen) {
215
- return
216
- }
217
-
218
- this.$playButton?.show()
222
+ trace(`${T} showPlayButton`)
223
+ this.$el.find('#poster-play').show()
219
224
  this.$el.addClass('clickable')
220
225
  this.container.$el.addClass('container-with-poster-clickable')
221
226
  }
222
227
 
223
228
  private hidePlayButton() {
224
- this.$playButton.hide()
229
+ trace(`${T} hidePlayButton`)
230
+ this.$el.find('#poster-play').hide()
225
231
  this.$el.removeClass('clickable')
226
232
  }
227
233
 
228
- private clicked() {
229
- trace(`${T} clicked`, {
230
- hasStartedPlaying: this.hasStartedPlaying,
231
- chromeless: this.options.chromeless,
232
- allowUserInteraction: this.options.allowUserInteraction,
233
- })
234
+ private clicked(e: MouseEvent) {
235
+ trace(`${T} clicked`)
236
+ e.preventDefault()
237
+ e.stopPropagation()
238
+ if (this.options.chromeless && !this.options.allowUserInteraction) {
239
+ return
240
+ }
234
241
  // Let "click_to_pause" plugin handle click event if media has started playing
235
- if (!this.hasStartedPlaying) {
236
- if (!this.options.chromeless || this.options.allowUserInteraction) {
237
- this.playRequested = true
238
- this.update()
239
- this.container.playback.consent()
240
- this.container.playback.play()
241
- }
242
+ if (!this.playing) {
243
+ this.playRequested = true
244
+ this.update()
245
+ this.container.play()
242
246
  }
243
-
244
- return false
245
247
  }
246
248
 
247
249
  private shouldHideOnPlay() {
@@ -250,27 +252,15 @@ export class Poster extends UIContainerPlugin {
250
252
  }
251
253
 
252
254
  private update() {
253
- trace(`${T} update`, {
254
- shouldRender: this.shouldRender,
255
- })
256
- if (!this.shouldRender) {
257
- return
258
- }
255
+ trace(`${T} update`)
259
256
 
260
- const showPlayButton =
261
- !this.playRequested &&
262
- !this.hasStartedPlaying &&
263
- !this.container.buffering
264
-
265
- this.updatePlayButton(showPlayButton)
257
+ this.updatePlayButton()
266
258
  this.updatePoster()
267
259
  }
268
260
 
269
261
  private updatePoster() {
270
- trace(`${T} updatePoster`, {
271
- hasStartedPlaying: this.hasStartedPlaying,
272
- })
273
- if (!this.hasStartedPlaying) {
262
+ trace(`${T} updatePoster`)
263
+ if (!this.playing) {
274
264
  this.showPoster()
275
265
  } else {
276
266
  this.hidePoster()
@@ -283,9 +273,7 @@ export class Poster extends UIContainerPlugin {
283
273
  }
284
274
 
285
275
  private hidePoster() {
286
- trace(`${T} hidePoster`, {
287
- shouldHideOnPlay: this.shouldHideOnPlay(),
288
- })
276
+ trace(`${T} hidePoster`)
289
277
  if (!this.options.disableMediaControl) {
290
278
  this.container.enableMediaControl()
291
279
  }
@@ -304,34 +292,27 @@ export class Poster extends UIContainerPlugin {
304
292
 
305
293
  this.$el.html(Poster.template())
306
294
 
307
- const isRegularPoster =
308
- this.options.poster && this.options.poster.custom === undefined
295
+ const isCustomPoster = this.options.poster?.custom !== undefined
309
296
 
310
- if (isRegularPoster) {
311
- const posterUrl = this.options.poster.url || this.options.poster
312
-
313
- this.$el.css({ 'background-image': 'url(' + posterUrl + ')' })
314
- } else if (this.options.poster) {
297
+ if (isCustomPoster) {
315
298
  this.$el.css({ background: this.options.poster.custom })
299
+ } else {
300
+ const posterUrl =
301
+ typeof this.options.poster === 'string'
302
+ ? this.options.poster
303
+ : this.options.poster?.url
304
+ if (posterUrl) {
305
+ this.$el.css({ 'background-image': 'url(' + posterUrl + ')' })
306
+ }
316
307
  }
317
308
 
318
309
  this.container.$el.removeClass('container-with-poster-clickable')
319
310
  this.container.$el.append(this.el)
320
- this.$playWrapper = this.$el.find('.play-wrapper')
321
- this.$playWrapper.addClass('control-need-disable')
322
- this.$playButton = $(
323
- "<div class='circle-poster gcore-skin-button-color gcore-skin-border-color'></div>",
324
- )
325
- this.$playWrapper.append(this.$playButton)
326
- this.$playButton.append(playIcon)
311
+ this.$el.find('#poster-play').append(playIcon)
327
312
 
328
- if (this.options.autoPlay) {
329
- this.$playButton.hide()
313
+ if (this.options.autoPlay || this.isNoOp) {
314
+ this.$el.find('#poster-play').hide()
330
315
  }
331
- this.$playButton.addClass('poster-icon')
332
- this.$playButton.attr('data-poster', '')
333
-
334
- this.update()
335
316
 
336
317
  return this
337
318
  }
@@ -0,0 +1,119 @@
1
+ import { Poster } from '../Poster'
2
+ import { describe, it, expect, beforeEach } from 'vitest'
3
+ import { createMockCore } from '../../../testUtils'
4
+ import { Events, PlayerError } from '@clappr/core'
5
+
6
+ describe('Poster', () => {
7
+ let core: any
8
+ let poster: Poster
9
+ describe('basically', () => {
10
+ beforeEach(() => {
11
+ core = createMockCore({
12
+ poster: {
13
+ url: 'https://via.placeholder.com/150.png',
14
+ },
15
+ })
16
+ poster = new Poster(core.activeContainer)
17
+ core.activeContainer.trigger(Events.CONTAINER_READY)
18
+ })
19
+ it('should render', () => {
20
+ expect(poster.el.innerHTML).toMatchSnapshot()
21
+ })
22
+ describe('when clicked', () => {
23
+ beforeEach(() => {
24
+ poster.el.click()
25
+ })
26
+ it('should start playback', () => {
27
+ expect(core.activeContainer.play).toHaveBeenCalled()
28
+ expect(core.activeContainer.playback.consent).not.toHaveBeenCalled()
29
+ })
30
+ it('should hide button', () => {
31
+ expect(poster.$el.find('#poster-play')[0].style.display).toBe('none')
32
+ })
33
+ it('should remove clickable class', () => {
34
+ expect(poster.el.classList.contains('clickable')).toBe(false)
35
+ })
36
+ })
37
+ describe('when playback is triggered', () => {
38
+ beforeEach(() => {
39
+ core.activeContainer.playback.trigger(Events.PLAYBACK_PLAY_INTENT)
40
+ })
41
+ it('should hide button', () => {
42
+ expect(poster.$el.find('#poster-play')[0].style.display).toBe('none')
43
+ })
44
+ })
45
+ describe('when playback is about to start', () => {
46
+ describe.each([
47
+ [
48
+ Events.CONTAINER_STATE_BUFFERING,
49
+ ], [
50
+ Events.CONTAINER_STATE_BUFFERFULL,
51
+ ]
52
+ ])("event %s", (event) => {
53
+ beforeEach(() => {
54
+ core.activeContainer.buffering = true
55
+ core.activeContainer.trigger(event)
56
+ })
57
+ it('should hide button', () => {
58
+ expect(poster.$el.find('#poster-play')[0].style.display).toBe('none')
59
+ })
60
+ })
61
+ })
62
+ describe('when playback is started', () => {
63
+ beforeEach(() => {
64
+ core.activeContainer.trigger(Events.CONTAINER_PLAY)
65
+ core.activeContainer.playback.trigger(Events.PLAYBACK_PLAY)
66
+ })
67
+ it('should hide poster', () => {
68
+ expect(poster.el.style.display).toBe('none')
69
+ })
70
+ })
71
+ describe('when playback is stopped', () => {
72
+ beforeEach(() => {
73
+ core.activeContainer.trigger(Events.CONTAINER_PLAY)
74
+ core.activeContainer.playback.trigger(Events.PLAYBACK_PLAY)
75
+ core.activeContainer.trigger(Events.CONTAINER_STOP)
76
+ })
77
+ it('should show poster', () => {
78
+ expect(poster.el.style.display).not.toBe('none')
79
+ })
80
+ it('should show button', () => {
81
+ expect(poster.$el.find('#poster-play')[0].style.display).not.toBe('none')
82
+ })
83
+ it('should add clickable class', () => {
84
+ expect(poster.el.classList.contains('clickable')).toBe(true)
85
+ })
86
+ })
87
+ })
88
+ describe('when autoplay is configured', () => {
89
+ beforeEach(() => {
90
+ core = createMockCore({
91
+ autoPlay: true,
92
+ })
93
+ poster = new Poster(core.activeContainer)
94
+ core.activeContainer.trigger(Events.CONTAINER_READY)
95
+ })
96
+ it('should hide button initially', () => {
97
+ expect(poster.$el.find('#poster-play')[0].style.display).toBe('none')
98
+ })
99
+ })
100
+ describe('when error occurs', () => {
101
+ beforeEach(() => {
102
+ core = createMockCore({
103
+ autoPlay: true,
104
+ })
105
+ poster = new Poster(core.activeContainer)
106
+ core.activeContainer.trigger(Events.CONTAINER_READY)
107
+ core.activeContainer.playback.trigger(Events.PLAYBACK_PLAY_INTENT)
108
+ core.activeContainer.trigger(Events.CONTAINER_ERROR, {
109
+ level: PlayerError.Levels.FATAL,
110
+ })
111
+ })
112
+ it('should show poster', () => {
113
+ expect(poster.el.style.display).not.toBe('none')
114
+ })
115
+ it('should hide button', () => {
116
+ expect(poster.$el.find('#poster-play')[0].style.display).toBe('none')
117
+ })
118
+ })
119
+ })
@@ -0,0 +1,8 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`Poster > basically > should render 1`] = `
4
+ "<div class="play-wrapper" id="gplayer-poster">
5
+ <div class="circle-poster gcore-skin-button-color gcore-skin-border-color" id="poster-play">/assets/icons/new/play.svg</div>
6
+ </div>
7
+ "
8
+ `;
@@ -5,7 +5,6 @@ import FakeTimers from '@sinonjs/fake-timers'
5
5
  import { SourceController } from '../SourceController'
6
6
  import { PlaybackErrorCode } from '../../../playback.types.js'
7
7
  import {
8
- _MockPlayback,
9
8
  createMockCore,
10
9
  createMockPlayback,
11
10
  createMockPlugin,
@@ -151,7 +150,7 @@ describe('SourceController', () => {
151
150
  core.activePlayback.emit('playback:error', {
152
151
  code: PlaybackErrorCode.MediaSourceUnavailable,
153
152
  })
154
- nextPlayback = new _MockPlayback({} as any, {} as any)
153
+ nextPlayback = createMockPlayback()
155
154
  vi.spyOn(nextPlayback, 'consent')
156
155
  vi.spyOn(nextPlayback, 'play')
157
156
  core.activePlayback = nextPlayback
package/src/testUtils.ts CHANGED
@@ -1,86 +1,6 @@
1
- import { $, Playback, UICorePlugin } from '@clappr/core'
1
+ import { $, UICorePlugin } from '@clappr/core'
2
2
  import Events from 'eventemitter3'
3
3
  import { vi } from 'vitest'
4
- /**
5
- * @internal
6
- * @deprecated
7
- * TODO use createMockPlayback() instead
8
- */
9
- export class _MockPlayback extends Events {
10
- constructor(
11
- protected options: any,
12
- readonly i18n: any,
13
- protected playerError?: any,
14
- ) {
15
- super()
16
- }
17
-
18
- get name() {
19
- return 'mock'
20
- }
21
-
22
- consent() {}
23
-
24
- play() {}
25
-
26
- pause() {}
27
-
28
- stop() {}
29
-
30
- destroy() {}
31
-
32
- seek() {}
33
-
34
- seekPercentage() {}
35
-
36
- getDuration() {
37
- return 100
38
- }
39
-
40
- enterPiP() {}
41
-
42
- exitPiP() {}
43
-
44
- getPlaybackType() {
45
- return Playback.LIVE
46
- }
47
-
48
- getStartTimeOffset() {
49
- return 0
50
- }
51
-
52
- getCurrentTime() {
53
- return 0
54
- }
55
-
56
- isHighDefinitionInUse() {
57
- return false
58
- }
59
-
60
- mute() {}
61
-
62
- unmute() {}
63
-
64
- volume() {}
65
-
66
- configure() {}
67
-
68
- attemptAutoPlay() {
69
- return true
70
- }
71
-
72
- canAutoPlay() {
73
- return true
74
- }
75
-
76
- onResize() {
77
- return true
78
- }
79
-
80
- trigger(event: string, ...args: any[]) {
81
- this.emit(event, ...args)
82
- }
83
- }
84
4
 
85
5
  export function createMockCore(
86
6
  options: Record<string, unknown> = {},
@@ -129,11 +49,12 @@ export function createMockPlayback(name = 'mock') {
129
49
  el: document.createElement('video'),
130
50
  dvrEnabled: false,
131
51
  dvrInUse: false,
52
+ isAudioOnly: false,
132
53
  levels: [],
133
- consent() {},
134
- play() {},
135
- pause() {},
136
- stop() {},
54
+ consent: vi.fn(),
55
+ play: vi.fn(),
56
+ pause: vi.fn(),
57
+ stop: vi.fn(),
137
58
  destroy: vi.fn(),
138
59
  seek: vi.fn(),
139
60
  seekPercentage: vi.fn(),
@@ -166,13 +87,20 @@ export function createMockContainer(
166
87
  return Object.assign(emitter, {
167
88
  el,
168
89
  playback,
169
- options,
90
+ options: {
91
+ ...options,
92
+ },
170
93
  $el: $(el),
94
+ disableMediaControl: vi.fn(),
95
+ enableMediaControl: vi.fn(),
96
+ enterPiP: vi.fn(),
97
+ exitPiP: vi.fn(),
171
98
  getDuration: vi.fn().mockReturnValue(0),
172
99
  getPlugin: vi.fn(),
173
100
  getPlaybackType: vi.fn(),
174
101
  isDvrInUse: vi.fn().mockReturnValue(false),
175
102
  isDvrEnabled: vi.fn().mockReturnValue(false),
103
+ isHighDefinitionInUse: vi.fn().mockReturnValue(false),
176
104
  isPlaying: vi.fn().mockReturnValue(false),
177
105
  play: vi.fn(),
178
106
  seek: vi.fn(),