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-14246): add cypress tests #71

Merged
merged 9 commits into from
Dec 25, 2024
Merged
Show file tree
Hide file tree
Changes from 7 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
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
281 changes: 281 additions & 0 deletions cypress/e2e/related.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,281 @@
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, getPlayer} 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.wait(1500).then(() => {
roeedean marked this conversation as resolved.
Show resolved Hide resolved
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);
expect(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
Loading