@npo/player 1.26.0 → 1.27.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.
Files changed (180) hide show
  1. package/README.md +1 -1
  2. package/lib/js/playeractions/handlers/mediasessionactions.js +2 -2
  3. package/lib/js/playeractions/playeractions.d.ts +0 -1
  4. package/lib/js/playeractions/playeractions.js +0 -1
  5. package/lib/js/utilities/utilities.prid.d.ts +6 -0
  6. package/lib/js/utilities/utilities.prid.js +8 -0
  7. package/lib/js/utilities/utilities.prid.test.js +46 -0
  8. package/lib/npoplayer.d.ts +1 -1
  9. package/lib/npoplayer.js +52 -69
  10. package/lib/npoplayer.test.js +2 -2
  11. package/lib/package.json +1 -1
  12. package/lib/services/a11y/setup.test.js +0 -1
  13. package/lib/services/advertHandlers/discardAdBreak.js +2 -0
  14. package/lib/services/advertHandlers/discardAdBreak.test.js +6 -1
  15. package/lib/services/advertHandlers/handlePreRolls.js +2 -4
  16. package/lib/services/advertHandlers/handlePrerolls.test.js +62 -1
  17. package/lib/services/drmHandlers/decideprofile.js +7 -1
  18. package/lib/services/drmHandlers/decideprofile.test.js +4 -0
  19. package/lib/services/drmHandlers/utils.js +4 -1
  20. package/lib/services/drmHandlers/utils.test.js +7 -0
  21. package/lib/services/drmHandlers/verifydrm.js +5 -6
  22. package/lib/services/drmHandlers/verifydrm.test.js +28 -5
  23. package/lib/services/errors/errorBackground.test.js +48 -0
  24. package/lib/services/errors/errorHandler.d.ts +3 -0
  25. package/lib/services/errors/errorHandler.js +46 -0
  26. package/lib/services/errors/errorText.d.ts +2 -0
  27. package/lib/services/errors/errorText.js +59 -0
  28. package/lib/services/errors/errorText.test.js +66 -0
  29. package/lib/services/keyboardHandlers/resolvekeypress.js +21 -17
  30. package/lib/services/localStorageHandlers/localStorageHandlers.js +5 -2
  31. package/lib/services/localStorageHandlers/localStorageHandlers.test.js +0 -1
  32. package/lib/services/nicamHandlers/nicamhandler.js +0 -4
  33. package/lib/services/nicamHandlers/nicamhandler.test.js +0 -5
  34. package/lib/services/npoPlayerAPI/contants.d.ts +20 -0
  35. package/lib/services/npoPlayerAPI/contants.js +6 -0
  36. package/lib/services/npoPlayerAPI/npoPlayerAPI.d.ts +4 -1
  37. package/lib/services/npoPlayerAPI/npoPlayerAPI.js +31 -5
  38. package/lib/services/npoPlayerAPI/npoPlayerAPI.test.js +11 -0
  39. package/lib/services/services.d.ts +8 -2
  40. package/lib/services/services.js +28 -2
  41. package/lib/services/streamFetchHandler/fetchStream.d.ts +2 -0
  42. package/lib/services/streamFetchHandler/fetchStream.js +48 -0
  43. package/lib/services/streamFetchHandler/fetchstream.test.js +70 -0
  44. package/lib/services/trackingHandlers/eventBinding.d.ts +2 -0
  45. package/lib/{js/tracking/handlers/eventbinding.js → services/trackingHandlers/eventBinding.js} +16 -14
  46. package/lib/services/trackingHandlers/eventBinding.test.js +89 -0
  47. package/lib/services/trackingHandlers/eventLogging.d.ts +2 -0
  48. package/lib/{js/tracking/handlers/eventlogging.js → services/trackingHandlers/eventLogging.js} +18 -7
  49. package/lib/services/trackingHandlers/eventLogging.test.js +63 -0
  50. package/lib/services/trackingHandlers/index.d.ts +3 -0
  51. package/lib/services/trackingHandlers/index.js +3 -0
  52. package/lib/services/trackingHandlers/playerTrackerInit.d.ts +2 -0
  53. package/lib/{js/tracking/handlers/playertrackerinit.js → services/trackingHandlers/playerTrackerInit.js} +6 -3
  54. package/lib/services/trackingHandlers/playerTrackerInit.test.js +75 -0
  55. package/lib/services/trackingHandlers/playerTrackerStart.d.ts +2 -0
  56. package/lib/services/trackingHandlers/playerTrackerStart.js +25 -0
  57. package/lib/services/trackingHandlers/playerTrackerStart.test.js +59 -0
  58. package/lib/services/trackingHandlers/streamTrackerInit.d.ts +3 -0
  59. package/lib/services/trackingHandlers/streamTrackerInit.js +27 -0
  60. package/lib/services/trackingHandlers/streamTrackerInit.test.js +84 -0
  61. package/lib/services/verticalVideoHandlers/handleVerticalVideoControls.d.ts +2 -2
  62. package/lib/services/verticalVideoHandlers/handleVerticalVideoControls.js +4 -6
  63. package/lib/services/verticalVideoHandlers/handleVerticalVideoControls.test.js +4 -17
  64. package/lib/services/verticalVideoHandlers/handleVerticalVideoSettings.d.ts +2 -0
  65. package/lib/services/verticalVideoHandlers/handleVerticalVideoSettings.js +26 -0
  66. package/lib/services/verticalVideoHandlers/handleVerticalVideoSettings.test.js +82 -0
  67. package/lib/src/js/playeractions/playeractions.d.ts +0 -1
  68. package/lib/src/js/utilities/utilities.prid.d.ts +6 -0
  69. package/lib/src/js/utilities/utilities.prid.test.d.ts +1 -0
  70. package/lib/src/npoplayer.d.ts +1 -1
  71. package/lib/src/services/errors/errorBackground.test.d.ts +1 -0
  72. package/lib/src/services/errors/errorHandler.d.ts +3 -0
  73. package/lib/src/services/errors/errorText.d.ts +2 -0
  74. package/lib/src/services/errors/errorText.test.d.ts +1 -0
  75. package/lib/src/services/npoPlayerAPI/contants.d.ts +20 -0
  76. package/lib/src/services/npoPlayerAPI/npoPlayerAPI.d.ts +4 -1
  77. package/lib/src/services/services.d.ts +8 -2
  78. package/lib/src/services/streamFetchHandler/fetchStream.d.ts +2 -0
  79. package/lib/src/services/streamFetchHandler/fetchstream.test.d.ts +1 -0
  80. package/lib/src/services/trackingHandlers/eventBinding.d.ts +2 -0
  81. package/lib/src/services/trackingHandlers/eventBinding.test.d.ts +1 -0
  82. package/lib/src/services/trackingHandlers/eventLogging.d.ts +2 -0
  83. package/lib/src/services/trackingHandlers/eventLogging.test.d.ts +1 -0
  84. package/lib/src/services/trackingHandlers/index.d.ts +3 -0
  85. package/lib/src/services/trackingHandlers/playerTrackerInit.d.ts +2 -0
  86. package/lib/src/services/trackingHandlers/playerTrackerInit.test.d.ts +1 -0
  87. package/lib/src/services/trackingHandlers/playerTrackerStart.d.ts +2 -0
  88. package/lib/src/services/trackingHandlers/playerTrackerStart.test.d.ts +1 -0
  89. package/lib/src/services/trackingHandlers/streamTrackerInit.d.ts +3 -0
  90. package/lib/src/services/trackingHandlers/streamTrackerInit.test.d.ts +1 -0
  91. package/lib/src/services/verticalVideoHandlers/handleVerticalVideoControls.d.ts +2 -2
  92. package/lib/src/services/verticalVideoHandlers/handleVerticalVideoSettings.d.ts +2 -0
  93. package/lib/src/services/verticalVideoHandlers/handleVerticalVideoSettings.test.d.ts +1 -0
  94. package/lib/src/types/interfaces.d.ts +16 -2
  95. package/lib/src/ui/components/seekbar.d.ts +2 -1
  96. package/lib/src/ui/components/verticalvideo/controlbar.d.ts +3 -3
  97. package/lib/src/ui/components/verticalvideo/settingspanel.d.ts +2 -0
  98. package/lib/tests/mocks/mockNpoplayer.js +1 -1
  99. package/lib/tests/mocks/mockStreamObject.d.ts +2 -0
  100. package/lib/tests/mocks/mockStreamObject.js +21 -0
  101. package/lib/tests/mocks/playerContextMock.d.ts +1 -0
  102. package/lib/tests/mocks/playerContextMock.js +5 -1
  103. package/lib/types/interfaces.d.ts +16 -2
  104. package/lib/ui/components/audio/controlbar.js +2 -1
  105. package/lib/ui/components/controlbar.js +1 -1
  106. package/lib/ui/components/seekbar.d.ts +2 -1
  107. package/lib/ui/components/seekbar.js +2 -2
  108. package/lib/ui/components/settingspanel.js +8 -12
  109. package/lib/ui/components/verticalvideo/controlbar.d.ts +3 -3
  110. package/lib/ui/components/verticalvideo/controlbar.js +14 -11
  111. package/lib/ui/components/verticalvideo/settingspanel.d.ts +2 -0
  112. package/lib/ui/components/verticalvideo/settingspanel.js +21 -0
  113. package/lib/ui/handlers/domhandlers.test.js +6 -26
  114. package/lib/ui/nativemobileuifactory.js +1 -1
  115. package/lib/ui/uicontainer.js +5 -4
  116. package/lib/ui/uicontainer.test.js +4 -1
  117. package/package.json +1 -1
  118. package/src/style/components/_advert.scss +3 -3
  119. package/src/style/components/_buffering.scss +14 -8
  120. package/src/style/components/_error.scss +44 -1
  121. package/src/style/components/_hugeplaybacktogglebutton.scss +1 -0
  122. package/src/style/components/_metadata.scss +13 -12
  123. package/src/style/components/_nicam.scss +11 -6
  124. package/src/style/components/_playnext.scss +1 -1
  125. package/src/style/components/_replay.scss +1 -6
  126. package/src/style/components/_settingspanel.scss +74 -79
  127. package/src/style/components/audio/_bottombar.scss +7 -9
  128. package/src/style/components/audio/_errors.scss +1 -1
  129. package/src/style/components/audio/_metadata.scss +14 -8
  130. package/src/style/components/audio/_playbutton.scss +1 -0
  131. package/src/style/components/audio/_topbar.scss +12 -2
  132. package/src/style/components/audio/_volumeslider.scss +3 -3
  133. package/src/style/components/vertical-video/_bottombar.scss +42 -1
  134. package/src/style/components/vertical-video/_hugeplaybacktogglebutton.scss +24 -4
  135. package/src/style/components/vertical-video/_settingspanel.scss +20 -3
  136. package/src/style/components/vertical-video/_topbar.scss +47 -6
  137. package/src/style/npoplayer.css +91 -57
  138. package/src/style/npoplayer.scss +4 -7
  139. package/src/style/variants/_player-base.scss +10 -2
  140. package/src/style/variants/_player-large.scss +4 -0
  141. package/src/style/variants/_player-medium.scss +4 -1
  142. package/src/style/variants/_player-small.scss +15 -1
  143. package/src/style/vars/_fonts.scss +13 -7
  144. package/src/style/vars/_z-index.scss +1 -0
  145. package/lib/js/api/getstreamobject.d.ts +0 -3
  146. package/lib/js/api/getstreamobject.js +0 -38
  147. package/lib/js/api/getstreamobject.test.js +0 -48
  148. package/lib/js/playeractions/customerrors.test.js +0 -51
  149. package/lib/js/playeractions/handlers/customerrors.d.ts +0 -50
  150. package/lib/js/playeractions/handlers/customerrors.js +0 -56
  151. package/lib/js/playeractions/handlers/error.d.ts +0 -3
  152. package/lib/js/playeractions/handlers/error.js +0 -14
  153. package/lib/js/playeractions/handlers/error.test.js +0 -44
  154. package/lib/js/tracking/handlers/eventbinding.d.ts +0 -3
  155. package/lib/js/tracking/handlers/eventlogging.d.ts +0 -2
  156. package/lib/js/tracking/handlers/eventlogging.test.js +0 -46
  157. package/lib/js/tracking/handlers/playertrackerinit.d.ts +0 -4
  158. package/lib/js/tracking/handlers/playertrackerinit.test.js +0 -74
  159. package/lib/js/tracking/handlers/playertrackerstart.d.ts +0 -1
  160. package/lib/js/tracking/handlers/playertrackerstart.js +0 -25
  161. package/lib/js/tracking/playertracker.d.ts +0 -4
  162. package/lib/js/tracking/playertracker.js +0 -4
  163. package/lib/src/js/api/getstreamobject.d.ts +0 -3
  164. package/lib/src/js/playeractions/handlers/customerrors.d.ts +0 -50
  165. package/lib/src/js/playeractions/handlers/error.d.ts +0 -3
  166. package/lib/src/js/tracking/handlers/eventbinding.d.ts +0 -3
  167. package/lib/src/js/tracking/handlers/eventlogging.d.ts +0 -2
  168. package/lib/src/js/tracking/handlers/playertrackerinit.d.ts +0 -4
  169. package/lib/src/js/tracking/handlers/playertrackerstart.d.ts +0 -1
  170. package/lib/src/js/tracking/playertracker.d.ts +0 -4
  171. /package/lib/js/{api/getstreamobject.test.d.ts → utilities/utilities.prid.test.d.ts} +0 -0
  172. /package/lib/{js/playeractions/customerrors.test.d.ts → services/errors/errorBackground.test.d.ts} +0 -0
  173. /package/lib/{js/playeractions/handlers/error.test.d.ts → services/errors/errorText.test.d.ts} +0 -0
  174. /package/lib/{js/tracking/handlers/eventlogging.test.d.ts → services/streamFetchHandler/fetchstream.test.d.ts} +0 -0
  175. /package/lib/{js/tracking/handlers/playertrackerinit.test.d.ts → services/trackingHandlers/eventBinding.test.d.ts} +0 -0
  176. /package/lib/{src/js/api/getstreamobject.test.d.ts → services/trackingHandlers/eventLogging.test.d.ts} +0 -0
  177. /package/lib/{src/js/playeractions/customerrors.test.d.ts → services/trackingHandlers/playerTrackerInit.test.d.ts} +0 -0
  178. /package/lib/{src/js/playeractions/handlers/error.test.d.ts → services/trackingHandlers/playerTrackerStart.test.d.ts} +0 -0
  179. /package/lib/{src/js/tracking/handlers/eventlogging.test.d.ts → services/trackingHandlers/streamTrackerInit.test.d.ts} +0 -0
  180. /package/lib/{src/js/tracking/handlers/playertrackerinit.test.d.ts → services/verticalVideoHandlers/handleVerticalVideoSettings.test.d.ts} +0 -0
@@ -1,23 +1,41 @@
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
  };
36
+ mockNpoplayer.npoPlayerServices = {
37
+ fetchStream: jest.fn()
38
+ };
21
39
  mockPlayerContext = { player: mockPlayer, npoPlayer: mockNpoplayer };
22
40
  });
23
41
  afterEach(() => {
@@ -66,10 +84,15 @@ describe('Test DRM verification', () => {
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 () => {
@@ -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,46 @@
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
+ npoPlayer.logEmitter.emit('logError', status);
9
+ await player.unload();
10
+ uiComponents.controlBar?.hide();
11
+ const errorMessageOverlay = uiComponents.errorMessageOverlay;
12
+ if (!errorMessageOverlay)
13
+ return;
14
+ player.addClassToNpoPlayerElement(errorContainerClass);
15
+ setErrorBackground(playerContext);
16
+ errorMessageOverlay.display(message);
17
+ if (shouldRetry) {
18
+ setupRetryHandler(playerContext, errorContainerClass);
19
+ }
20
+ }
21
+ function generateErrorMessage(status, shouldRetry) {
22
+ const baseMessage = npoBusinessErrors[status] ?? customSpecificErrorMessageOverlayConfig[status] ?? 'De video kan niet worden geladen';
23
+ const retryMessage = shouldRetry
24
+ ? '<br>Klik om het opnieuw te proberen.<br><br><button class="retry-button">Opnieuw proberen</button>'
25
+ : '';
26
+ return `<span class="errorcode">Foutcode ${status}</span>\n${baseMessage}${retryMessage}`;
27
+ }
28
+ function setupRetryHandler(playerContext, errorContainerClass) {
29
+ const playerContainer = playerContext.player.getNpoPlayerElement();
30
+ playerContainer.addEventListener('click', (event) => {
31
+ const target = event.target;
32
+ if (target.classList.contains('retry-button') && playerContainer.classList.contains(errorContainerClass)) {
33
+ target.style.visibility = 'hidden';
34
+ playerContext.player.handleErrorRetry(playerContext);
35
+ playerContext.player.removeClassFromNpoPlayerElement(errorContainerClass);
36
+ setTimeout(() => {
37
+ target.style.visibility = 'visible';
38
+ }, 200);
39
+ }
40
+ });
41
+ }
42
+ export function setErrorBackground(playerContext) {
43
+ const playerContainer = playerContext.player.getNpoPlayerElement();
44
+ const posterImage = playerContext.npoPlayer.sourceConfig.poster;
45
+ playerContainer?.style.setProperty('--npo-player-errormessage-background-image', posterImage || 'none');
46
+ }
@@ -0,0 +1,2 @@
1
+ export declare const customSpecificErrorMessageOverlayConfig: Record<number, string>;
2
+ export declare const npoBusinessErrors: Record<number, string>;
@@ -0,0 +1,59 @@
1
+ export const customSpecificErrorMessageOverlayConfig = {
2
+ 1000: 'Er is een onbekende fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.',
3
+ 1001: 'Er is een onbekende fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.',
4
+ 1101: 'Er is een configuratie fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.',
5
+ 1102: 'Er is een configuratie fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.',
6
+ 1103: 'Er is een licentie-fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.',
7
+ 1104: 'Er is een licentie-fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.',
8
+ 1105: 'Er is een licentie-fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.',
9
+ 1106: 'Er is een licentie-fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.',
10
+ 1107: 'Er is een licentie-fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.',
11
+ 1108: 'Er is een onbekende fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.',
12
+ 1113: 'Er is een onbekende fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.',
13
+ 1200: 'Er is een onbekende fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.',
14
+ 1201: 'Er is een onbekende fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.',
15
+ 1202: 'Dit item kon niet worden geladen.',
16
+ 1203: 'Dit item is niet beschikbaar op dit apparaat. Controleer of jouw apparaat geschikt is voor het afspelen van beveiligde content.',
17
+ 1204: 'Dit item is niet beschikbaar op dit apparaat. Controleer of jouw apparaat geschikt is voor het afspelen van beveiligde content.',
18
+ 1205: 'Dit item is niet beschikbaar op dit apparaat. Controleer of jouw apparaat geschikt is voor het afspelen van beveiligde content.',
19
+ 1206: 'Dit item is niet beschikbaar op dit apparaat. Controleer of jouw apparaat geschikt is voor het afspelen van beveiligde content.',
20
+ 1207: 'Er is een onbekende fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.',
21
+ 1208: 'Dit item kon niet worden geladen.',
22
+ 1209: 'Er is een onbekende fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.',
23
+ 1210: 'Er is een onbekende fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.',
24
+ 1211: 'Er is een onbekende fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.',
25
+ 1301: 'Er is een onbekende fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.',
26
+ 1304: 'Er is een onbekende fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.',
27
+ 1400: 'Er is iets mis met uw internet-verbinding',
28
+ 1401: 'Er is een serverfout opgetreden. Controleer je internetverbinding.',
29
+ 1402: 'Er is een serverfout opgetreden. Controleer je internetverbinding.',
30
+ 1403: 'Er is een serverfout opgetreden. Controleer je internetverbinding.',
31
+ 1404: 'Er is een serverfout opgetreden. Controleer je internetverbinding.',
32
+ 2001: 'Er is een configuratie fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.',
33
+ 2002: 'Er is een configuratie fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.',
34
+ 2003: 'Er is een onbekende fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.',
35
+ 2005: 'Er is een onbekende fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.',
36
+ 2006: 'Oeps, er is iets mis met de DRM',
37
+ 2007: 'Dit item is niet beschikbaar op dit apparaat. Controleer of jouw apparaat geschikt is voor het afspelen van beveiligde content.',
38
+ 2008: 'Dit item is niet beschikbaar op dit apparaat. Controleer of jouw apparaat geschikt is voor het afspelen van beveiligde content.',
39
+ 2009: 'Er is een licentie-fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.',
40
+ 2010: 'Dit item is niet beschikbaar op dit apparaat. Controleer of jouw apparaat geschikt is voor het afspelen van beveiligde content.',
41
+ 2011: 'Er is een licentie-fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.',
42
+ 2012: 'Er is een licentie-fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.',
43
+ 2013: 'Dit item is niet beschikbaar op dit apparaat. Controleer of jouw apparaat geschikt is voor het afspelen van beveiligde content.',
44
+ 2015: 'Er is een licentie-fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.',
45
+ 2101: 'Er is een onbekende fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.',
46
+ 3001: 'Er is een onbekende fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.',
47
+ 3002: 'Er is een onbekende fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.',
48
+ 3003: 'Er is een onbekende fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.',
49
+ 3004: 'Er is een onbekende fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.',
50
+ 4000: 'Er is een onbekende fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.'
51
+ };
52
+ export const npoBusinessErrors = {
53
+ 402: 'Dit programma is alleen te zien op NPO Start met een plus-abonnement.',
54
+ 403: 'Dit item is momenteel niet beschikbaar.',
55
+ 404: 'Dit item is momenteel niet beschikbaar.',
56
+ 410: 'Dit item is momenteel niet beschikbaar.',
57
+ 450: 'Dit item heeft een leeftijdsrestrictie en is alleen beschikbaar tussen 20:00 uur en 06:00 uur of te streamen op NPO Start met een plus-abonnement.',
58
+ 451: 'Dit item is niet beschikbaar op jouw locatie.'
59
+ };
@@ -0,0 +1,66 @@
1
+ import { customSpecificErrorMessageOverlayConfig } from './errorText';
2
+ describe('Test custom error messages', () => {
3
+ it('should return a 1000 error message', () => {
4
+ expect(customSpecificErrorMessageOverlayConfig[1000]).toBe('Er is een onbekende fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.');
5
+ });
6
+ it('should return a 1001 error message', () => {
7
+ expect(customSpecificErrorMessageOverlayConfig[1001]).toBe('Er is een onbekende fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.');
8
+ });
9
+ it('should return a 1101 error message', () => {
10
+ expect(customSpecificErrorMessageOverlayConfig[1101]).toBe('Er is een configuratie fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.');
11
+ });
12
+ it('should return a 1102 error message', () => {
13
+ expect(customSpecificErrorMessageOverlayConfig[1102]).toBe('Er is een configuratie fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.');
14
+ });
15
+ it('should return a 1103 error message', () => {
16
+ expect(customSpecificErrorMessageOverlayConfig[1103]).toBe('Er is een licentie-fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.');
17
+ });
18
+ it('should return a 1104 error message', () => {
19
+ expect(customSpecificErrorMessageOverlayConfig[1104]).toBe('Er is een licentie-fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.');
20
+ });
21
+ it('should return a 1113 error message', () => {
22
+ expect(customSpecificErrorMessageOverlayConfig[1113]).toBe('Er is een onbekende fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.');
23
+ });
24
+ it('should return a 1201 error message', () => {
25
+ expect(customSpecificErrorMessageOverlayConfig[1201]).toBe('Er is een onbekende fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.');
26
+ });
27
+ it('should return a 1202 error message', () => {
28
+ expect(customSpecificErrorMessageOverlayConfig[1202]).toBe('Dit item kon niet worden geladen.');
29
+ });
30
+ it('should return a 1203 error message', () => {
31
+ expect(customSpecificErrorMessageOverlayConfig[1203]).toBe('Dit item is niet beschikbaar op dit apparaat. Controleer of jouw apparaat geschikt is voor het afspelen van beveiligde content.');
32
+ });
33
+ it('should return a 1400 error message', () => {
34
+ expect(customSpecificErrorMessageOverlayConfig[1400]).toBe('Er is iets mis met uw internet-verbinding');
35
+ });
36
+ it('should return a 1401 error message', () => {
37
+ expect(customSpecificErrorMessageOverlayConfig[1401]).toBe('Er is een serverfout opgetreden. Controleer je internetverbinding.');
38
+ });
39
+ it('should return a 1402 error message', () => {
40
+ expect(customSpecificErrorMessageOverlayConfig[1402]).toBe('Er is een serverfout opgetreden. Controleer je internetverbinding.');
41
+ });
42
+ it('should return a 1403 error message', () => {
43
+ expect(customSpecificErrorMessageOverlayConfig[1403]).toBe('Er is een serverfout opgetreden. Controleer je internetverbinding.');
44
+ });
45
+ it('should return a 2006 error message', () => {
46
+ expect(customSpecificErrorMessageOverlayConfig[2006]).toBe('Oeps, er is iets mis met de DRM');
47
+ });
48
+ it('should return a 2007 error message', () => {
49
+ expect(customSpecificErrorMessageOverlayConfig[2007]).toBe('Dit item is niet beschikbaar op dit apparaat. Controleer of jouw apparaat geschikt is voor het afspelen van beveiligde content.');
50
+ });
51
+ it('should return a 2013 error message', () => {
52
+ expect(customSpecificErrorMessageOverlayConfig[2013]).toBe('Dit item is niet beschikbaar op dit apparaat. Controleer of jouw apparaat geschikt is voor het afspelen van beveiligde content.');
53
+ });
54
+ it('should return a 2015 error message', () => {
55
+ expect(customSpecificErrorMessageOverlayConfig[2015]).toBe('Er is een licentie-fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.');
56
+ });
57
+ it('should return a 3001 error message', () => {
58
+ expect(customSpecificErrorMessageOverlayConfig[3001]).toBe('Er is een onbekende fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.');
59
+ });
60
+ it('should return a 3003 error message', () => {
61
+ expect(customSpecificErrorMessageOverlayConfig[3003]).toBe('Er is een onbekende fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.');
62
+ });
63
+ it('should return a 4000 error message', () => {
64
+ expect(customSpecificErrorMessageOverlayConfig[4000]).toBe('Er is een onbekende fout opgetreden. Als het probleem zich blijft voordoen, neem dan contact op met onze klantenservice.');
65
+ });
66
+ });
@@ -1,39 +1,43 @@
1
- import { ViewMode } from '../../types/interfaces';
1
+ import { NpoPlayerUIVariants, ViewMode } from '../../types/interfaces';
2
2
  export function resolveKeyPress(playerContext, e) {
3
- const isMuted = playerContext.player.isMuted() ?? false;
4
- const isPaused = playerContext.player.isPaused() ?? false;
5
- const viewMode = playerContext.player.getViewMode();
3
+ const { player, npoPlayer } = playerContext;
4
+ const isMuted = player.isMuted() ?? false;
5
+ const isPaused = player.isPaused() ?? false;
6
+ const viewMode = player.getViewMode();
7
+ const variant = npoPlayer.variant;
6
8
  if (['Space', 'ArrowUp', 'ArrowDown'].includes(e.code))
7
9
  e.preventDefault();
8
10
  const actions = {
9
- KeyM: () => (isMuted ? playerContext.player.unmute() : playerContext.player.mute()),
10
- KeyF: () => viewMode === ViewMode.Fullscreen
11
- ? playerContext.player.setViewMode(ViewMode.Inline)
12
- : playerContext.player.setViewMode(ViewMode.Fullscreen),
11
+ KeyM: () => (isMuted ? player.unmute() : player.mute()),
12
+ KeyF: () => viewMode === ViewMode.Fullscreen ? player.setViewMode(ViewMode.Inline) : player.setViewMode(ViewMode.Fullscreen),
13
13
  Space: () => {
14
14
  if (isPaused) {
15
- playerContext.player.play().catch((error) => {
15
+ player.play().catch((error) => {
16
16
  console.error('Failed to play:', error);
17
17
  });
18
18
  }
19
19
  else {
20
- playerContext.player.pause();
20
+ player.pause();
21
21
  }
22
22
  },
23
23
  ArrowUp: () => {
24
+ if (variant === NpoPlayerUIVariants.VERTICAL)
25
+ return;
24
26
  if (isMuted)
25
- playerContext.player.unmute();
26
- playerContext.npoPlayer.increaseVolume();
27
+ player.unmute();
28
+ npoPlayer.increaseVolume();
27
29
  },
28
30
  ArrowDown: () => {
31
+ if (variant === NpoPlayerUIVariants.VERTICAL)
32
+ return;
29
33
  if (isMuted)
30
- playerContext.player.unmute();
31
- playerContext.npoPlayer.decreaseVolume();
34
+ player.unmute();
35
+ npoPlayer.decreaseVolume();
32
36
  },
33
- ArrowLeft: () => playerContext.npoPlayer.goBackwards(10),
34
- ArrowRight: () => playerContext.npoPlayer.goForward(10),
37
+ ArrowLeft: () => npoPlayer.goBackwards(10),
38
+ ArrowRight: () => npoPlayer.goForward(10),
35
39
  Escape: () => {
36
- const { settingsPanels } = playerContext.npoPlayer.uiComponents;
40
+ const { settingsPanels } = npoPlayer.uiComponents;
37
41
  if (settingsPanels && settingsPanels.length > 0) {
38
42
  for (const panel of settingsPanels) {
39
43
  if (panel.isShown()) {
@@ -1,3 +1,4 @@
1
+ import { NpoPlayerUIVariants } from '../../types/interfaces';
1
2
  export function setLocalStorage(key, value) {
2
3
  const prefixedKey = `npoplayer-${key}`;
3
4
  localStorage.setItem(prefixedKey, JSON.stringify(value));
@@ -18,12 +19,14 @@ export function getLocalStorage() {
18
19
  }
19
20
  export function setValuesBasedOnLocalStorage(playerContext) {
20
21
  const localStorageData = getLocalStorage();
21
- const { player } = playerContext;
22
+ const { player, npoPlayer } = playerContext;
22
23
  if (!player) {
23
24
  console.error('Player is undefined in playerContext');
24
25
  return;
25
26
  }
26
- player.setVolume(localStorageData.volume ?? 100);
27
+ if (npoPlayer.variant !== NpoPlayerUIVariants.VERTICAL) {
28
+ player.setVolume(localStorageData.volume ?? 100);
29
+ }
27
30
  if (localStorageData.ismuted === 'true') {
28
31
  player.mute();
29
32
  }
@@ -64,7 +64,6 @@ describe('localStorageHandler', () => {
64
64
  playerConfig: {},
65
65
  initPlayer: () => { },
66
66
  loadStream: () => Promise.resolve(),
67
- doError: () => { },
68
67
  play: async () => { },
69
68
  pause: () => { },
70
69
  setVolume: () => { },
@@ -1,4 +1,3 @@
1
- import { NpoPlayerEvent } from '../../types/events';
2
1
  export function processNicam(playerContext, nicamElement) {
3
2
  const streamOptions = playerContext.npoPlayer.streamOptions;
4
3
  const metadata = playerContext?.npoPlayer?.streamObject?.metadata ?? {};
@@ -50,9 +49,6 @@ export function showNicamAfterUiDelay(playerContext) {
50
49
  const { uiManager } = npoPlayer;
51
50
  const showNicamClassName = 'bmpui-show-nicam';
52
51
  const playerContainer = player.getNpoPlayerElement();
53
- player.off(NpoPlayerEvent.Ready, () => {
54
- npoPlayer.npoPlayerServices.showNicamAfterUiDelay(playerContext);
55
- });
56
52
  if (!playerContainer || !uiManager)
57
53
  return;
58
54
  uiManager.activeUi.onControlsHide.subscribe(() => {
@@ -1,7 +1,6 @@
1
1
  import { processNicam, showNicamAfterUiDelay } from './nicamhandler';
2
2
  import '@testing-library/jest-dom';
3
3
  import { createMockNpoPlayer, createPlayerContextMock } from '../../../tests/mocks/playerContextMock';
4
- import { NpoPlayerEvent } from '../../types/events';
5
4
  describe('NICAM Processing', () => {
6
5
  let mockElement;
7
6
  beforeEach(() => {
@@ -124,9 +123,5 @@ describe('NICAM Visibility Management', () => {
124
123
  expect(mockUiManager.activeUi.onControlsHide.subscribe).not.toHaveBeenCalled();
125
124
  expect(mockUiManager.activeUi.onControlsShow.subscribe).not.toHaveBeenCalled();
126
125
  });
127
- it('should clean up event listeners when the player is ready', () => {
128
- showNicamAfterUiDelay(mockPlayerContext);
129
- expect(mockPlayer.off).toHaveBeenCalledWith(NpoPlayerEvent.Ready, expect.any(Function));
130
- });
131
126
  });
132
127
  });
@@ -3,3 +3,23 @@ export declare const PREVENT_UI_DELAY = -1;
3
3
  export declare const VOLUME_STEP = 10;
4
4
  export declare const VOLUME_MIN = 0;
5
5
  export declare const VOLUME_MAX = 100;
6
+ export declare const emptyStreamObject: {
7
+ stream: {
8
+ drmType: string;
9
+ streamProfile: string;
10
+ streamURL: string;
11
+ avType: string;
12
+ sourceProfile: string;
13
+ };
14
+ metadata: {
15
+ title: string;
16
+ description: string;
17
+ };
18
+ assets: {
19
+ scrubbingThumbnail: string;
20
+ subtitles: never[];
21
+ };
22
+ user: {
23
+ type: "anonymous" | "plus";
24
+ };
25
+ };
@@ -3,3 +3,9 @@ export const PREVENT_UI_DELAY = -1;
3
3
  export const VOLUME_STEP = 10;
4
4
  export const VOLUME_MIN = 0;
5
5
  export const VOLUME_MAX = 100;
6
+ export const emptyStreamObject = {
7
+ stream: { drmType: '', streamProfile: '', streamURL: '', avType: '', sourceProfile: '' },
8
+ metadata: { title: '', description: '' },
9
+ assets: { scrubbingThumbnail: '', subtitles: [] },
10
+ user: { type: 'anonymous' }
11
+ };
@@ -6,6 +6,7 @@ export declare class NpoPlayerAPI {
6
6
  playerAPI: PlayerAPI;
7
7
  constructor(playerAPI: PlayerAPI);
8
8
  load(sourceConfig: SourceConfig): Promise<void>;
9
+ unload(): Promise<void>;
9
10
  play(): Promise<void>;
10
11
  pause(): void;
11
12
  mute(): void;
@@ -27,6 +28,7 @@ export declare class NpoPlayerAPI {
27
28
  off(eventType: NpoPlayerEvent, callback: NpoPlayerEventCallback): void;
28
29
  on(eventType: NpoPlayerEvent, callback: NpoPlayerEventCallback): void;
29
30
  isCastAvailable(): boolean;
31
+ isCasting(): boolean;
30
32
  seek(time: number): void;
31
33
  timeShift(time: number): void;
32
34
  getContainer(): HTMLElement;
@@ -38,7 +40,8 @@ export declare class NpoPlayerAPI {
38
40
  getDuration(): number;
39
41
  getTimeShift(): number;
40
42
  scheduleAds(adConfig: AdConfig): Promise<AdBreak[]>;
43
+ handleErrorRetry(playerContext: PlayerContext): void;
41
44
  getActiveAdBreak(): AdBreak | null;
42
45
  getConfig(mergedConfig?: boolean): PlayerConfig;
43
- createUIManager(playerContext: PlayerContext, variant: NpoPlayerUIVariants): Promise<void | UIManager>;
46
+ createUIManager(playerContext: PlayerContext, variant: NpoPlayerUIVariants): void | UIManager;
44
47
  }
@@ -1,8 +1,9 @@
1
1
  import { UIManager } from 'bitmovin-player-ui';
2
- import { customSpecificErrorMessageOverlayConfig } from '../../js/playeractions/handlers/customerrors';
2
+ import { customSpecificErrorMessageOverlayConfig } from '../errors/errorText';
3
3
  import { createUIContainer } from '../../ui/uicontainer';
4
4
  import { playerEventMap } from '../../types/events';
5
5
  import { VOLUME_MAX, VOLUME_MIN, VOLUME_STEP } from './contants';
6
+ import { localizationConfig } from '../../js/settings/localization';
6
7
  const externalCallbacksMap = new WeakMap();
7
8
  export class NpoPlayerAPI {
8
9
  constructor(playerAPI) {
@@ -11,8 +12,19 @@ export class NpoPlayerAPI {
11
12
  async load(sourceConfig) {
12
13
  await this.playerAPI.load(sourceConfig);
13
14
  }
15
+ async unload() {
16
+ await this.playerAPI.unload();
17
+ }
14
18
  async play() {
15
- await this.playerAPI.play();
19
+ await this.playerAPI.play().catch((error) => {
20
+ console.error('Playback error:', error);
21
+ if (error.code === 1201) {
22
+ console.error('No source was loaded. Please load a source before playing.');
23
+ }
24
+ else {
25
+ console.error('An unexpected playback error occurred.');
26
+ }
27
+ });
16
28
  }
17
29
  pause() {
18
30
  this.playerAPI.pause();
@@ -95,6 +107,9 @@ export class NpoPlayerAPI {
95
107
  isCastAvailable() {
96
108
  return this.playerAPI.isCastAvailable();
97
109
  }
110
+ isCasting() {
111
+ return this.playerAPI.isCasting();
112
+ }
98
113
  seek(time) {
99
114
  this.playerAPI.seek(time);
100
115
  }
@@ -128,25 +143,36 @@ export class NpoPlayerAPI {
128
143
  async scheduleAds(adConfig) {
129
144
  return this.playerAPI.ads.schedule(adConfig);
130
145
  }
146
+ handleErrorRetry(playerContext) {
147
+ if (playerContext.npoPlayer.streamOptions.retryCallback === undefined) {
148
+ console.error('No retry callback found in stream options');
149
+ return;
150
+ }
151
+ return playerContext.npoPlayer.streamOptions.retryCallback();
152
+ }
131
153
  getActiveAdBreak() {
132
154
  return this.playerAPI.ads.getActiveAdBreak();
133
155
  }
134
156
  getConfig(mergedConfig) {
135
157
  return this.playerAPI.getConfig(mergedConfig);
136
158
  }
137
- async createUIManager(playerContext, variant) {
159
+ createUIManager(playerContext, variant) {
138
160
  const { npoPlayerServices } = playerContext.npoPlayer;
139
- npoPlayerServices.removeUivisiblityHandlers(playerContext);
140
161
  if (playerContext.npoPlayer.uiManager === undefined || variant !== playerContext.npoPlayer.variant) {
162
+ npoPlayerServices.removeUivisiblityHandlers(playerContext);
141
163
  const uiConfig = {
142
164
  errorMessages: customSpecificErrorMessageOverlayConfig,
143
165
  disableAutoHideWhenHovered: true,
144
166
  seekbarSnappingEnabled: false
145
167
  };
146
- playerContext.npoPlayer.variant = variant;
168
+ npoPlayerServices.removeUivisiblityHandlers(playerContext);
169
+ playerContext.npoPlayer.uiManager?.release();
170
+ UIManager.setLocalizationConfig(localizationConfig);
147
171
  const uiManager = new UIManager(this.playerAPI, createUIContainer(playerContext, this.playerAPI, variant), uiConfig);
148
172
  playerContext.npoPlayer.uiManager = uiManager;
173
+ playerContext.npoPlayer.variant = variant;
149
174
  npoPlayerServices.addUivisiblityHandlers(playerContext);
175
+ npoPlayerServices.showNicamAfterUiDelay(playerContext);
150
176
  }
151
177
  }
152
178
  }
@@ -20,9 +20,20 @@ describe('NpoPlayerAPI', () => {
20
20
  npoPlayerAPI = new NpoPlayerAPI(mockPlayerAPI);
21
21
  });
22
22
  it('should call play on the PlayerAPI', async () => {
23
+ mockPlayerAPI.play.mockResolvedValueOnce(undefined);
23
24
  await npoPlayerAPI.play();
24
25
  expect(mockPlayerAPI.play).toHaveBeenCalled();
25
26
  });
27
+ it('should handle error when play throws an error', async () => {
28
+ const error = { code: 1201, message: 'No source loaded' };
29
+ mockPlayerAPI.play.mockRejectedValueOnce(error);
30
+ const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {
31
+ });
32
+ await npoPlayerAPI.play();
33
+ expect(consoleErrorSpy).toHaveBeenCalledWith('Playback error:', error);
34
+ expect(consoleErrorSpy).toHaveBeenCalledWith('No source was loaded. Please load a source before playing.');
35
+ consoleErrorSpy.mockRestore();
36
+ });
26
37
  it('should call pause on the PlayerAPI', () => {
27
38
  npoPlayerAPI.pause();
28
39
  expect(mockPlayerAPI.pause).toHaveBeenCalled();
@@ -1,4 +1,4 @@
1
- import { ApiPayload, Fragment, PlayerContext, Profile, Segment, TimeLineMarker, LocalStorageData, LocalStorageValues, NpoPlayerUIVariants } from '../types/interfaces';
1
+ import { ApiPayload, Fragment, PlayerContext, Profile, Segment, TimeLineMarker, LocalStorageData, LocalStorageValues, StreamObject, PlayerTrackerParams, LogEventParams } from '../types/interfaces';
2
2
  import { AVType } from '@npotag/tag/dist/types/src/streamTracker';
3
3
  export declare class NpoPlayerServices {
4
4
  getAVType(avType: string): AVType;
@@ -13,11 +13,17 @@ export declare class NpoPlayerServices {
13
13
  setAccessibilityAttributes(playerContext: PlayerContext): void;
14
14
  schedulePreRolls(playerContext: PlayerContext): Promise<void>;
15
15
  discardAdBreak(playerContext: PlayerContext): void;
16
- handleVerticalVideoControls(playerContext: PlayerContext, variant: NpoPlayerUIVariants): void;
16
+ handleVerticalVideoControls(playerContext: PlayerContext): void;
17
+ handleVerticalVideoSettings(playerContext: PlayerContext): void;
17
18
  showNicamAfterUiDelay(playerContext: PlayerContext | undefined): void;
18
19
  setupNicamKijkwijzerIcons(playerContext: PlayerContext): void;
19
20
  handlePreferences(playerContext: PlayerContext): void;
20
21
  addUivisiblityHandlers(playerContext: PlayerContext): void;
21
22
  removeUivisiblityHandlers(playerContext: PlayerContext): void;
22
23
  handleStreamOptions(playerContext: PlayerContext): void;
24
+ handleError(playerContext: PlayerContext, input: number): Promise<void>;
25
+ fetchStream(playerContext: PlayerContext, payload: ApiPayload): Promise<StreamObject>;
26
+ startPlayerTracker({ playerContext, source, duration }: PlayerTrackerParams): void;
27
+ initPlayerTracker(playerContext: PlayerContext): void;
28
+ logEvent({ playerContext, event, data }: LogEventParams): void;
23
29
  }