@npo/player 1.25.0 → 1.27.0

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 (249) hide show
  1. package/README.md +1 -1
  2. package/lib/js/playeractions/handlers/handleoffsets.js +9 -7
  3. package/lib/js/playeractions/handlers/handleoffsets.test.js +1 -1
  4. package/lib/js/playeractions/handlers/mediasessionactions.js +2 -2
  5. package/lib/js/playeractions/handlers/processplayerconfig.d.ts +1 -1
  6. package/lib/js/playeractions/handlers/processplayerconfig.js +4 -4
  7. package/lib/js/playeractions/handlers/processsourceconfig.d.ts +1 -0
  8. package/lib/js/playeractions/handlers/processsourceconfig.js +4 -5
  9. package/lib/js/playeractions/handlers/processsourceconfig.test.js +25 -0
  10. package/lib/js/playeractions/playeractions.d.ts +0 -1
  11. package/lib/js/playeractions/playeractions.js +0 -1
  12. package/lib/js/utilities/utilities.prid.d.ts +6 -0
  13. package/lib/js/utilities/utilities.prid.js +8 -0
  14. package/lib/js/utilities/utilities.prid.test.js +46 -0
  15. package/lib/lang/nl.json +1 -1
  16. package/lib/lang/subtitleLabels/nl.json +14 -0
  17. package/lib/npoplayer.d.ts +3 -4
  18. package/lib/npoplayer.js +66 -83
  19. package/lib/npoplayer.test.js +3 -3
  20. package/lib/package.json +2 -2
  21. package/lib/services/a11y/setup.js +2 -5
  22. package/lib/services/a11y/setup.test.js +2 -20
  23. package/lib/services/advertHandlers/discardAdBreak.js +6 -4
  24. package/lib/services/advertHandlers/discardAdBreak.test.js +31 -14
  25. package/lib/services/advertHandlers/handlePreRolls.js +19 -21
  26. package/lib/services/advertHandlers/handlePrerolls.test.js +66 -5
  27. package/lib/services/drmHandlers/decideprofile.js +8 -2
  28. package/lib/services/drmHandlers/decideprofile.test.js +5 -1
  29. package/lib/services/drmHandlers/verifydrm.js +7 -8
  30. package/lib/services/drmHandlers/verifydrm.test.js +32 -9
  31. package/lib/services/errors/errorBackground.test.js +48 -0
  32. package/lib/services/errors/errorHandler.d.ts +3 -0
  33. package/lib/services/errors/errorHandler.js +45 -0
  34. package/lib/services/errors/errorText.d.ts +2 -0
  35. package/lib/services/errors/errorText.js +59 -0
  36. package/lib/services/errors/errorText.test.js +66 -0
  37. package/lib/services/eventListenerHandlers/removeEventListeners.js +2 -2
  38. package/lib/services/eventListenerHandlers/removeEventListeners.test.js +9 -9
  39. package/lib/services/keyboardHandlers/resolvekeypress.js +21 -17
  40. package/lib/services/keyboardHandlers/resolvekeypress.test.js +1 -1
  41. package/lib/services/liveStreamHandlers/handleLiveStreamControls.js +2 -2
  42. package/lib/services/liveStreamHandlers/handleLiveStreamControls.test.js +2 -2
  43. package/lib/services/localStorageHandlers/localStorageHandlers.js +6 -3
  44. package/lib/services/localStorageHandlers/localStorageHandlers.test.js +2 -6
  45. package/lib/services/nicamHandlers/nicamhandler.d.ts +1 -2
  46. package/lib/services/nicamHandlers/nicamhandler.js +15 -18
  47. package/lib/services/nicamHandlers/nicamhandler.test.js +67 -9
  48. package/lib/services/npoPlayerAPI/contants.d.ts +20 -0
  49. package/lib/services/npoPlayerAPI/contants.js +6 -0
  50. package/lib/services/npoPlayerAPI/npoPlayerAPI.d.ts +6 -3
  51. package/lib/services/npoPlayerAPI/npoPlayerAPI.js +43 -26
  52. package/lib/services/npoPlayerAPI/npoPlayerAPI.test.js +11 -0
  53. package/lib/services/preferences/handlePreferences.d.ts +2 -0
  54. package/lib/services/preferences/handlePreferences.js +42 -0
  55. package/lib/services/preferences/handlePreferences.test.js +102 -0
  56. package/lib/services/segmentHandlers/addSegmentEventListeners.js +2 -2
  57. package/lib/services/segmentHandlers/addSegmentEventListeners.test.js +1 -1
  58. package/lib/services/services.d.ts +14 -4
  59. package/lib/services/services.js +49 -4
  60. package/lib/services/streamFetchHandler/fetchStream.d.ts +2 -0
  61. package/lib/services/streamFetchHandler/fetchStream.js +48 -0
  62. package/lib/services/streamFetchHandler/fetchstream.test.js +70 -0
  63. package/lib/services/streamoptionsHandlers/{steamOptionsHandler.js → streamOptionsHandler.js} +11 -11
  64. package/lib/services/streamoptionsHandlers/streamOptionsHandler.test.js +20 -20
  65. package/lib/services/trackingHandlers/eventBinding.d.ts +2 -0
  66. package/lib/{js/tracking/handlers/eventbinding.js → services/trackingHandlers/eventBinding.js} +16 -14
  67. package/lib/services/trackingHandlers/eventBinding.test.js +89 -0
  68. package/lib/services/trackingHandlers/eventLogging.d.ts +2 -0
  69. package/lib/{js/tracking/handlers/eventlogging.js → services/trackingHandlers/eventLogging.js} +18 -7
  70. package/lib/services/trackingHandlers/eventLogging.test.js +63 -0
  71. package/lib/services/trackingHandlers/index.d.ts +3 -0
  72. package/lib/services/trackingHandlers/index.js +3 -0
  73. package/lib/services/trackingHandlers/playerTrackerInit.d.ts +2 -0
  74. package/lib/{js/tracking/handlers/playertrackerinit.js → services/trackingHandlers/playerTrackerInit.js} +6 -3
  75. package/lib/services/trackingHandlers/playerTrackerInit.test.js +75 -0
  76. package/lib/services/trackingHandlers/playerTrackerStart.d.ts +2 -0
  77. package/lib/services/trackingHandlers/playerTrackerStart.js +25 -0
  78. package/lib/services/trackingHandlers/playerTrackerStart.test.js +59 -0
  79. package/lib/services/trackingHandlers/streamTrackerInit.d.ts +3 -0
  80. package/lib/services/trackingHandlers/streamTrackerInit.js +27 -0
  81. package/lib/services/trackingHandlers/streamTrackerInit.test.js +84 -0
  82. package/lib/services/uiHandlers/uiVisiblityHandler.d.ts +3 -0
  83. package/lib/services/uiHandlers/uiVisiblityHandler.js +26 -0
  84. package/lib/services/uiHandlers/uiVisiblityHandler.test.js +62 -0
  85. package/lib/services/verticalVideoHandlers/handleVerticalVideoControls.d.ts +2 -2
  86. package/lib/services/verticalVideoHandlers/handleVerticalVideoControls.js +4 -6
  87. package/lib/services/verticalVideoHandlers/handleVerticalVideoControls.test.js +4 -17
  88. package/lib/services/verticalVideoHandlers/handleVerticalVideoSettings.d.ts +2 -0
  89. package/lib/services/verticalVideoHandlers/handleVerticalVideoSettings.js +26 -0
  90. package/lib/services/verticalVideoHandlers/handleVerticalVideoSettings.test.d.ts +1 -0
  91. package/lib/services/verticalVideoHandlers/handleVerticalVideoSettings.test.js +82 -0
  92. package/lib/src/js/playeractions/handlers/processplayerconfig.d.ts +1 -1
  93. package/lib/src/js/playeractions/handlers/processsourceconfig.d.ts +1 -0
  94. package/lib/src/js/playeractions/handlers/processsourceconfig.test.d.ts +1 -0
  95. package/lib/src/js/playeractions/playeractions.d.ts +0 -1
  96. package/lib/src/js/utilities/utilities.prid.d.ts +6 -0
  97. package/lib/src/js/utilities/utilities.prid.test.d.ts +1 -0
  98. package/lib/src/npoplayer.d.ts +3 -4
  99. package/lib/src/services/errors/errorBackground.test.d.ts +1 -0
  100. package/lib/src/services/errors/errorHandler.d.ts +3 -0
  101. package/lib/src/services/errors/errorText.d.ts +2 -0
  102. package/lib/src/services/errors/errorText.test.d.ts +1 -0
  103. package/lib/src/services/nicamHandlers/nicamhandler.d.ts +1 -2
  104. package/lib/src/services/npoPlayerAPI/contants.d.ts +20 -0
  105. package/lib/src/services/npoPlayerAPI/npoPlayerAPI.d.ts +6 -3
  106. package/lib/src/services/preferences/handlePreferences.d.ts +2 -0
  107. package/lib/src/services/preferences/handlePreferences.test.d.ts +1 -0
  108. package/lib/src/services/services.d.ts +14 -4
  109. package/lib/src/services/streamFetchHandler/fetchStream.d.ts +2 -0
  110. package/lib/src/services/streamFetchHandler/fetchstream.test.d.ts +1 -0
  111. package/lib/src/services/trackingHandlers/eventBinding.d.ts +2 -0
  112. package/lib/src/services/trackingHandlers/eventBinding.test.d.ts +1 -0
  113. package/lib/src/services/trackingHandlers/eventLogging.d.ts +2 -0
  114. package/lib/src/services/trackingHandlers/eventLogging.test.d.ts +1 -0
  115. package/lib/src/services/trackingHandlers/index.d.ts +3 -0
  116. package/lib/src/services/trackingHandlers/playerTrackerInit.d.ts +2 -0
  117. package/lib/src/services/trackingHandlers/playerTrackerInit.test.d.ts +1 -0
  118. package/lib/src/services/trackingHandlers/playerTrackerStart.d.ts +2 -0
  119. package/lib/src/services/trackingHandlers/playerTrackerStart.test.d.ts +1 -0
  120. package/lib/src/services/trackingHandlers/streamTrackerInit.d.ts +3 -0
  121. package/lib/src/services/trackingHandlers/streamTrackerInit.test.d.ts +1 -0
  122. package/lib/src/services/uiHandlers/uiVisiblityHandler.d.ts +3 -0
  123. package/lib/src/services/uiHandlers/uiVisiblityHandler.test.d.ts +1 -0
  124. package/lib/src/services/verticalVideoHandlers/handleVerticalVideoControls.d.ts +2 -2
  125. package/lib/src/services/verticalVideoHandlers/handleVerticalVideoSettings.d.ts +2 -0
  126. package/lib/src/services/verticalVideoHandlers/handleVerticalVideoSettings.test.d.ts +1 -0
  127. package/lib/src/types/classes.d.ts +6 -0
  128. package/lib/src/types/interfaces.d.ts +39 -4
  129. package/lib/src/ui/components/adbutton.d.ts +1 -1
  130. package/lib/src/ui/components/adlabel.d.ts +1 -1
  131. package/lib/src/ui/components/buttons.d.ts +6 -16
  132. package/lib/src/ui/components/controlbar.d.ts +2 -2
  133. package/lib/src/ui/components/ctabar.d.ts +1 -1
  134. package/lib/src/ui/components/playnext.d.ts +1 -4
  135. package/lib/src/ui/components/seekbar.d.ts +2 -1
  136. package/lib/src/ui/components/titlebar.d.ts +1 -1
  137. package/lib/src/ui/components/verticalvideo/controlbar.d.ts +3 -3
  138. package/lib/src/ui/components/verticalvideo/settingspanel.d.ts +2 -0
  139. package/lib/src/ui/handlers/playnextscreen.test.d.ts +1 -0
  140. package/lib/src/ui/uicontainer.test.d.ts +1 -0
  141. package/lib/tests/mocks/mockLogEmitter.d.ts +2 -0
  142. package/lib/tests/mocks/mockLogEmitter.js +20 -0
  143. package/lib/tests/mocks/mockNpoplayer.js +2 -3
  144. package/lib/tests/mocks/mockStreamObject.d.ts +2 -0
  145. package/lib/tests/mocks/mockStreamObject.js +21 -0
  146. package/lib/tests/mocks/playerContextMock.d.ts +6 -3
  147. package/lib/tests/mocks/playerContextMock.js +12 -6
  148. package/lib/types/classes.d.ts +6 -0
  149. package/lib/types/classes.js +12 -0
  150. package/lib/types/interfaces.d.ts +39 -4
  151. package/lib/types/interfaces.js +1 -0
  152. package/lib/ui/components/adbutton.d.ts +1 -1
  153. package/lib/ui/components/adbutton.js +3 -3
  154. package/lib/ui/components/adlabel.d.ts +1 -1
  155. package/lib/ui/components/adlabel.js +3 -3
  156. package/lib/ui/components/audio/controlbar.js +2 -1
  157. package/lib/ui/components/buttons.d.ts +6 -16
  158. package/lib/ui/components/buttons.js +27 -10
  159. package/lib/ui/components/controlbar.d.ts +2 -2
  160. package/lib/ui/components/controlbar.js +21 -38
  161. package/lib/ui/components/ctabar.d.ts +1 -1
  162. package/lib/ui/components/ctabar.js +4 -4
  163. package/lib/ui/components/nativemobile/topbar.js +2 -2
  164. package/lib/ui/components/playnext.d.ts +1 -4
  165. package/lib/ui/components/playnext.js +3 -3
  166. package/lib/ui/components/seekbar.d.ts +2 -1
  167. package/lib/ui/components/seekbar.js +5 -3
  168. package/lib/ui/components/settingspanel.js +7 -9
  169. package/lib/ui/components/titlebar.d.ts +1 -1
  170. package/lib/ui/components/titlebar.js +2 -2
  171. package/lib/ui/components/topbar.js +6 -20
  172. package/lib/ui/components/verticalvideo/controlbar.d.ts +3 -3
  173. package/lib/ui/components/verticalvideo/controlbar.js +15 -12
  174. package/lib/ui/components/verticalvideo/settingspanel.d.ts +2 -0
  175. package/lib/ui/components/verticalvideo/settingspanel.js +21 -0
  176. package/lib/ui/handlers/domhandlers.test.js +6 -26
  177. package/lib/ui/handlers/playnextscreen.test.d.ts +1 -0
  178. package/lib/ui/nativemobileuifactory.js +2 -2
  179. package/lib/ui/nativemobileuifactory.test.js +2 -1
  180. package/lib/ui/uicontainer.js +14 -30
  181. package/lib/ui/uicontainer.test.d.ts +1 -0
  182. package/lib/ui/uicontainer.test.js +83 -0
  183. package/package.json +2 -2
  184. package/src/style/components/_advert.scss +3 -12
  185. package/src/style/components/_buffering.scss +14 -8
  186. package/src/style/components/_error.scss +44 -1
  187. package/src/style/components/_hugeplaybacktogglebutton.scss +1 -0
  188. package/src/style/components/_metadata.scss +13 -12
  189. package/src/style/components/_nicam.scss +16 -10
  190. package/src/style/components/_playnext.scss +1 -1
  191. package/src/style/components/_replay.scss +1 -6
  192. package/src/style/components/_settingspanel.scss +121 -95
  193. package/src/style/components/audio/_errors.scss +1 -1
  194. package/src/style/components/audio/_metadata.scss +14 -8
  195. package/src/style/components/audio/_playbutton.scss +1 -0
  196. package/src/style/components/audio/_topbar.scss +10 -2
  197. package/src/style/components/audio/_volumeslider.scss +3 -3
  198. package/src/style/components/vertical-video/_bottombar.scss +42 -1
  199. package/src/style/components/vertical-video/_hugeplaybacktogglebutton.scss +24 -4
  200. package/src/style/components/vertical-video/_settingspanel.scss +21 -4
  201. package/src/style/components/vertical-video/_topbar.scss +47 -6
  202. package/src/style/npoplayer.css +108 -70
  203. package/src/style/npoplayer.scss +4 -7
  204. package/src/style/variants/_player-base.scss +14 -2
  205. package/src/style/variants/_player-large.scss +5 -1
  206. package/src/style/variants/_player-small.scss +26 -9
  207. package/src/style/vars/_fonts.scss +13 -7
  208. package/src/style/vars/_z-index.scss +1 -0
  209. package/lib/js/api/getstreamobject.d.ts +0 -3
  210. package/lib/js/api/getstreamobject.js +0 -38
  211. package/lib/js/api/getstreamobject.test.js +0 -48
  212. package/lib/js/playeractions/customerrors.test.js +0 -51
  213. package/lib/js/playeractions/handlers/customerrors.d.ts +0 -50
  214. package/lib/js/playeractions/handlers/customerrors.js +0 -56
  215. package/lib/js/playeractions/handlers/error.d.ts +0 -3
  216. package/lib/js/playeractions/handlers/error.js +0 -14
  217. package/lib/js/playeractions/handlers/error.test.js +0 -44
  218. package/lib/js/tracking/handlers/eventbinding.d.ts +0 -3
  219. package/lib/js/tracking/handlers/eventlogging.d.ts +0 -2
  220. package/lib/js/tracking/handlers/eventlogging.test.js +0 -46
  221. package/lib/js/tracking/handlers/playertrackerinit.d.ts +0 -4
  222. package/lib/js/tracking/handlers/playertrackerinit.test.js +0 -74
  223. package/lib/js/tracking/handlers/playertrackerstart.d.ts +0 -1
  224. package/lib/js/tracking/handlers/playertrackerstart.js +0 -25
  225. package/lib/js/tracking/playertracker.d.ts +0 -4
  226. package/lib/js/tracking/playertracker.js +0 -4
  227. package/lib/src/js/api/getstreamobject.d.ts +0 -3
  228. package/lib/src/js/playeractions/handlers/customerrors.d.ts +0 -50
  229. package/lib/src/js/playeractions/handlers/error.d.ts +0 -3
  230. package/lib/src/js/tracking/handlers/eventbinding.d.ts +0 -3
  231. package/lib/src/js/tracking/handlers/eventlogging.d.ts +0 -2
  232. package/lib/src/js/tracking/handlers/playertrackerinit.d.ts +0 -4
  233. package/lib/src/js/tracking/handlers/playertrackerstart.d.ts +0 -1
  234. package/lib/src/js/tracking/playertracker.d.ts +0 -4
  235. /package/lib/js/{api/getstreamobject.test.d.ts → playeractions/handlers/processsourceconfig.test.d.ts} +0 -0
  236. /package/lib/js/{playeractions/customerrors.test.d.ts → utilities/utilities.prid.test.d.ts} +0 -0
  237. /package/lib/{js/playeractions/handlers/error.test.d.ts → services/errors/errorBackground.test.d.ts} +0 -0
  238. /package/lib/{js/tracking/handlers/eventlogging.test.d.ts → services/errors/errorText.test.d.ts} +0 -0
  239. /package/lib/{js/tracking/handlers/playertrackerinit.test.d.ts → services/preferences/handlePreferences.test.d.ts} +0 -0
  240. /package/lib/{src/js/api/getstreamobject.test.d.ts → services/streamFetchHandler/fetchstream.test.d.ts} +0 -0
  241. /package/lib/services/streamoptionsHandlers/{steamOptionsHandler.d.ts → streamOptionsHandler.d.ts} +0 -0
  242. /package/lib/{src/js/playeractions/customerrors.test.d.ts → services/trackingHandlers/eventBinding.test.d.ts} +0 -0
  243. /package/lib/{src/js/playeractions/handlers/error.test.d.ts → services/trackingHandlers/eventLogging.test.d.ts} +0 -0
  244. /package/lib/{src/js/tracking/handlers/eventlogging.test.d.ts → services/trackingHandlers/playerTrackerInit.test.d.ts} +0 -0
  245. /package/lib/{src/js/tracking/handlers/playertrackerinit.test.d.ts → services/trackingHandlers/playerTrackerStart.test.d.ts} +0 -0
  246. /package/lib/{src/ui/handlers/playnextstreen.test.d.ts → services/trackingHandlers/streamTrackerInit.test.d.ts} +0 -0
  247. /package/lib/{ui/handlers/playnextstreen.test.d.ts → services/uiHandlers/uiVisiblityHandler.test.d.ts} +0 -0
  248. /package/lib/src/services/streamoptionsHandlers/{steamOptionsHandler.d.ts → streamOptionsHandler.d.ts} +0 -0
  249. /package/lib/ui/handlers/{playnextstreen.test.js → playnextscreen.test.js} +0 -0
@@ -31,20 +31,16 @@ describe('setupAccessibilityAttributes', () => {
31
31
  };
32
32
  playerContext = {
33
33
  player: mockPlayerAPI,
34
- npoplayer: {
34
+ npoPlayer: {
35
35
  ...mockNpoPlayer,
36
36
  streamOptions: {
37
37
  enableSubtitles: false
38
38
  },
39
- userPreferences: {
40
- subtitles_enabled: 'false'
41
- },
42
39
  container: document.createElement('div'),
43
40
  streamObject: {},
44
41
  playerConfig: {},
45
42
  initPlayer: () => { },
46
43
  loadStream: () => Promise.resolve(),
47
- doError: () => { },
48
44
  play: async () => { },
49
45
  pause: () => { },
50
46
  setVolume: () => { },
@@ -69,20 +65,6 @@ describe('setupAccessibilityAttributes', () => {
69
65
  afterEach(() => {
70
66
  jest.clearAllMocks();
71
67
  });
72
- it('should enable subtitles if playerContext.npoplayer.userPreferences.subtitles_enabled is "true"', () => {
73
- playerContext.npoplayer.userPreferences.subtitles_enabled = 'true';
74
- setupAccessibilityAttributes(playerContext);
75
- const triggerFunction = mockAddEventListener.mock.calls[0][1];
76
- triggerFunction();
77
- expect(mockEnableSubtitles).toHaveBeenCalled();
78
- });
79
- it('should enable subtitles if streamOptions.enableSubtitles is true', () => {
80
- playerContext.npoplayer.streamOptions.enableSubtitles = true;
81
- setupAccessibilityAttributes(playerContext);
82
- const triggerFunction = mockAddEventListener.mock.calls[0][1];
83
- triggerFunction();
84
- expect(mockEnableSubtitles).toHaveBeenCalled();
85
- });
86
68
  it('should set up event listeners for specified events', () => {
87
69
  setupAccessibilityAttributes(playerContext);
88
70
  expect(mockAddEventListener).toHaveBeenCalledTimes(3);
@@ -103,6 +85,6 @@ describe('setupAccessibilityAttributes', () => {
103
85
  setupAccessibilityAttributes(playerContext);
104
86
  const triggerFunction = mockAddEventListener.mock.calls[0][1];
105
87
  triggerFunction();
106
- expect(addAccessibilityAttributes).toHaveBeenCalledWith(playerContext.npoplayer.container, playerContext.npoplayer.streamObject.metadata);
88
+ expect(addAccessibilityAttributes).toHaveBeenCalledWith(playerContext.npoPlayer.container, playerContext.npoPlayer.streamObject.metadata);
107
89
  });
108
90
  });
@@ -1,11 +1,13 @@
1
+ import { NpoPlayerUIVariants } from '../../types/interfaces';
1
2
  export function discardAdBreak(playerContext) {
2
- const { npoplayer, player } = playerContext;
3
- const { adBreakActive } = npoplayer;
3
+ const { npoPlayer, player } = playerContext;
4
+ const { adBreakActive } = npoPlayer;
4
5
  if (!player || adBreakActive === false)
5
6
  return;
7
+ void playerContext.player.createUIManager(playerContext, NpoPlayerUIVariants.DEFAULT);
6
8
  const activeAdBreak = player.getActiveAdBreak();
7
9
  if (activeAdBreak?.id) {
8
- player.discardAdBreak(activeAdBreak.id);
10
+ player.playerAPI.ads.discardAdBreak(activeAdBreak.id);
9
11
  }
10
- npoplayer.adBreakActive = false;
12
+ npoPlayer.adBreakActive = false;
11
13
  }
@@ -1,60 +1,77 @@
1
1
  import createPlayerContextMock, { createMockNpoPlayer, createMockNpoPlayerAPI } from '../../../tests/mocks/playerContextMock';
2
+ import { NpoPlayerUIVariants } from '../../types/interfaces';
2
3
  import { discardAdBreak } from './discardAdBreak';
3
4
  describe('discardAdBreak', () => {
4
5
  let mockNpoPlayerAPI;
5
- let npoplayerMock;
6
+ let npoPlayerMock;
6
7
  const activeAdBreakMock = { id: 'ad-break-id' };
7
8
  afterEach(() => {
8
9
  jest.resetAllMocks();
9
10
  });
11
+ it('should not discard ad break if player is undefined', () => {
12
+ npoPlayerMock = createMockNpoPlayer({
13
+ adBreakActive: true
14
+ });
15
+ const playerContextMock = createPlayerContextMock({
16
+ player: undefined,
17
+ npoPlayer: npoPlayerMock
18
+ });
19
+ discardAdBreak(playerContextMock);
20
+ expect(npoPlayerMock.adBreakActive).toBe(true);
21
+ });
10
22
  it('should not discard ad break if adBreakActive is false', () => {
11
23
  mockNpoPlayerAPI = createMockNpoPlayerAPI({
12
- getActiveAdBreak: jest.fn().mockReturnValue(undefined),
24
+ getActiveAdBreak: jest.fn().mockReturnValue(activeAdBreakMock),
13
25
  discardAdBreak: jest.fn()
14
26
  });
15
- npoplayerMock = createMockNpoPlayer({
27
+ npoPlayerMock = createMockNpoPlayer({
16
28
  adBreakActive: false
17
29
  });
18
30
  const playerContextMock = createPlayerContextMock({
19
31
  player: mockNpoPlayerAPI,
20
- npoplayer: npoplayerMock
32
+ npoPlayer: npoPlayerMock
21
33
  });
22
34
  discardAdBreak(playerContextMock);
23
35
  expect(mockNpoPlayerAPI.getActiveAdBreak).not.toHaveBeenCalled();
24
- expect(mockNpoPlayerAPI.discardAdBreak).not.toHaveBeenCalled();
36
+ expect(mockNpoPlayerAPI.playerAPI.ads.discardAdBreak).not.toHaveBeenCalled();
37
+ expect(npoPlayerMock.adBreakActive).toBe(false);
38
+ expect(playerContextMock.player.createUIManager).not.toHaveBeenCalled();
25
39
  });
26
40
  it('should discard active ad break if adBreakActive is true and ad break exists', () => {
27
41
  mockNpoPlayerAPI = createMockNpoPlayerAPI({
28
42
  getActiveAdBreak: jest.fn().mockReturnValue(activeAdBreakMock),
29
- discardAdBreak: jest.fn()
43
+ discardAdBreak: jest.fn(),
44
+ variant: NpoPlayerUIVariants.AD
30
45
  });
31
- npoplayerMock = createMockNpoPlayer({
46
+ npoPlayerMock = createMockNpoPlayer({
32
47
  adBreakActive: true
33
48
  });
34
49
  const playerContextMock = createPlayerContextMock({
35
50
  player: mockNpoPlayerAPI,
36
- npoplayer: npoplayerMock
51
+ npoPlayer: npoPlayerMock
37
52
  });
38
53
  discardAdBreak(playerContextMock);
39
54
  expect(mockNpoPlayerAPI.getActiveAdBreak).toHaveBeenCalled();
40
- expect(mockNpoPlayerAPI.discardAdBreak).toHaveBeenCalledWith(activeAdBreakMock.id);
41
- expect(npoplayerMock.adBreakActive).toBe(false);
55
+ expect(mockNpoPlayerAPI.playerAPI.ads.discardAdBreak).toHaveBeenCalledWith(activeAdBreakMock.id);
56
+ expect(npoPlayerMock.adBreakActive).toBe(false);
57
+ expect(playerContextMock.player.createUIManager).toHaveBeenCalledWith(playerContextMock, NpoPlayerUIVariants.DEFAULT);
42
58
  });
43
59
  it('should not discard ad break if active ad break does not exist', () => {
44
60
  mockNpoPlayerAPI = createMockNpoPlayerAPI({
45
61
  getActiveAdBreak: jest.fn().mockReturnValue(undefined),
46
62
  discardAdBreak: jest.fn()
47
63
  });
48
- npoplayerMock = createMockNpoPlayer({
64
+ npoPlayerMock = createMockNpoPlayer({
49
65
  adBreakActive: true
50
66
  });
51
67
  const playerContextMock = createPlayerContextMock({
52
68
  player: mockNpoPlayerAPI,
53
- npoplayer: npoplayerMock
69
+ npoPlayer: npoPlayerMock
54
70
  });
55
71
  discardAdBreak(playerContextMock);
56
72
  expect(mockNpoPlayerAPI.getActiveAdBreak).toHaveBeenCalled();
57
- expect(mockNpoPlayerAPI.discardAdBreak).not.toHaveBeenCalled();
58
- expect(npoplayerMock.adBreakActive).toBe(false);
73
+ expect(mockNpoPlayerAPI.playerAPI.ads.discardAdBreak).not.toHaveBeenCalled();
74
+ expect(npoPlayerMock.adBreakActive).toBe(false);
75
+ expect(playerContextMock.player.createUIManager).toHaveBeenCalledWith(playerContextMock, NpoPlayerUIVariants.DEFAULT);
59
76
  });
60
77
  });
@@ -3,12 +3,12 @@ import { NpoPlayerUIVariants } from '../../types/interfaces';
3
3
  import { NpoPlayerEvent } from '../../types/events';
4
4
  export async function handlePreRolls(playerContext) {
5
5
  return new Promise((resolve) => {
6
- if (playerContext.npoplayer.streamObject.metadata.hasPreroll == 'false' ||
7
- playerContext.npoplayer.streamObject.assets.preroll == undefined) {
6
+ if (playerContext.npoPlayer.streamObject.metadata.hasPreroll == 'false' ||
7
+ playerContext.npoPlayer.streamObject.assets.preroll == undefined) {
8
8
  resolve();
9
9
  return;
10
10
  }
11
- const prerollUrl = playerContext.npoplayer.streamObject.assets.preroll;
11
+ const prerollUrl = playerContext.npoPlayer.streamObject.assets.preroll;
12
12
  let adIndex = 0;
13
13
  let totalAds = 0;
14
14
  let currentClickListener;
@@ -26,7 +26,7 @@ export async function handlePreRolls(playerContext) {
26
26
  await playerContext.player.scheduleAds(advertConfig);
27
27
  }
28
28
  playerContext.player.on(NpoPlayerEvent.Ready, handleReady);
29
- async function handlePlay() {
29
+ function handlePlay() {
30
30
  playerContext.player.off(NpoPlayerEvent.Play, handlePlay);
31
31
  attemptSetAdUi();
32
32
  }
@@ -35,13 +35,11 @@ export async function handlePreRolls(playerContext) {
35
35
  const activeAdBreak = playerContext.player.getActiveAdBreak();
36
36
  if (!activeAdBreak || !activeAdBreak.ads)
37
37
  return false;
38
- playerContext.npoplayer.uiManager?.release();
39
- playerContext.npoplayer.uiManager = undefined;
40
- if (playerContext.npoplayer.playerContext) {
41
- playerContext.player.createUIManager(playerContext, NpoPlayerUIVariants.AD);
42
- }
38
+ playerContext.npoPlayer.uiManager?.release();
39
+ playerContext.npoPlayer.uiManager = undefined;
40
+ void playerContext.player.createUIManager(playerContext, NpoPlayerUIVariants.AD);
43
41
  adUiSet = true;
44
- const adButton = playerContext.npoplayer.uiComponents.adbutton;
42
+ const adButton = playerContext.npoPlayer.uiComponents.adbutton;
45
43
  const currentAd = activeAdBreak.ads[0];
46
44
  adIndex = 1;
47
45
  totalAds = activeAdBreak.ads.length;
@@ -49,7 +47,7 @@ export async function handlePreRolls(playerContext) {
49
47
  adButton.show();
50
48
  adClickHandler(currentAd, adButton);
51
49
  }
52
- playerContext.npoplayer.uiComponents.adlabel?.setText(`Advertentie 1 van ${activeAdBreak.ads.length}`);
50
+ playerContext.npoPlayer.uiComponents.adlabel?.setText(`Advertentie 1 van ${activeAdBreak.ads.length}`);
53
51
  return true;
54
52
  }
55
53
  function attemptSetAdUi(attemptsLeft = 10) {
@@ -71,7 +69,7 @@ export async function handlePreRolls(playerContext) {
71
69
  }
72
70
  if (!adUiSet)
73
71
  attemptSetAdUi();
74
- playerContext.npoplayer.adBreakActive = true;
72
+ playerContext.npoPlayer.adBreakActive = true;
75
73
  }
76
74
  playerContext.player.on(NpoPlayerEvent.AdStarted, handleAdStarted);
77
75
  function adClickHandler(ad, button) {
@@ -102,26 +100,26 @@ export async function handlePreRolls(playerContext) {
102
100
  handleAdBreakFinished();
103
101
  return;
104
102
  }
105
- const adButton = playerContext.npoplayer.uiComponents.adbutton;
103
+ const adButton = playerContext.npoPlayer.uiComponents.adbutton;
106
104
  const nextAd = activeAdBreak.ads[adIndex];
107
105
  adIndex += 1;
108
106
  if (adButton) {
109
107
  adButton.show();
110
108
  adClickHandler(nextAd, adButton);
111
109
  }
112
- playerContext.npoplayer.uiComponents.adlabel?.setText(`Advertentie ${adIndex} van ${activeAdBreak.ads.length}`);
110
+ playerContext.npoPlayer.uiComponents.adlabel?.setText(`Advertentie ${adIndex} van ${activeAdBreak.ads.length}`);
113
111
  }
114
112
  playerContext.player.on(NpoPlayerEvent.AdFinished, handleAdFinished);
115
113
  function handleAdBreakFinished() {
116
114
  playerContext.player.off(NpoPlayerEvent.AdBreakFinished, handleAdBreakFinished);
117
115
  playerContext.player.off(NpoPlayerEvent.AdError, handleAdBreakFinished);
118
- playerContext.npoplayer.adBreakActive = false;
119
- playerContext.npoplayer.uiComponents.adbutton?.hide();
120
- playerContext.npoplayer.uiComponents.adlabel?.hide();
121
- playerContext.npoplayer.uiManager?.release();
122
- playerContext.npoplayer.uiManager = undefined;
123
- if (playerContext.npoplayer.playerContext) {
124
- playerContext.player.createUIManager(playerContext, NpoPlayerUIVariants.DEFAULT);
116
+ playerContext.npoPlayer.adBreakActive = false;
117
+ playerContext.npoPlayer.uiComponents.adbutton?.hide();
118
+ playerContext.npoPlayer.uiComponents.adlabel?.hide();
119
+ playerContext.npoPlayer.uiManager?.release();
120
+ playerContext.npoPlayer.uiManager = undefined;
121
+ if (playerContext.npoPlayer.playerContext) {
122
+ void playerContext.player.createUIManager(playerContext, NpoPlayerUIVariants.DEFAULT);
125
123
  }
126
124
  adUiSet = false;
127
125
  resolve();
@@ -1,4 +1,5 @@
1
1
  import { handlePreRolls } from './handlePreRolls';
2
+ import { PlayerEvent } from 'bitmovin-player/modules/bitmovinplayer-core';
2
3
  import { createMockNpoPlayer, createPlayerContextMock } from '../../../tests/mocks/playerContextMock';
3
4
  jest.mock('bitmovin-player');
4
5
  jest.mock('../../npoplayer');
@@ -11,11 +12,12 @@ describe('handlePreRolls', () => {
11
12
  getActiveAdBreak: jest.fn()
12
13
  },
13
14
  on: jest.fn(),
14
- off: jest.fn()
15
+ off: jest.fn(),
16
+ scheduleAds: jest.fn()
15
17
  };
16
18
  });
17
19
  it('should not schedule ads when hasPreroll is false', async () => {
18
- const npoplayerMock = createMockNpoPlayer({
20
+ const npoPlayerMock = createMockNpoPlayer({
19
21
  streamObject: {
20
22
  metadata: {
21
23
  hasPreroll: 'false'
@@ -26,13 +28,13 @@ describe('handlePreRolls', () => {
26
28
  }
27
29
  });
28
30
  const playerContextMock = createPlayerContextMock({
29
- npoplayer: npoplayerMock
31
+ npoPlayer: npoPlayerMock
30
32
  });
31
33
  await handlePreRolls(playerContextMock);
32
34
  expect(mockPlayerAPI.ads.schedule).not.toHaveBeenCalled();
33
35
  });
34
36
  it('should not schedule ads if preroll URL is missing', async () => {
35
- const npoplayerMock = createMockNpoPlayer({
37
+ const npoPlayerMock = createMockNpoPlayer({
36
38
  streamObject: {
37
39
  metadata: {
38
40
  hasPreroll: 'true'
@@ -41,7 +43,7 @@ describe('handlePreRolls', () => {
41
43
  }
42
44
  });
43
45
  const playerContextMock = createPlayerContextMock({
44
- npoplayer: npoplayerMock
46
+ npoPlayer: npoPlayerMock
45
47
  });
46
48
  await handlePreRolls(playerContextMock);
47
49
  expect(mockPlayerAPI.ads.schedule).not.toHaveBeenCalled();
@@ -49,4 +51,63 @@ describe('handlePreRolls', () => {
49
51
  afterEach(() => {
50
52
  jest.clearAllMocks();
51
53
  });
54
+ it('should schedule ads when hasPreroll is true and preroll URL exists', async () => {
55
+ await new Promise((resolve) => setTimeout(resolve, 0));
56
+ const npoPlayerMock = createMockNpoPlayer({
57
+ streamObject: {
58
+ metadata: {
59
+ hasPreroll: 'true'
60
+ },
61
+ assets: {
62
+ preroll: 'sample_url'
63
+ }
64
+ }
65
+ });
66
+ const playerContextMock = createPlayerContextMock({
67
+ npoPlayer: npoPlayerMock,
68
+ player: mockPlayerAPI
69
+ });
70
+ const readyCallback = jest.fn();
71
+ mockPlayerAPI.on.mockImplementation((event, callback) => {
72
+ if (event === PlayerEvent.Ready) {
73
+ readyCallback.mockImplementation(callback);
74
+ }
75
+ });
76
+ void handlePreRolls(playerContextMock);
77
+ readyCallback();
78
+ expect(playerContextMock.player.scheduleAds).toHaveBeenCalledWith({
79
+ tag: {
80
+ url: 'sample_url',
81
+ type: 'vast'
82
+ },
83
+ id: 'Ad',
84
+ position: 'pre'
85
+ });
86
+ });
87
+ it('should cleanup UI and resolve when AdBreakFinished event occurs', async () => {
88
+ const npoPlayerMock = createMockNpoPlayer({
89
+ streamObject: {
90
+ metadata: {
91
+ hasPreroll: 'true'
92
+ },
93
+ assets: {
94
+ preroll: 'sample_url'
95
+ }
96
+ }
97
+ });
98
+ const playerContextMock = createPlayerContextMock({
99
+ npoPlayer: npoPlayerMock,
100
+ player: mockPlayerAPI
101
+ });
102
+ const adBreakFinishedHandler = jest.fn();
103
+ mockPlayerAPI.on.mockImplementation((event, handler) => {
104
+ if (event === PlayerEvent.AdBreakFinished) {
105
+ adBreakFinishedHandler.mockImplementation(handler);
106
+ }
107
+ });
108
+ const handlePromise = handlePreRolls(playerContextMock);
109
+ adBreakFinishedHandler();
110
+ await handlePromise;
111
+ expect(playerContextMock.npoPlayer.uiManager).toBeUndefined();
112
+ });
52
113
  });
@@ -5,7 +5,7 @@ export async function decideProfile(playerContext, preferredDRM = '') {
5
5
  console.error('No player detected');
6
6
  return { profileName: '', drm: '' };
7
7
  }
8
- const player = playerContext.player;
8
+ const { player } = playerContext;
9
9
  const supportedTech = player.getSupportedTech();
10
10
  const supportedDRM = await player.getSupportedDRM();
11
11
  const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
@@ -15,7 +15,7 @@ export async function decideProfile(playerContext, preferredDRM = '') {
15
15
  }
16
16
  const { bestWithDRM, bestDRM } = determineBestWithDRM(supportedTech, { supportedDRM, preferredDRM });
17
17
  const bestWithoutDRM = determineBestWithoutDRM(supportedTech);
18
- return bestWithDRM ? { profileName: bestWithDRM, drm: bestDRM } : { profileName: bestWithoutDRM, drm: bestDRM };
18
+ return bestWithDRM ? { profileName: bestWithDRM, drm: bestDRM } : { profileName: bestWithoutDRM, drm: '' };
19
19
  }
20
20
  function determineBestWithDRM(supportedTech, drmInfo) {
21
21
  let bestWithDRM = '';
@@ -33,6 +33,12 @@ function determineBestWithDRM(supportedTech, drmInfo) {
33
33
  continue;
34
34
  if (techMap[tech.streaming]) {
35
35
  const { drm, stream } = techMap[tech.streaming];
36
+ if ((drmInfo.preferredDRM === DRM_TYPES.PLAYREADY || drmInfo.supportedDRM.includes(DRM_TYPES.PLAYREADY)) &&
37
+ tech.streaming === STREAM_TYPES.DASH) {
38
+ bestWithDRM = STREAM_TYPES.DASH;
39
+ bestDRM = DRM_TYPES.PLAYREADY;
40
+ break;
41
+ }
36
42
  if (drmInfo.preferredDRM !== drm) {
37
43
  bestDRM =
38
44
  tech.streaming === STREAM_TYPES.DASH ? getBestDRMForDash(drmInfo) : getBestDRMForHls(drmInfo);
@@ -13,7 +13,7 @@ describe('decideProfile', () => {
13
13
  .fn()
14
14
  .mockResolvedValue(['com.widevine.alpha', 'com.microsoft.playready', 'com.apple.fps.1_0'])
15
15
  };
16
- mockPlayerContext = { player: mockPlayer, npoplayer: mockNpoplayer };
16
+ mockPlayerContext = { player: mockPlayer, npoPlayer: mockNpoplayer };
17
17
  });
18
18
  afterEach(() => {
19
19
  jest.clearAllMocks();
@@ -31,4 +31,8 @@ describe('decideProfile', () => {
31
31
  const result = await decideProfile(mockPlayerContext, DRM_TYPES.FAIRPLAY);
32
32
  expect(result).toEqual({ profileName: STREAM_TYPES.HLS, drm: DRM_TYPES.FAIRPLAY });
33
33
  });
34
+ it('should return profile with dash streaming and playready DRM when preferred DRM is PlayReady', async () => {
35
+ const result = await decideProfile(mockPlayerContext, DRM_TYPES.PLAYREADY);
36
+ expect(result).toEqual({ profileName: STREAM_TYPES.DASH, drm: DRM_TYPES.PLAYREADY });
37
+ });
34
38
  });
@@ -1,8 +1,7 @@
1
1
  import { convertJwtToBase64, convertBase64ToObject } from '../../js/utilities/utilities.jwt';
2
- import { getStreamObject } from '../../js/api/getstreamobject';
3
2
  export async function verifyDRM(playerContext, payload) {
4
3
  try {
5
- const { player, npoplayer: { streamObject, sourceConfig } } = playerContext;
4
+ const { player, npoPlayer: { streamObject, sourceConfig } } = playerContext;
6
5
  const { stream } = streamObject;
7
6
  if (stream.drmToken) {
8
7
  const drmJsonTimestamp = getDRMTokenTimestamp(stream.drmToken);
@@ -29,12 +28,12 @@ function getDRMTokenTimestamp(drmToken) {
29
28
  return convertBase64ToObject(drmBase64).iat;
30
29
  }
31
30
  async function refreshDRMToken(playerContext, payload) {
32
- const backupStreamObject = await getStreamObject(playerContext.npoplayer, payload);
33
- const newDrmToken = backupStreamObject.stream.drmToken;
31
+ const { npoPlayer: { npoPlayerServices, streamObject, sourceConfig } } = playerContext;
32
+ const { stream: { drmToken: newDrmToken } } = await npoPlayerServices.fetchStream(playerContext, payload);
34
33
  const clonedStreamObject = {
35
- ...playerContext.npoplayer.streamObject,
36
- stream: { ...playerContext.npoplayer.streamObject.stream, drmToken: newDrmToken }
34
+ ...streamObject,
35
+ stream: { ...streamObject.stream, drmToken: newDrmToken }
37
36
  };
38
- playerContext.npoplayer.streamObject = clonedStreamObject;
39
- await loadPlayer(playerContext, playerContext.npoplayer.sourceConfig);
37
+ playerContext.npoPlayer.streamObject = clonedStreamObject;
38
+ await loadPlayer(playerContext, sourceConfig);
40
39
  }
@@ -1,24 +1,42 @@
1
1
  import { verifyDRM } from './verifydrm';
2
2
  import { mockNpoPlayer } from '../../../tests/mocks/mockNpoplayer';
3
3
  import { convertBase64ToObject, convertJwtToBase64 } from '../../js/utilities/utilities.jwt';
4
- import { getStreamObject } from '../../js/api/getstreamobject';
5
4
  jest.mock('../../js/utilities/utilities.jwt', () => ({
6
5
  convertBase64ToObject: jest.fn(),
7
6
  convertJwtToBase64: jest.fn()
8
7
  }));
9
- jest.mock('../../js/api/getstreamobject', () => ({
10
- getStreamObject: jest.fn()
8
+ jest.mock('../streamFetchHandler/fetchStream', () => ({
9
+ fetchStream: jest.fn()
11
10
  }));
12
11
  let mockPlayer;
13
12
  const mockNpoplayer = mockNpoPlayer;
14
13
  let mockPlayerContext;
14
+ function createMockStreamObject(overrides = {}) {
15
+ return {
16
+ stream: {
17
+ avType: '',
18
+ drmType: '',
19
+ streamProfile: '',
20
+ sourceProfile: '',
21
+ streamURL: '',
22
+ drmToken: 'newToken'
23
+ },
24
+ metadata: { description: 'default description', title: 'default title' },
25
+ assets: { scrubbingThumbnail: 'thumbnail.jpg', subtitles: [] },
26
+ user: { type: 'anonymous' },
27
+ ...overrides
28
+ };
29
+ }
15
30
  beforeEach(() => {
16
31
  jest.clearAllMocks();
17
32
  mockPlayer = {
18
33
  streamObject: { stream: { drmToken: undefined } },
19
34
  load: jest.fn()
20
35
  };
21
- mockPlayerContext = { player: mockPlayer, npoplayer: mockNpoplayer };
36
+ mockNpoplayer.npoPlayerServices = {
37
+ fetchStream: jest.fn()
38
+ };
39
+ mockPlayerContext = { player: mockPlayer, npoPlayer: mockNpoplayer };
22
40
  });
23
41
  afterEach(() => {
24
42
  jest.clearAllMocks();
@@ -42,7 +60,7 @@ describe('Test DRM verification', () => {
42
60
  streamURL: '',
43
61
  drmToken: drmToken
44
62
  };
45
- mockPlayerContext.npoplayer.sourceConfig = sourceConfig;
63
+ mockPlayerContext.npoPlayer.sourceConfig = sourceConfig;
46
64
  jest.spyOn(global.Date, 'now').mockImplementation(() => currentTime * 1000);
47
65
  convertJwtToBase64.mockReturnValue(JSON.stringify({ iat: drmJsonTimestamp }));
48
66
  convertBase64ToObject.mockReturnValue({ iat: drmJsonTimestamp });
@@ -62,14 +80,19 @@ describe('Test DRM verification', () => {
62
80
  streamURL: '',
63
81
  drmToken: drmToken
64
82
  };
65
- mockPlayerContext.npoplayer.sourceConfig = sourceConfig;
83
+ mockPlayerContext.npoPlayer.sourceConfig = sourceConfig;
66
84
  jest.spyOn(global.Date, 'now').mockImplementation(() => currentTime * 1000);
67
85
  convertJwtToBase64.mockReturnValue(JSON.stringify({ iat: drmJsonTimestamp }));
68
86
  convertBase64ToObject.mockReturnValue({ iat: drmJsonTimestamp });
69
- getStreamObject.mockResolvedValue({ stream: { drmToken: 'newToken' } });
87
+ jest.spyOn(mockNpoplayer.npoPlayerServices, 'fetchStream').mockResolvedValue(createMockStreamObject({
88
+ stream: {
89
+ ...createMockStreamObject().stream,
90
+ drmToken: 'overriddenToken'
91
+ }
92
+ }));
70
93
  jest.spyOn(mockPlayerContext.player, 'load').mockResolvedValue(undefined);
71
94
  await verifyDRM(mockPlayerContext, payload);
72
- expect(getStreamObject).toHaveBeenCalledWith(mockPlayerContext.npoplayer, payload);
95
+ expect(mockNpoplayer.npoPlayerServices.fetchStream).toHaveBeenCalledWith(mockPlayerContext, payload);
73
96
  expect(mockPlayerContext.player.load).toHaveBeenCalledWith(sourceConfig);
74
97
  });
75
98
  it('should call loadPlayer when the drmToken is null', async () => {
@@ -82,7 +105,7 @@ describe('Test DRM verification', () => {
82
105
  streamURL: '',
83
106
  drmToken: undefined
84
107
  };
85
- mockPlayerContext.npoplayer.sourceConfig = sourceConfig;
108
+ mockPlayerContext.npoPlayer.sourceConfig = sourceConfig;
86
109
  await verifyDRM(mockPlayerContext, payload);
87
110
  expect(mockPlayerContext.player.load).toHaveBeenCalledWith(sourceConfig);
88
111
  });
@@ -0,0 +1,48 @@
1
+ import { setErrorBackground } from './errorHandler';
2
+ const posterUrl = 'https://example.com/poster.jpg';
3
+ describe('setErrorBackground', () => {
4
+ it('sets the error background image correctly', () => {
5
+ const mockPlayerContainer = document.createElement('div');
6
+ const mockPlayerContext = {
7
+ player: {
8
+ getNpoPlayerElement: jest.fn(() => mockPlayerContainer)
9
+ },
10
+ npoPlayer: {
11
+ sourceConfig: {
12
+ poster: posterUrl
13
+ }
14
+ }
15
+ };
16
+ setErrorBackground(mockPlayerContext);
17
+ expect(mockPlayerContainer.style.getPropertyValue('--npo-player-errormessage-background-image')).toBe(posterUrl);
18
+ });
19
+ it('sets the error background image to "none" if poster is not provided', () => {
20
+ const mockPlayerContainer = document.createElement('div');
21
+ const mockPlayerContext = {
22
+ player: {
23
+ getNpoPlayerElement: jest.fn(() => mockPlayerContainer)
24
+ },
25
+ npoPlayer: {
26
+ sourceConfig: {
27
+ poster: undefined
28
+ }
29
+ }
30
+ };
31
+ setErrorBackground(mockPlayerContext);
32
+ expect(mockPlayerContainer.style.getPropertyValue('--npo-player-errormessage-background-image')).toBe('none');
33
+ });
34
+ it('does nothing if getNpoPlayerElement returns undefined', () => {
35
+ const mockPlayerContext = {
36
+ player: {
37
+ getNpoPlayerElement: jest.fn(() => undefined)
38
+ },
39
+ npoPlayer: {
40
+ sourceConfig: {
41
+ poster: posterUrl
42
+ }
43
+ }
44
+ };
45
+ setErrorBackground(mockPlayerContext);
46
+ expect(() => setErrorBackground(mockPlayerContext)).not.toThrow();
47
+ });
48
+ });
@@ -0,0 +1,3 @@
1
+ import { PlayerContext } from '../../types/interfaces';
2
+ export declare function handlePlayerError(playerContext: PlayerContext, status: number): Promise<void>;
3
+ export declare function setErrorBackground(playerContext: PlayerContext): void;
@@ -0,0 +1,45 @@
1
+ import { customSpecificErrorMessageOverlayConfig, npoBusinessErrors } from './errorText';
2
+ export async function handlePlayerError(playerContext, status) {
3
+ const { player, npoPlayer } = playerContext;
4
+ const uiComponents = npoPlayer.uiComponents;
5
+ const errorContainerClass = 'npo-player-error';
6
+ const shouldRetry = status >= 1000 && npoPlayer.streamOptions.retryCallback !== undefined;
7
+ const message = generateErrorMessage(status, shouldRetry);
8
+ await player.unload();
9
+ uiComponents.controlBar?.hide();
10
+ const errorMessageOverlay = uiComponents.errorMessageOverlay;
11
+ if (!errorMessageOverlay)
12
+ return;
13
+ player.addClassToNpoPlayerElement(errorContainerClass);
14
+ setErrorBackground(playerContext);
15
+ errorMessageOverlay.display(message);
16
+ if (shouldRetry) {
17
+ setupRetryHandler(playerContext, errorContainerClass);
18
+ }
19
+ }
20
+ function generateErrorMessage(status, shouldRetry) {
21
+ const baseMessage = npoBusinessErrors[status] ?? customSpecificErrorMessageOverlayConfig[status] ?? 'De video kan niet worden geladen';
22
+ const retryMessage = shouldRetry
23
+ ? '<br>Klik om het opnieuw te proberen.<br><br><button class="retry-button">Opnieuw proberen</button>'
24
+ : '';
25
+ return `<span class="errorcode">Foutcode ${status}</span>\n${baseMessage}${retryMessage}`;
26
+ }
27
+ function setupRetryHandler(playerContext, errorContainerClass) {
28
+ const playerContainer = playerContext.player.getNpoPlayerElement();
29
+ playerContainer.addEventListener('click', (event) => {
30
+ const target = event.target;
31
+ if (target.classList.contains('retry-button') && playerContainer.classList.contains(errorContainerClass)) {
32
+ target.style.visibility = 'hidden';
33
+ playerContext.player.handleErrorRetry(playerContext);
34
+ playerContext.player.removeClassFromNpoPlayerElement(errorContainerClass);
35
+ setTimeout(() => {
36
+ target.style.visibility = 'visible';
37
+ }, 200);
38
+ }
39
+ });
40
+ }
41
+ export function setErrorBackground(playerContext) {
42
+ const playerContainer = playerContext.player.getNpoPlayerElement();
43
+ const posterImage = playerContext.npoPlayer.sourceConfig.poster;
44
+ playerContainer?.style.setProperty('--npo-player-errormessage-background-image', posterImage || 'none');
45
+ }
@@ -0,0 +1,2 @@
1
+ export declare const customSpecificErrorMessageOverlayConfig: Record<number, string>;
2
+ export declare const npoBusinessErrors: Record<number, string>;