Skip to content

Commit

Permalink
fix(FEC-14246): add cypress tests (#71)
Browse files Browse the repository at this point in the history
### Description of the Changes

added cypress and tests to the project.

### CheckLists

- [ v ] changes have been done against master branch, and PR does not
conflict
- [ v ] new unit / functional tests have been added (whenever
applicable)
- [ v ] test are passing in local environment
- [ v ] Travis tests are passing (or test results are not worse than on
master branch :))
- [ ] Docs have been updated

---------

Co-authored-by: Roee Dean <[email protected]>
  • Loading branch information
roeedean and Roee Dean authored Dec 25, 2024
1 parent 9580b11 commit 9946417
Show file tree
Hide file tree
Showing 20 changed files with 1,483 additions and 43 deletions.
3 changes: 2 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
node_modules
dist
webpack.config.js
webpack.config.js
cypress
2 changes: 1 addition & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"root": true,
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint", "prettier", "jsdoc"],
"plugins": ["@typescript-eslint", "prettier", "jsdoc", "cypress"],
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "preact", "plugin:jsdoc/recommended"],
"globals": {
"KalturaPlayer": true,
Expand Down
7 changes: 6 additions & 1 deletion .github/workflows/run_canary.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,16 @@ on:
- master

jobs:
test:
uses: kaltura/playkit-js-common/.github/workflows/cypress.yml@master
secrets: inherit

canary:
if: ${{ github.actor != 'PlaykitJs-Bot' }}
uses: kaltura/playkit-js-common/.github/workflows/canary_plugin.yaml@master
secrets: inherit
with:
schema-type: "playerV3Versions"
schema-type: 'playerV3Versions'
tests-yarn-run-to-execute: 'eslint'
enabled-openssl-legacy-provider: 'false'
node-version: '18.x'
7 changes: 4 additions & 3 deletions .github/workflows/run_canary_full_flow.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ jobs:
PLAYER_MSTEAMS_WEBHOOK: ${{ secrets.PLAYER_MSTEAMS_WEBHOOK }}
PLAYER_GITHUB_BOT_TOKEN: ${{ secrets.PLAYER_GITHUB_BOT_TOKEN }}
with:
type: "plugin"
stage: "canary"
schema-type: "playerV3Versions"
type: 'plugin'
stage: 'canary'
schema-type: 'playerV3Versions'
tests-yarn-run-to-execute: 'eslint'
enabled-openssl-legacy-provider: 'false'
node-version: '18.x'
7 changes: 4 additions & 3 deletions .github/workflows/run_prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ jobs:
PLAYER_MSTEAMS_WEBHOOK: ${{ secrets.PLAYER_MSTEAMS_WEBHOOK }}
PLAYER_GITHUB_BOT_TOKEN: ${{ secrets.PLAYER_GITHUB_BOT_TOKEN }}
with:
type: "plugin"
env: "prod"
schema-type: "playerV3Versions"
type: 'plugin'
env: 'prod'
schema-type: 'playerV3Versions'
tests-yarn-run-to-execute: 'eslint'
enabled-openssl-legacy-provider: 'false'
node-version: '18.x'
7 changes: 6 additions & 1 deletion .github/workflows/run_tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,18 @@ run-name: Player And Plugin Tests
on:
pull_request:
branches:
- "*"
- '*'

jobs:
tests:
uses: kaltura/playkit-js-common/.github/workflows/cypress.yml@master
secrets: inherit
running-tests:
uses: kaltura/ovp-pipelines-pub/.github/workflows/player_tests.yaml@master
with:
yarn-run-to-execute: 'eslint'
node-version: '18.x'

notification:
if: always()
uses: kaltura/ovp-pipelines-pub/.github/workflows/notification.yaml@master
Expand Down
12 changes: 12 additions & 0 deletions cypress.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import {defineConfig} from 'cypress';

export default defineConfig({
experimentalWebKitSupport: true,
chromeWebSecurity: false,
defaultCommandTimeout: 30000,
fileServerFolder: 'cypress/public',
e2e: {
supportFile: false,
watchForFileChanges: false
}
});
2 changes: 2 additions & 0 deletions cypress/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
public/playkit-related.js
public/playkit-related.js.map
282 changes: 282 additions & 0 deletions cypress/e2e/related.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,282 @@
declare global {
interface Window {
KalturaPlayer: {
setup: (config: any) => any;
getPlayer: () => any;
};
}
}

import {clickOnNextButton, clickOnListToggle, clickOnCloseButton, clickOnRelatedEntry} from './utils/actions';
import {
expectElementContains,
expectElementDoesntExist,
expectElementExists,
expectRelatedGridVisible,
expectRelatedListVisible,
setupAndExpect
} from './utils/expects';
import {
getRelatedGridElement,
getRelatedListElement,
getNextButtonElement,
getListToggleButtonElement,
getCountdownElement,
getCloseButtonElement
} from './utils/getters';
import {loadPlayerAndSetMedia, mockRelatedEntries} from './utils/setup';
import {DEFAULT_COUNTDOWN_TIME, DEFAULT_ENTRIES_LIMIT} from './utils/values';

describe('Related plugin', () => {
describe('entry relation methods', () => {
beforeEach(() => {
cy.intercept('GET', '**/service/playlist/execute*', {
body: {
data: mockRelatedEntries
}
});

cy.intercept('GET', '**/service/playlist*', req => {
if (req.body?.filter?.objectType === 'KalturaMediaEntryFilterForPlaylist') {
req.reply({
data: mockRelatedEntries
});
}
});
});

it('should load related entries from playlistId', () => {
const playlistId = 'test_playlist_123';
setupAndExpect({playlistId}, loadPlayerAndSetMedia, () => {
clickOnListToggle();
expectElementExists(getRelatedListElement);
expectElementContains(getRelatedListElement, [mockRelatedEntries[0].name, mockRelatedEntries[1].name]);
});
});

it('should load related entries from entryList', () => {
const entryList = mockRelatedEntries.map(entry => ({
entryId: entry.id,
...entry
}));
setupAndExpect({entryList}, loadPlayerAndSetMedia, () => {
clickOnListToggle();
expectElementExists(getRelatedListElement);
expectElementContains(getRelatedListElement, [mockRelatedEntries[0].name, mockRelatedEntries[1].name]);
});
});

it('should load related entries from sourcesList', () => {
const sourcesList = mockRelatedEntries.map(entry => ({
id: entry.id,
duration: entry.duration,
metadata: {
name: entry.name
},
progressive: [
{
mimetype: 'video/mp4',
url: 'test-video.mp4'
}
]
}));
setupAndExpect({sourcesList}, loadPlayerAndSetMedia, () => {
clickOnListToggle();
expectElementExists(getRelatedListElement);
expectElementContains(getRelatedListElement, [mockRelatedEntries[0].name, mockRelatedEntries[1].name]);
});
});

it('should load related entries using context when useContext is true', () => {
setupAndExpect({useContext: true, entriesByContextLimit: 2}, loadPlayerAndSetMedia, () => {
clickOnListToggle();
expectElementExists(getRelatedListElement);
expectElementContains(getRelatedListElement, [mockRelatedEntries[0].name, mockRelatedEntries[1].name]);
});
});

it('should prioritize playlistId over other methods', () => {
const playlistEntries = [
{
id: 'playlist_1',
name: 'Playlist Video 1',
description: 'From Playlist',
thumbnailUrl: 'thumb1.jpg',
duration: 120
}
];

// Mock playlist response with different entries
cy.intercept('GET', '**/service/playlist/execute*', {
body: {
data: playlistEntries
}
});

setupAndExpect(
{
playlistId: 'test_playlist',
entryList: mockRelatedEntries,
sourcesList: mockRelatedEntries,
useContext: true
},
loadPlayerAndSetMedia,
() => {
clickOnListToggle();
expectElementExists(getRelatedListElement);
expectElementContains(getRelatedListElement, [playlistEntries[0].name]);
expectElementDoesntExist(() => cy.contains(mockRelatedEntries[0].name));
}
);
});

it('should prioritize entryList over sourcesList and context', () => {
const sourcesList = [
{
id: 'source_1',
metadata: {name: 'Source Video'},
progressive: [{mimetype: 'video/mp4', url: 'test.mp4'}]
}
];

setupAndExpect(
{
entryList: mockRelatedEntries,
sourcesList,
useContext: true
},
loadPlayerAndSetMedia,
() => {
clickOnListToggle();
expectElementExists(getRelatedListElement);
expectElementContains(getRelatedListElement, [mockRelatedEntries[0].name]);
expectElementDoesntExist(() => cy.contains('Source Video'));
}
);
});
});

describe('initialization', () => {
it('should not show related content by default when video starts', () => {
setupAndExpect({}, loadPlayerAndSetMedia, () => {
expectElementDoesntExist(getRelatedGridElement);
expectElementDoesntExist(getRelatedListElement);
});
});

it('should load with provided related entries', () => {
setupAndExpect({entryList: mockRelatedEntries}, loadPlayerAndSetMedia, () => {
clickOnListToggle();
expectElementExists(getRelatedListElement);
expectElementContains(getRelatedListElement, [mockRelatedEntries[0].name, mockRelatedEntries[1].name]);
});
});
});

describe('list view', () => {
beforeEach(() => {
cy.intercept('GET', '**/service/playlist*', {
body: {
data: mockRelatedEntries
}
});
});

it('should show list view when toggle button is clicked', () => {
setupAndExpect({entryList: mockRelatedEntries}, loadPlayerAndSetMedia, () => {
expectElementDoesntExist(getRelatedListElement);
clickOnListToggle();
expectElementExists(getRelatedListElement);
});
});

it('should hide list view when close button is clicked', () => {
setupAndExpect({entryList: mockRelatedEntries}, loadPlayerAndSetMedia, () => {
clickOnListToggle();
expectElementExists(getRelatedListElement);
clickOnCloseButton();
expectElementDoesntExist(getRelatedListElement);
});
});

it('should play selected entry when clicked', () => {
setupAndExpect({entryList: mockRelatedEntries}, loadPlayerAndSetMedia, () => {
clickOnListToggle();
clickOnRelatedEntry(0);
// Verify the video source has changed to the selected entry
cy.window().then(win => {
expect((win as any).KalturaPlayer.getPlayer().sources.id).to.equal(mockRelatedEntries[0].id);
});
});
});
});

describe('auto continue', () => {
it('should show countdown when video ends with autoContinue enabled', () => {
setupAndExpect({entryList: mockRelatedEntries, autoContinue: true}, loadPlayerAndSetMedia, player => {
player.currentTime = player.duration;
expectElementExists(getCountdownElement);
});
});

it('should not show countdown when autoContinue is disabled', () => {
setupAndExpect({entryList: mockRelatedEntries, autoContinue: false}, loadPlayerAndSetMedia, player => {
player.currentTime = player.duration;
expectElementDoesntExist(getCountdownElement);
});
});

it('should auto continue to next video after countdown', () => {
setupAndExpect({entryList: mockRelatedEntries, autoContinue: true, autoContinueTime: 1}, loadPlayerAndSetMedia, player => {
player.currentTime = player.duration;
cy.window().then(win => {
expect((win as any).KalturaPlayer.getPlayer().sources.id).to.equal(mockRelatedEntries[0].id);
});
}
);
});
});

describe('grid view', () => {
it('should show grid view on pause when showOnPlaybackPaused is true', () => {
setupAndExpect({entryList: mockRelatedEntries, showOnPlaybackPaused: true}, loadPlayerAndSetMedia, player => {
player.pause();
expectElementExists(getRelatedGridElement);
});
});

it('should not show grid view on pause when showOnPlaybackPaused is false', () => {
setupAndExpect({entryList: mockRelatedEntries, showOnPlaybackPaused: false}, loadPlayerAndSetMedia, player => {
player.pause();
expectElementDoesntExist(getRelatedGridElement);
});
});

it('should play selected entry from grid when clicked', () => {
setupAndExpect({entryList: mockRelatedEntries, showOnPlaybackPaused: true}, loadPlayerAndSetMedia, player => {
player.pause();
clickOnRelatedEntry(0);
cy.window().then(win => {
expect((win as any).KalturaPlayer.getPlayer().sources.id).to.equal(mockRelatedEntries[0].id);
});
});
});
});

describe('next button', () => {
it('should show next button when there are related entries', () => {
setupAndExpect({entryList: mockRelatedEntries}, loadPlayerAndSetMedia, () => {
expectElementExists(getNextButtonElement);
});
});

it('should play next entry when next button is clicked', () => {
setupAndExpect({entryList: mockRelatedEntries}, loadPlayerAndSetMedia, () => {
clickOnNextButton();
cy.window().then(win => {
expect((win as any).KalturaPlayer.getPlayer().sources.id).to.equal(mockRelatedEntries[0].id);
});
});
});
});
});
17 changes: 17 additions & 0 deletions cypress/e2e/utils/actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {getNextButtonElement, getListToggleButtonElement, getCloseButtonElement, getRelatedEntryElement} from './getters';

export const clickOnNextButton = () => {
getNextButtonElement().click({force: true});
};

export const clickOnListToggle = () => {
getListToggleButtonElement().click({force: true});
};

export const clickOnCloseButton = () => {
getCloseButtonElement().click({force: true});
};

export const clickOnRelatedEntry = (index: number) => {
getRelatedEntryElement(index).click({force: true});
};
Loading

0 comments on commit 9946417

Please sign in to comment.