Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(FEC-14041): error handling #67

Merged
merged 5 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 59 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,30 +66,73 @@ Finally, add the bundle as a script tag in your page, and initialize the player
</div>
```

## Documentation

Playlist plugin configuration can been found here:
## Configuration
#### Configuration Structure

```js
//Default configuration
"playlist" = {};
//Plugin params
"playlist" = {
expandOnFirstPlay?: boolean, // optional
position?: string, // optional
expandMode?: string, // optional
playNextOnError?: boolean // optional
}
```

- **[Configuration](docs/configuration.md)**
##

> ### config.expandOnFirstPlay
>
> ##### Type: `boolean`
>
> ##### Default: true
>
> ##### Description: if plugin should automatically open on first play.
>

##

> ### config.position
>
> ##### Type: `'right' | 'left' | 'top' | 'bottom'`
>
> ##### Default: `right`
>
> ##### Description: expand mode of side panel (‘alongside', ‘hidden’, 'over’, default 'alongside').
>

##

> ### config.expandMode
>
> ##### Type: `string`
>
> ##### Default: `alongside`
>
> ##### Description: expand mode of side panel (‘alongside', ‘hidden’, 'over’, default 'alongside').
>

##

> ### config.playNextOnError
>
> ##### Type: `boolean`
>
> ##### Default: true
>
> ##### Description: If entry playback fails the playlist will move playback to the next entry.
>

## Running the tests

Tests can be run locally via [Karma], which will run on Chrome, Firefox and Safari

[karma]: https://karma-runner.github.io/1.0/index.html
The plugin uses `cypress` tool for e2e tests

```
```javascript
yarn run test
```

You can test individual browsers:

```
yarn run test:chrome
yarn run test:firefox
yarn run test:safari
```

### And coding style tests

We use ESLint [recommended set](http://eslint.org/docs/rules/) with some additions for enforcing [Flow] types and other rules.
Expand Down
49 changes: 49 additions & 0 deletions cypress/e2e/playlist.cy.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// @ts-expect-error Module '"@playkit-js/kaltura-player-js"' has no exported member 'core'
import {core} from '@playkit-js/kaltura-player-js';
import {mockKalturaBe, loadPlayer, MANIFEST, MANIFEST_SAFARI} from './env';

describe('Playlist plugin', () => {
Expand Down Expand Up @@ -57,4 +59,51 @@ describe('Playlist plugin', () => {
});
});
});

describe('playlist navigation on click', () => {
it('should navigate between playlist items on click', () => {
mockKalturaBe();
loadPlayer({expandOnFirstPlay: true}, {autoplay: true}).then(() => {
cy.get('[data-testid="playlist_item"]').eq(0).should('have.attr', 'aria-current', 'true');
cy.get('[data-testid="playlist_item"]').eq(2).should('have.attr', 'aria-current', 'false');
cy.get('[data-testid="playlist_item"]').eq(2).click({force: true});
cy.get('[data-testid="playlist_item"]').eq(0).should('have.attr', 'aria-current', 'false');
cy.get('[data-testid="playlist_item"]').eq(2).should('have.attr', 'aria-current', 'true');
});
});

it('should navigate between playlist items on keyboard press', () => {
mockKalturaBe();
loadPlayer({expandOnFirstPlay: true}, {autoplay: true}).then(() => {
cy.get('[data-testid="playlist_item"]').eq(2).should('have.attr', 'aria-current', 'false');
cy.get('[data-testid="playlist_item"]').eq(2).focus().type('{enter}');
cy.get('[data-testid="playlist_item"]').eq(2).should('have.attr', 'aria-current', 'true');
});
});
});

describe('error handling', () => {
it('should play next entry on error', () => {
mockKalturaBe();
loadPlayer({expandOnFirstPlay: true}, {autoplay: true}).then(kalturaPlayer => {
cy.get('[data-testid="playlist_item"]').eq(0).should('have.attr', 'aria-current', 'true');
const error = new core.Error(core.Error.Severity.CRITICAL, core.Error.Category.PLAYER, core.Error.Code.VIDEO_ERROR, {});
kalturaPlayer.dispatchEvent(new core.FakeEvent(core.EventType.ERROR, error));
cy.get('[data-testid="playlist_item"]').eq(0).should('have.attr', 'aria-current', 'false');
cy.get('[data-testid="playlist_item"]').eq(1).should('have.attr', 'aria-current', 'true');
});
});
it('should not play next entry on error if feature disabled', () => {
mockKalturaBe();
loadPlayer({expandOnFirstPlay: true, playNextOnError: false}, {autoplay: true}).then(kalturaPlayer => {
cy.get('[data-testid="playlist_root"]')
.should('exist')
.then(() => {
const error = new core.Error(core.Error.Severity.CRITICAL, core.Error.Category.PLAYER, core.Error.Code.VIDEO_ERROR, {});
kalturaPlayer.dispatchEvent(new core.FakeEvent(core.EventType.ERROR, error));
cy.get('[data-testid="playlist_root"]').should('not.exist');
});
});
});
});
});
23 changes: 0 additions & 23 deletions docs/configuration.md

This file was deleted.

31 changes: 23 additions & 8 deletions src/playlist.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {h} from 'preact';
import {ui} from '@playkit-js/kaltura-player-js';
// @ts-expect-error Module '"@playkit-js/kaltura-player-js"' has no exported member 'core'
import {ui, core} from '@playkit-js/kaltura-player-js';
import {OnClickEvent} from '@playkit-js/common/dist/hoc/a11y-wrapper';
import {UpperBarManager, SidePanelsManager} from '@playkit-js/ui-managers';
import {PlaylistConfig, PluginPositions, PluginStates} from './types';
Expand Down Expand Up @@ -30,30 +31,38 @@ export class Playlist extends KalturaPlayer.core.BasePlugin {
static defaultConfig: PlaylistConfig = {
position: SidePanelPositions.RIGHT,
expandMode: SidePanelModes.ALONGSIDE,
expandOnFirstPlay: true
expandOnFirstPlay: true,
playNextOnError: true
};

constructor(name: string, player: KalturaPlayerTypes.Player, config: PlaylistConfig) {
super(name, player, config);
this._player = player;
this._dataManager = new DataManager(this._player, this.logger);
// subscribe on store changes
this._unsubscribeStore = this._player.ui.store?.subscribe(() => {
const state = this._player.ui.store.getState();
if (state.shell.playerClasses.includes('has-live-plugin-overlay') && !this._offlineSlateActive) {
this._unsubscribeStore = this.uiStore?.subscribe(() => {
const {shell} = this.uiStore.getState();
if (shell.playerClasses.includes('has-live-plugin-overlay') && !this._offlineSlateActive) {
this._offlineSlateActive = true;
this._activatePlugin();
}
if (this._activePresetName !== '' && this._activePresetName !== state.shell.activePresetName) {
this._activePresetName = state.shell.activePresetName;
if (this._activePresetName !== '' && this._activePresetName !== shell.activePresetName) {
this._activePresetName = shell.activePresetName;
// when switching from non-broadcasting live to VOD we need to toggle the plugin since the live plugin disables it
this._deactivatePlugin();
this._activatePlugin();
} else if (this._activePresetName === '') {
this._activePresetName = state.shell.activePresetName;
this._activePresetName = shell.activePresetName;
}
this._addSidePanel();
});
if (this.config.playNextOnError) {
this.eventManager.listen(this.player, core.EventType.ERROR, this._handleError);
semarche-kaltura marked this conversation as resolved.
Show resolved Hide resolved
}
}

get uiStore() {
return this._player.ui.store;
}

get sidePanelsManager() {
Expand Down Expand Up @@ -192,6 +201,12 @@ export class Playlist extends KalturaPlayer.core.BasePlugin {
});
};

private _handleError = () => {
if (this._player.playlist?.items?.length > 1) {
this.player.playlist.playNext();
SivanA-Kaltura marked this conversation as resolved.
Show resolved Hide resolved
}
};

static isValid(): boolean {
return true;
}
Expand Down
1 change: 1 addition & 0 deletions src/types/playlist-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ export interface PlaylistConfig {
position: string;
expandMode: string;
expandOnFirstPlay: boolean;
playNextOnError: boolean;
}
Loading