@clappr/hlsjs-playback 0.5.3 → 1.0.1

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clappr/hlsjs-playback",
3
- "version": "0.5.3",
3
+ "version": "1.0.1",
4
4
  "description": "HLS Playback based on hls.js",
5
5
  "main": "./dist/hlsjs-playback.js",
6
6
  "module": "./dist/hlsjs-playback.esm.js",
@@ -11,7 +11,7 @@
11
11
  "watch": "rollup --config --watch",
12
12
  "bundle-check": "ANALYZE_BUNDLE=true rollup --config",
13
13
  "release": "MINIMIZE=true rollup --config",
14
- "test": "jest ./src --coverage",
14
+ "test": "jest ./src --coverage --silent",
15
15
  "test:debug": "node --inspect node_modules/.bin/jest ./src --runInBand",
16
16
  "test:watch": "jest ./src --watch",
17
17
  "lint": "eslint *.js ./src",
@@ -35,30 +35,30 @@
35
35
  },
36
36
  "homepage": "https://github.com/clappr/hlsjs-playback",
37
37
  "peerDependencies": {
38
- "@clappr/core": "^0.4.11",
39
- "hls.js": "^0.13.2"
38
+ "@clappr/core": "^0.4.27",
39
+ "hls.js": "^1.2.4"
40
40
  },
41
41
  "devDependencies": {
42
- "@babel/core": "^7.10.2",
43
- "@babel/preset-env": "^7.10.2",
44
- "@clappr/core": "^0.4.11",
45
- "@rollup/plugin-babel": "^5.0.3",
46
- "@rollup/plugin-commonjs": "^13.0.0",
47
- "@rollup/plugin-node-resolve": "^8.0.1",
48
- "@rollup/plugin-replace": "^2.3.3",
49
- "babel-jest": "^26.0.1",
50
- "coveralls": "^3.0.0",
51
- "cz-conventional-changelog": "^2.1.0",
52
- "eslint": "^4.18.2",
53
- "hls.js": "^0.13.2",
54
- "jest": "^26.0.1",
55
- "rollup": "^2.15.0",
56
- "rollup-plugin-filesize": "^9.0.0",
57
- "rollup-plugin-livereload": "^1.3.0",
58
- "rollup-plugin-serve": "^1.0.1",
59
- "rollup-plugin-sizes": "^1.0.2",
60
- "rollup-plugin-terser": "^6.1.0",
61
- "rollup-plugin-visualizer": "^4.0.4"
42
+ "@babel/core": "^7.14.2",
43
+ "@babel/preset-env": "^7.14.2",
44
+ "@clappr/core": "^0.4.27",
45
+ "@rollup/plugin-babel": "^5.3.0",
46
+ "@rollup/plugin-commonjs": "^19.0.0",
47
+ "@rollup/plugin-node-resolve": "^13.0.0",
48
+ "@rollup/plugin-replace": "^2.4.2",
49
+ "babel-jest": "^26.6.3",
50
+ "coveralls": "^3.1.0",
51
+ "cz-conventional-changelog": "^3.3.0",
52
+ "eslint": "^7.26.0",
53
+ "hls.js": "^1.2.4",
54
+ "jest": "^26.6.3",
55
+ "rollup": "^2.47.0",
56
+ "rollup-plugin-filesize": "^9.1.1",
57
+ "rollup-plugin-livereload": "^2.0.0",
58
+ "rollup-plugin-serve": "^1.1.0",
59
+ "rollup-plugin-sizes": "^1.0.4",
60
+ "rollup-plugin-terser": "^7.0.2",
61
+ "rollup-plugin-visualizer": "^5.5.0"
62
62
  },
63
63
  "config": {
64
64
  "commitizen": {
package/src/hls.js CHANGED
@@ -109,6 +109,14 @@ export default class HlsjsPlayback extends HTML5Video {
109
109
  return this._hls && this._hls.bandwidthEstimate
110
110
  }
111
111
 
112
+ get defaultOptions() {
113
+ return { preload: true }
114
+ }
115
+
116
+ get customListeners() {
117
+ return this.options.hlsPlayback && this.options.hlsPlayback.customListeners || []
118
+ }
119
+
112
120
  static get HLSJS() {
113
121
  return HLSJS
114
122
  }
@@ -117,6 +125,7 @@ export default class HlsjsPlayback extends HTML5Video {
117
125
  super(...args)
118
126
  // backwards compatibility (TODO: remove on 0.3.0)
119
127
  this.options.playback = { ...this.options, ...this.options.playback }
128
+ this.options.hlsPlayback = { ...this.defaultOptions, ...this.options.hlsPlayback }
120
129
  this._minDvrSize = typeof (this.options.hlsMinimumDvrSize) === 'undefined' ? 60 : this.options.hlsMinimumDvrSize
121
130
  // The size of the start time extrapolation window measured as a multiple of segments.
122
131
  // Should be 2 or higher, or 0 to disable. Should only need to be increased above 2 if more than one segment is
@@ -158,11 +167,13 @@ export default class HlsjsPlayback extends HTML5Video {
158
167
  }
159
168
 
160
169
  _setup() {
170
+ this._manifestParsed = false
161
171
  this._ccIsSetup = false
162
172
  this._ccTracksUpdated = false
163
173
  this._hls && this._hls.destroy()
164
174
  this._hls = new HLSJS(assign({}, this.options.playback.hlsjsConfig))
165
- this._hls.once(HLSJS.Events.MEDIA_ATTACHED, () => this._hls.loadSource(this.options.src))
175
+ this._hls.once(HLSJS.Events.MEDIA_ATTACHED, () => { this.options.hlsPlayback.preload && this._hls.loadSource(this.options.src) })
176
+ this._hls.on(HLSJS.Events.MANIFEST_PARSED, () => this._manifestParsed = true)
166
177
  this._hls.on(HLSJS.Events.LEVEL_LOADED, (evt, data) => this._updatePlaybackType(evt, data))
167
178
  this._hls.on(HLSJS.Events.LEVEL_UPDATED, (evt, data) => this._onLevelUpdated(evt, data))
168
179
  this._hls.on(HLSJS.Events.LEVEL_SWITCHING, (evt,data) => this._onLevelSwitch(evt, data))
@@ -172,9 +183,27 @@ export default class HlsjsPlayback extends HTML5Video {
172
183
  this._hls.on(HLSJS.Events.ERROR, (evt, data) => this._onHLSJSError(evt, data))
173
184
  this._hls.on(HLSJS.Events.SUBTITLE_TRACK_LOADED, (evt, data) => this._onSubtitleLoaded(evt, data))
174
185
  this._hls.on(HLSJS.Events.SUBTITLE_TRACKS_UPDATED, () => this._ccTracksUpdated = true)
186
+
187
+ this.bindCustomListeners()
188
+
175
189
  this._hls.attachMedia(this.el)
176
190
  }
177
191
 
192
+ bindCustomListeners() {
193
+ this.customListeners.forEach(item => {
194
+ const requestedEventName = item.eventName
195
+ const typeOfListener = item.once ? 'once': 'on'
196
+ requestedEventName && this._hls[`${typeOfListener}`](requestedEventName, item.callback)
197
+ })
198
+ }
199
+
200
+ unbindCustomListeners() {
201
+ this.customListeners.forEach(item => {
202
+ const requestedEventName = item.eventName
203
+ requestedEventName && this._hls.off(requestedEventName, item.callback)
204
+ })
205
+ }
206
+
178
207
  _onFragmentParsingMetadata(evt, data) {
179
208
  this.trigger(Events.Custom.PLAYBACK_FRAGMENT_PARSING_METADATA, { evt, data })
180
209
  }
@@ -185,6 +214,8 @@ export default class HlsjsPlayback extends HTML5Video {
185
214
  }
186
215
 
187
216
  _ready() {
217
+ if (this._isReadyState) return
218
+ !this._hls && this._setup()
188
219
  this._isReadyState = true
189
220
  this.trigger(Events.PLAYBACK_READY, this.name)
190
221
  }
@@ -416,8 +447,8 @@ export default class HlsjsPlayback extends HTML5Video {
416
447
  }
417
448
 
418
449
  play() {
419
- if (!this._hls)
420
- this._setup()
450
+ !this._hls && this._setup()
451
+ !this._manifestParsed && !this.options.hlsPlayback.preload && this._hls.loadSource(this.options.src)
421
452
 
422
453
  super.play()
423
454
  this._startTimeUpdateTimer()
package/src/hls.test.js CHANGED
@@ -2,16 +2,34 @@ import { Core, Events } from '@clappr/core'
2
2
  import HlsjsPlayback from './hls.js'
3
3
  import HLSJS from 'hls.js'
4
4
 
5
- describe('HLS playback', function() {
6
- beforeEach(() => {
7
- this.isSupportedStub = jest.spyOn(HLSJS, 'isSupported').mockImplementation(() => true)
5
+ const simplePlaybackMock = new HlsjsPlayback({ src: 'http://clappr.io/video.m3u8' })
6
+
7
+ describe('HlsjsPlayback', () => {
8
+ test('have a getter called defaultOptions', () => {
9
+ expect(Object.getOwnPropertyDescriptor(Object.getPrototypeOf(simplePlaybackMock), 'defaultOptions').get).toBeTruthy()
10
+ })
11
+
12
+ test('defaultOptions getter returns all the default options values into one object', () => {
13
+ expect(simplePlaybackMock.defaultOptions).toEqual({ preload: true })
14
+ })
15
+
16
+ test('have a getter called customListeners', () => {
17
+ expect(Object.getOwnPropertyDescriptor(Object.getPrototypeOf(simplePlaybackMock), 'customListeners').get).toBeTruthy()
8
18
  })
9
19
 
10
- // afterEach(() => {
11
- // this.isSupportedStub.restore()
12
- // })
20
+ test('customListeners getter returns all configured custom listeners for each hls.js event', () => {
21
+ const cb = () => {}
22
+ const playback = new HlsjsPlayback({
23
+ src: 'http://clappr.io/foo.m3u8',
24
+ hlsPlayback: {
25
+ customListeners: [{ eventName: 'hlsMediaAttaching', callback: cb }]
26
+ }
27
+ })
28
+ expect(playback.customListeners).toEqual(playback.options.hlsPlayback.customListeners)
29
+ })
13
30
 
14
- it('should be able to identify it can play resources independently of the file extension case', function() {
31
+ test('should be able to identify it can play resources independently of the file extension case', () => {
32
+ jest.spyOn(HLSJS, 'isSupported').mockImplementation(() => true)
15
33
  expect(HlsjsPlayback.canPlay('/relative/video.m3u8')).toBeTruthy()
16
34
  expect(HlsjsPlayback.canPlay('/relative/VIDEO.M3U8')).toBeTruthy()
17
35
  expect(HlsjsPlayback.canPlay('/relative/video.m3u8?foobarQuery=1234#somefragment')).toBeTruthy()
@@ -19,12 +37,13 @@ describe('HLS playback', function() {
19
37
  expect(HlsjsPlayback.canPlay('//whatever_no_extension?foobarQuery=1234#somefragment', 'application/x-mpegURL' )).toBeTruthy()
20
38
  })
21
39
 
22
- it('can play regardless of any mime type letter case', function() {
40
+ test('can play regardless of any mime type letter case', () => {
41
+ jest.spyOn(HLSJS, 'isSupported').mockImplementation(() => true)
23
42
  expect(HlsjsPlayback.canPlay('/path/list.m3u8', 'APPLICATION/VND.APPLE.MPEGURL' )).toBeTruthy()
24
43
  expect(HlsjsPlayback.canPlay('whatever_no_extension?foobarQuery=1234#somefragment', 'application/x-mpegurl' )).toBeTruthy()
25
44
  })
26
45
 
27
- it('should ensure it does not create an audio tag if audioOnly is not set', function() {
46
+ test('should ensure it does not create an audio tag if audioOnly is not set', () => {
28
47
  let options = { src: 'http://clappr.io/video.m3u8' },
29
48
  playback = new HlsjsPlayback(options)
30
49
  expect(playback.tagName).toEqual('video')
@@ -33,26 +52,67 @@ describe('HLS playback', function() {
33
52
  expect(playback.tagName).toEqual('video')
34
53
  })
35
54
 
36
- it('should play on an audio tag if audioOnly is set', function() {
55
+ test('should play on an audio tag if audioOnly is set', () => {
37
56
  let options = { src: 'http://clappr.io/video.m3u8', playback: { audioOnly: true } },
38
57
  playback = new HlsjsPlayback(options)
39
58
  expect(playback.tagName).toEqual('audio')
40
59
  })
41
60
 
42
- describe('options backwards compatibility', function() {
43
- // backwards compatibility (TODO: remove on 0.3.0)
44
- it('should set options.playback as a reference to options if options.playback not set', function() {
45
- let options = { src: 'http://clappr.io/video.m3u8' },
46
- hls = new HlsjsPlayback(options)
47
- expect(hls.options.playback).toEqual(hls.options)
48
- options = { src: 'http://clappr.io/video.m3u8', playback: { test: true } }
49
- hls = new HlsjsPlayback(options)
50
- expect(hls.options.playback.test).toEqual(true)
61
+ test('should trigger a playback error if source load failed', () => {
62
+ jest.spyOn(window.HTMLMediaElement.prototype, 'play').mockImplementation(() => {})
63
+ let resolveFn = undefined
64
+ const promise = new Promise((resolve) => {
65
+ resolveFn = resolve
66
+ })
67
+ let options = {
68
+ src: 'http://clappr.io/notfound.m3u8',
69
+ hlsRecoverAttempts: 0,
70
+ mute: true
71
+ }
72
+
73
+ const core = new Core({})
74
+ const playback = new HlsjsPlayback(options, null, core.playerError)
75
+ playback.on(Events.PLAYBACK_ERROR, (e) => resolveFn(e))
76
+ playback.play()
77
+
78
+ promise.then((e) => {
79
+ expect(e.raw.type).toEqual(HLSJS.ErrorTypes.NETWORK_ERROR)
80
+ expect(e.raw.details).toEqual(HLSJS.ErrorDetails.MANIFEST_LOAD_ERROR)
51
81
  })
52
82
  })
53
83
 
54
- describe('HlsjsPlayback.js configuration', function() {
55
- it('should use hlsjsConfig from playback options', function() {
84
+ test('registers PLAYBACK_FRAGMENT_CHANGED event', () => {
85
+ expect(Events.Custom.PLAYBACK_FRAGMENT_CHANGED).toEqual('playbackFragmentChanged')
86
+ })
87
+
88
+ test('registers PLAYBACK_FRAGMENT_PARSING_METADATA event', () => {
89
+ expect(Events.Custom.PLAYBACK_FRAGMENT_PARSING_METADATA).toEqual('playbackFragmentParsingMetadata')
90
+ })
91
+
92
+ test('levels supports specifying the level', () => {
93
+ let playback
94
+ const options = { src: 'http://clappr.io/foo.m3u8' }
95
+ playback = new HlsjsPlayback(options)
96
+ playback._setup()
97
+ // NOTE: rather than trying to call playback.setupHls, we'll punch a new one in place
98
+ playback._hls = { levels: [] }
99
+ playback._fillLevels()
100
+
101
+ // AUTO by default (-1)
102
+ expect(playback.currentLevel).toEqual(-1)
103
+
104
+ // Supports other level specification. Should keep track of it
105
+ // on itself and by proxy on the HLS.js object.
106
+ playback.currentLevel = 0
107
+ expect(playback.currentLevel).toEqual(0)
108
+ expect(playback._hls.currentLevel).toEqual(0)
109
+ playback.currentLevel = 1
110
+ expect(playback.currentLevel).toEqual(1)
111
+ expect(playback._hls.currentLevel).toEqual(1)
112
+ })
113
+
114
+ describe('constructor', () => {
115
+ test('should use hlsjsConfig from playback options', () => {
56
116
  const options = {
57
117
  src: 'http://clappr.io/video.m3u8',
58
118
  playback: {
@@ -67,7 +127,7 @@ describe('HLS playback', function() {
67
127
  expect(playback._hls.config.someHlsjsOption).toEqual('value')
68
128
  })
69
129
 
70
- it('should use hlsjsConfig from player options as fallback', function() {
130
+ test('should use hlsjsConfig from player options as fallback', () => {
71
131
  const options = {
72
132
  src: 'http://clappr.io/video.m3u8',
73
133
  hlsMinimumDvrSize: 1,
@@ -79,64 +139,199 @@ describe('HLS playback', function() {
79
139
  playback._setup()
80
140
  expect(playback._hls.config.someHlsjsOption).toEqual('value')
81
141
  })
142
+
143
+ test('merges defaultOptions with received options.hlsPlayback', () => {
144
+ const options = {
145
+ src: 'http://clappr.io/foo.m3u8',
146
+ hlsPlayback: { foo: 'bar' },
147
+ }
148
+ const playback = new HlsjsPlayback(options)
149
+ expect(playback.options.hlsPlayback).toEqual({ ...options.hlsPlayback, ...playback.defaultOptions })
150
+ })
82
151
  })
83
152
 
84
- it('should trigger a playback error if source load failed', function() {
85
- jest.spyOn(window.HTMLMediaElement.prototype, 'play').mockImplementation(() => {})
86
- let resolveFn = undefined
87
- const promise = new Promise((resolve) => {
88
- resolveFn = resolve
153
+ describe('_setup method', () => {
154
+ test('sets _manifestParsed flag to false', () => {
155
+ const playback = new HlsjsPlayback({ src: 'http://clappr.io/foo.m3u8' })
156
+ expect(playback._manifestParsed).toBeUndefined()
157
+
158
+ playback._setup()
159
+
160
+ expect(playback._manifestParsed).toBeFalsy()
89
161
  })
90
- let options = {
91
- src: 'http://clappr.io/notfound.m3u8',
92
- hlsRecoverAttempts: 0,
93
- mute: true
94
- }
95
162
 
96
- const core = new Core({})
97
- const playback = new HlsjsPlayback(options, null, core.playerError)
98
- playback.on(Events.PLAYBACK_ERROR, (e) => resolveFn(e))
99
- playback.play()
163
+ test('calls this._hls.loadSource when MEDIA_ATTACHED event is triggered and hlsPlayback.preload is true', () => {
164
+ const playback = new HlsjsPlayback({ src: 'http://clappr.io/foo.m3u8', hlsPlayback: { preload: false } })
165
+ playback._setup()
166
+ jest.spyOn(playback._hls, 'loadSource')
167
+ playback._hls.trigger(HLSJS.Events.MEDIA_ATTACHED, { media: playback.el })
100
168
 
101
- promise.then((e) => {
102
- expect(e.raw.type).toEqual(HLSJS.ErrorTypes.NETWORK_ERROR)
103
- expect(e.raw.details).toEqual(HLSJS.ErrorDetails.MANIFEST_LOAD_ERROR)
169
+ expect(playback._hls.loadSource).not.toHaveBeenCalled()
170
+
171
+ playback.options.hlsPlayback.preload = true
172
+ playback._setup()
173
+ jest.spyOn(playback._hls, 'loadSource')
174
+ playback._hls.trigger(HLSJS.Events.MEDIA_ATTACHED, { media: playback.el })
175
+
176
+ expect(playback._hls.loadSource).toHaveBeenCalledTimes(1)
177
+ })
178
+
179
+ test('updates _manifestParsed flag value to true if MANIFEST_PARSED event is triggered', () => {
180
+ const playback = new HlsjsPlayback({ src: 'http://clappr.io/foo.m3u8' })
181
+
182
+ expect(playback._manifestParsed).toBeUndefined()
183
+
184
+ playback._setup()
185
+ playback._hls.trigger(HLSJS.Events.MANIFEST_PARSED, { levels: [] })
186
+
187
+ expect(playback._manifestParsed).toBeTruthy()
188
+ })
189
+
190
+ test('calls bindCustomListeners method', () => {
191
+ const playback = new HlsjsPlayback({ src: 'http://clappr.io/foo.m3u8' })
192
+ jest.spyOn(playback, 'bindCustomListeners')
193
+ playback._setup()
194
+
195
+ expect(playback.bindCustomListeners).toHaveBeenCalledTimes(1)
104
196
  })
105
197
  })
106
198
 
107
- it('registers PLAYBACK_FRAGMENT_CHANGED event', function() {
108
- expect(Events.Custom.PLAYBACK_FRAGMENT_CHANGED).toEqual('playbackFragmentChanged')
199
+ describe('_ready method', () => {
200
+ test('avoid to run internal logic if _isReadyState flag is true', () => {
201
+ const playback = new HlsjsPlayback({ src: 'http://clappr.io/video.m3u8' })
202
+ playback._isReadyState = true
203
+ jest.spyOn(playback, '_setup')
204
+ playback._ready()
205
+
206
+ expect(playback._setup).not.toHaveBeenCalled()
207
+ })
208
+
209
+ test('call _setup method if HLS.JS internal don\'t exists', () => {
210
+ const playback = new HlsjsPlayback({ src: 'http://clappr.io/video.m3u8' })
211
+ jest.spyOn(playback, '_setup')
212
+ playback._ready()
213
+
214
+ expect(playback._setup).toHaveBeenCalledTimes(1)
215
+
216
+ playback._ready()
217
+ expect(playback._setup).toHaveBeenCalledTimes(1)
218
+ })
219
+
220
+ test('update _isReadyState flag value to true', () => {
221
+ const playback = new HlsjsPlayback({ src: 'http://clappr.io/video.m3u8' })
222
+
223
+ expect(playback._isReadyState).toBeFalsy()
224
+
225
+ playback._ready()
226
+
227
+ expect(playback._isReadyState).toBeTruthy()
228
+ })
229
+
230
+ test('triggers PLAYBACK_READY event', done => {
231
+ const cb = jest.fn()
232
+ const playback = new HlsjsPlayback({ src: 'http://clappr.io/video.m3u8' })
233
+
234
+ playback.listenTo(playback, Events.PLAYBACK_READY, cb)
235
+ playback.listenTo(playback, Events.PLAYBACK_READY, () => {
236
+ expect(cb).toHaveBeenCalledTimes(1)
237
+ done()
238
+ })
239
+ playback._ready()
240
+ })
109
241
  })
110
242
 
111
- it('registers PLAYBACK_FRAGMENT_PARSING_METADATA event', function() {
112
- expect(Events.Custom.PLAYBACK_FRAGMENT_PARSING_METADATA).toEqual('playbackFragmentParsingMetadata')
243
+ describe('play method', () => {
244
+ test('calls this._hls.loadSource if _manifestParsed flag and options.hlsPlayback.preload are falsy', () => {
245
+ const playback = new HlsjsPlayback({ src: 'http://clappr.io/foo.m3u8', hlsPlayback: { preload: true } })
246
+ playback._setup()
247
+ jest.spyOn(playback._hls, 'loadSource')
248
+ playback.play()
249
+
250
+ expect(playback._hls.loadSource).not.toHaveBeenCalled()
251
+
252
+ playback.options.hlsPlayback.preload = false
253
+ playback._manifestParsed = true
254
+ playback.play()
255
+
256
+ expect(playback._hls.loadSource).not.toHaveBeenCalled()
257
+
258
+ playback._manifestParsed = false
259
+ playback.play()
260
+
261
+ expect(playback._hls.loadSource).toHaveBeenCalledTimes(1)
262
+ })
113
263
  })
114
264
 
115
- xit('levels', function() {
116
- let playback
117
- beforeEach(() => {
118
- const options = { src: 'http://clappr.io/foo.m3u8' }
119
- playback = new HlsjsPlayback(options)
120
- playback.setupHls()
121
- // NOTE: rather than trying to call playback.setupHls, we'll punch a new one in place
122
- playback.hls = {
123
- levels: []
124
- }
125
- playback.fillLevels()
265
+ describe('bindCustomListeners method', () => {
266
+ test('creates listeners for each item configured on customListeners array', () => {
267
+ const cb = jest.fn()
268
+ const playback = new HlsjsPlayback({
269
+ src: 'http://clappr.io/foo.m3u8',
270
+ hlsPlayback: {
271
+ customListeners: [{ eventName: HLSJS.Events.MEDIA_ATTACHING, callback: cb }]
272
+ }
273
+ })
274
+ playback._setup()
275
+
276
+ expect(cb).toHaveBeenCalledTimes(1)
277
+
278
+ playback._hls.trigger(HLSJS.Events.MEDIA_ATTACHING, { media: playback.el })
279
+
280
+ expect(cb).toHaveBeenCalledTimes(2)
281
+ })
282
+
283
+ test('don\'t add one listener without a valid configuration', () => {
284
+ const cb = jest.fn()
285
+ const playback = new HlsjsPlayback({ src: 'http://clappr.io/foo.m3u8' })
286
+ playback._setup()
287
+
288
+ expect(cb).not.toHaveBeenCalled()
289
+
290
+ playback.options.hlsPlayback = {}
291
+
292
+ expect(cb).not.toHaveBeenCalled()
293
+
294
+ playback.options.hlsPlayback.customListeners = []
295
+
296
+ expect(cb).not.toHaveBeenCalled()
297
+
298
+ playback.options.hlsPlayback.customListeners.push([{ eventName: 'invalid_name', callback: cb }])
299
+
300
+ expect(cb).not.toHaveBeenCalled()
301
+ })
302
+
303
+ test('adds a listener for one time when the customListeners array item is configured with the "once" param', () => {
304
+ const cb = jest.fn()
305
+ const playback = new HlsjsPlayback({
306
+ src: 'http://clappr.io/foo.m3u8',
307
+ hlsPlayback: {
308
+ customListeners: [{ eventName: HLSJS.Events.MEDIA_ATTACHING, callback: cb, once: true }]
309
+ }
310
+ })
311
+ playback._setup()
312
+
313
+ expect(cb).toHaveBeenCalledTimes(1)
314
+
315
+ playback._hls.trigger(HLSJS.Events.MEDIA_ATTACHING)
316
+
317
+ expect(cb).toHaveBeenCalledTimes(1)
126
318
  })
319
+ })
127
320
 
128
- it('supports specifying the level', () => {
129
- // AUTO by default (-1)
130
- expect(playback.currentLevel).to.equal(-1)
321
+ describe('unbindCustomListeners method', () => {
322
+ test('remove listeners for each item configured on customListeners array', () => {
323
+ const cb = jest.fn()
324
+ const playback = new HlsjsPlayback({
325
+ src: 'http://clappr.io/foo.m3u8',
326
+ hlsPlayback: {
327
+ customListeners: [{ eventName: 'hlsFragLoaded', callback: cb }]
328
+ }
329
+ })
330
+ playback._setup()
331
+ playback.unbindCustomListeners()
332
+ playback._hls.trigger(HLSJS.Events.FRAG_LOADED)
131
333
 
132
- // Supports other level specification. Should keep track of it
133
- // on itself and by proxy on the HLS.js object.
134
- playback.currentLevel = 0
135
- expect(playback.currentLevel).to.equal(0)
136
- expect(playback.hls.currentLevel).to.equal(0)
137
- playback.currentLevel = 1
138
- expect(playback.currentLevel).to.equal(1)
139
- expect(playback.hls.currentLevel).to.equal(1)
334
+ expect(cb).not.toHaveBeenCalled()
140
335
  })
141
336
  })
142
337
  })