Skip to content

Commit

Permalink
chore: updates e2e tests
Browse files Browse the repository at this point in the history
  • Loading branch information
James Taylor committed Mar 4, 2024
1 parent b33b130 commit 5ca2397
Show file tree
Hide file tree
Showing 10 changed files with 179 additions and 54 deletions.
Binary file added apps/docs/assets/ui-tests/sample-5s.webm
Binary file not shown.
Binary file added apps/docs/assets/ui-tests/sample-poster.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 2 additions & 9 deletions libs/components/src/lib/video-player/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,7 @@ A video source can be provided to the component using the `src` attribute.
<style>
html { max-inline-size: 800px }
</style>
<script>
function addAutoplay() {
document.getElementById('video').src = '//d2zihajmogu5jn.cloudfront.net/elephantsdream/ed_hd.mp4'
}
</script>
<vwc-video-player id="video"></vwc-video-player>
<button onclick="addSrc()">Add src</button>
<vwc-video-player src="//d2zihajmogu5jn.cloudfront.net/elephantsdream/ed_hd.mp4"></vwc-video-player>
```

#### Source element
Expand Down Expand Up @@ -207,10 +201,9 @@ When `loop` is set, the video will restart automatically when it reaches the end
document.getElementById('video').autoplay = true;;
}
</script>
<vwc-video-player id="video" loop>
<vwc-video-player autoplay loop>
<source src="//d2zihajmogu5jn.cloudfront.net/elephantsdream/ed_hd.mp4" type="video/mp4">
</vwc-video-player>
<button onclick="addAuto()">Add autoplay</button>
```

## Events
Expand Down
153 changes: 139 additions & 14 deletions libs/components/src/lib/video-player/ui.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,154 @@ import {

const components = ['video-player'];

test('initialises in a ready to play state', async ({ page }: { page: Page }) => {
test('should show the component', async ({ page }: { page: Page }) => {
const template = `
<div style="max-width: 600px; padding: 8px;">
<vwc-video-player poster="//live.staticflickr.com/45/150125790_2df6475599_b.jpg">
<source src="//vjs.zencdn.net/v/oceans.webm" type="video/mp4">
</vwc-video-player>
<style>
.layout {
max-width: 800px;
padding: 8px;
}
.spacer {
padding-bottom: 8px;
}
</style>
<div class="layout">
<div class="spacer">
<vwc-video-player id="video-player" poster="//live.staticflickr.com/45/150125790_2df6475599_b.jpg">
<source src="https://download.samplelib.com/webm/sample-5s.webm" type="video/webm">
</vwc-video-player>
</div>
<div class="spacer">
<vwc-video-player id="video-player-controls">
<source src="https://download.samplelib.com/webm/sample-5s.webm" type="video/webm">
</vwc-video-player>
</div>
<div class="spacer">
<vwc-video-player id="video-player-controls-2">
<source src="https://download.samplelib.com/webm/sample-5s.webm" type="video/webm">
<track kind="captions"
src="//d2zihajmogu5jn.cloudfront.net/elephantsdream/captions.en.vtt" srclang="en" label="English">
<track kind="descriptions"
src="//d2zihajmogu5jn.cloudfront.net/elephantsdream/descriptions.en.vtt" label="English" srclang="en">
<track kind="chapters" src="//d2zihajmogu5jn.cloudfront.net/elephantsdream/chapters.en.vtt" srclang="en">
</vwc-video-player>
</div>
<div class="spacer">
<vwc-video-player src="invalid.xyz"></vwc-video-player>
</div>
<div class="spacer">
<vwc-video-player></vwc-video-player>
</div>
</div>
`;

await loadComponents({
page,
components,
});
await loadTemplate({
page,
template,
});
await loadComponents({ page, components });
await loadTemplate({ page, template });

const testWrapper = await page.$('#wrapper');

await page.waitForLoadState('networkidle');
await page.waitForLoadState('domcontentloaded');

// Wait for the poster image to be fully loaded
const locator = page.locator('#video-player .vjs-poster img');
const promise = locator.evaluate((image: any) => image.complete || new Promise(f => image.onload = f));
await Promise.resolve(promise);

await page.waitForSelector('#video-player-controls .vjs-tech');
const videoEle = await page.$('#video-player-controls video');
const videoEle2 = await page.$('#video-player-controls-2 video');
const loadProgress = await page.$('#video-player-controls .vjs-load-progress');
const loadProgress2 = await page.$('#video-player-controls-2 .vjs-load-progress');
// hide elements that could lead to a flakey test
videoEle?.evaluate(element => element.style.visibility = 'hidden');
videoEle2?.evaluate(element => element.style.visibility = 'hidden');
loadProgress?.evaluate(element => element.style.visibility = 'hidden');
loadProgress2?.evaluate(element => element.style.visibility = 'hidden');

await videoEle!.evaluate(video => (video as HTMLVideoElement)!.play());
await videoEle2!.evaluate(video => (video as HTMLVideoElement)!.play());
await videoEle!.evaluate(video => (video as HTMLVideoElement)!.pause());
await videoEle2!.evaluate(video => (video as HTMLVideoElement)!.pause());

// activate menus
const videoWrapper = await page.$('#video-player-controls .vjs-controls-enabled');
videoWrapper?.evaluate(element => element.classList.add('vjs-user-active'));
const volumePanel = await page.$('#video-player-controls .vjs-volume-panel');
volumePanel?.evaluate(element => element.classList.add('vjs-hover'));
const playbackRate = await page.$('#video-player-controls .vjs-playback-rate.vjs-control');
playbackRate?.evaluate(element => element.classList.add('vjs-hover'));
const captions = await page.$('#video-player-controls-2 .vjs-subs-caps-button.vjs-control');
captions?.evaluate(element => element.classList.add('vjs-hover'));

expect(await testWrapper?.screenshot()).toMatchSnapshot(
'./snapshots/video-player.png'
);
});

test('should hide the track menu buttons when no track elements are provided', async ({ page }: { page: Page }) => {
const template = `
<vwc-video-player>
<source src="https://download.samplelib.com/webm/sample-5s.webm" type="video/webm">
</vwc-video-player>`;

await loadComponents({ page, components });
await loadTemplate({ page, template });
await page.waitForLoadState('domcontentloaded');
await page.waitForSelector('.vjs-tech');

await expect(page.locator('.vjs-subs-caps-button.vjs-control')).not.toHaveClass('.vjs-hidden');
await expect(page.locator('.vjs-descriptions-button.vjs-control')).not.toHaveClass('.vjs-hidden');
await expect(page.locator('.vjs-chapters-button.vjs-control')).not.toHaveClass('.vjs-hidden');
});

test('should show the button and populate the menu when adding caption tracks', async ({ page }: { page: Page }) => {
const template = `
<vwc-video-player>
<source src="https://download.samplelib.com/webm/sample-5s.webm" type="video/webm">
<track kind="captions"
src="//d2zihajmogu5jn.cloudfront.net/elephantsdream/captions.en.vtt" srclang="en" label="English">
</vwc-video-player>`;

await loadComponents({ page, components });
await loadTemplate({ page, template });
await page.waitForLoadState('domcontentloaded');
await page.waitForSelector('.vjs-tech');
const menuOptionEnglishText = await page.locator('.vjs-subs-caps-button.vjs-control .vjs-menu li:nth-child(3)').textContent();
await expect(page.locator('.vjs-subs-caps-button.vjs-control')).not.toHaveClass('.vjs-hidden');
expect(menuOptionEnglishText).toBe('English Captions');
});

test('should show the button and populate the menu when adding audio description tracks', async ({ page }: { page: Page }) => {
const template = `
<vwc-video-player>
<source src="https://download.samplelib.com/webm/sample-5s.webm" type="video/webm">
<track kind="descriptions"
src="//d2zihajmogu5jn.cloudfront.net/elephantsdream/descriptions.en.vtt" label="English" srclang="en">
</vwc-video-player>`;

await loadComponents({ page, components });
await loadTemplate({ page, template });
await page.waitForLoadState('domcontentloaded');
await page.waitForSelector('.vjs-tech');
const menuOptionEnglishText = await page.locator('.vjs-descriptions-button.vjs-control .vjs-menu li:nth-child(2)').textContent();
await expect(page.locator('.vjs-descriptions-button.vjs-control')).not.toHaveClass('.vjs-hidden');
expect(menuOptionEnglishText).toBe('English');
});

test('should show the button when adding a chapter track', async ({ page }: { page: Page }) => {
const template = `
<vwc-video-player>
<source src="https://download.samplelib.com/webm/sample-5s.webm" type="video/webm">
<track kind="chapters" src="//d2zihajmogu5jn.cloudfront.net/elephantsdream/chapters.en.vtt" srclang="en">
</vwc-video-player>`;

await loadComponents({ page, components });
await loadTemplate({ page, template });
await page.waitForLoadState('domcontentloaded');
await page.waitForSelector('.vjs-tech');
await expect(page.locator('.vjs-chapters-button.vjs-control')).not.toHaveClass('.vjs-hidden');
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions libs/components/src/lib/video-player/video-player.scss
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,10 @@
offset-block-end: 70px;
}

.vjs-modal-dialog-content {
text-align: center;
}

@container (max-inline-size: 660px) {
.vjs-skip-backward-5,
.vjs-skip-forward-5,
Expand Down
58 changes: 30 additions & 28 deletions libs/components/src/lib/video-player/video-player.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ describe('vwc-video-player', () => {
return element.shadowRoot!.querySelector('.vjs-modal-dialog-content');
}

function getTrackEles() {
const videoEle = getVideoEle();
return videoEle?.querySelectorAll('track');
}

function isBigPlayButtonVisible() {
const btn = getBigPlayButton();
if (!btn) return false;
Expand Down Expand Up @@ -91,19 +96,6 @@ describe('vwc-video-player', () => {
});
});

describe('invalid src', () => {
xit('should show the invalid src error message', async() => {
element = (await fixture(
`<${COMPONENT_TAG} src="invalid.xyz"></${COMPONENT_TAG}>`
)) as VideoPlayer;
await elementUpdated(element);
const noSrcErrorEl = element.shadowRoot!.getElementById('no-sources');
const dialogContentEl = getDialogContentEle();
expect(noSrcErrorEl?.classList.contains('vjs-hidden')).toBe(false);
expect(dialogContentEl!.textContent).toBe('No compatible source was found for this media.');
});
});

it('should show the big play button by removing the vjs-hidden class', async () => {
element = (await fixture(
`<${COMPONENT_TAG} src="${VIDEO_SRC}"></${COMPONENT_TAG}>`
Expand Down Expand Up @@ -186,9 +178,9 @@ describe('vwc-video-player', () => {
});

describe('captions', () => {
xit('should display the captions button and menu', async () => {
it('should add captions tracks as children of the video element', async () => {
element = (await fixture(
`<${COMPONENT_TAG} playback-rates="">
`<${COMPONENT_TAG}>
<source src="${VIDEO_SRC}" type="video/mp4">
<track
kind="captions"
Expand All @@ -204,45 +196,55 @@ describe('vwc-video-player', () => {
</${COMPONENT_TAG}>`
)) as VideoPlayer;
await elementUpdated(element);
expect(element.shadowRoot!.querySelectorAll('[kind="captions"]').length).toBe(2);
// const subsCapsBtn = element.shadowRoot!.querySelector('.vjs-subs-caps-button');
// console.log(subsCapsBtn?.innerHTML);
const trackEles = getTrackEles();
expect(trackEles.length).toBe(2);
expect(trackEles[0].getAttribute('label')).toBe('English');
expect(trackEles[0].getAttribute('kind')).toBe('captions');
expect(trackEles[1].getAttribute('label')).toBe('French');
expect(trackEles[1].getAttribute('kind')).toBe('captions');
});
});

describe('audio descriptions', () => {
it('should display the audio description button and menu', async () => {
it('should add descriptions tracks as children of the video element', async () => {
element = (await fixture(
`<${COMPONENT_TAG} playback-rates="">
`<${COMPONENT_TAG}>
<source src="${VIDEO_SRC}" type="video/mp4">
<track
kind="descriptions"
src="descriptions.en.vtt"
label="English"
srclang="en"
default>
<track
kind="descriptions"
src="descriptions.fr.vtt"
label="French"
srclang="fr">
<track
kind="descriptions"
src="descriptions.fr.vtt"
label="French"
srclang="fr">
</${COMPONENT_TAG}>`
)) as VideoPlayer;
await elementUpdated(element);
expect(element.shadowRoot!.querySelectorAll('[kind="descriptions"]').length).toBe(2);
const trackEles = getTrackEles();
expect(trackEles.length).toBe(2);
expect(trackEles[0].getAttribute('label')).toBe('English');
expect(trackEles[0].getAttribute('kind')).toBe('descriptions');
expect(trackEles[1].getAttribute('label')).toBe('French');
expect(trackEles[1].getAttribute('kind')).toBe('descriptions');
});
});

describe('chapters', () => {
it('should display the chapters button and menu', async () => {
it('should add chapter track as child of the video element', async () => {
element = (await fixture(
`<${COMPONENT_TAG} playback-rates="">
<source src="${VIDEO_SRC}" type="video/mp4">
<track kind="chapters" src="chapters.vtt">
</${COMPONENT_TAG}>`
)) as VideoPlayer;
await elementUpdated(element);
expect(element.shadowRoot!.querySelector('[kind="chapters"]')).not.toBe(null);
const trackEles = getTrackEles();
expect(trackEles.length).toBe(1);
expect(trackEles[0].getAttribute('kind')).toBe('chapters');
});
});

Expand Down
7 changes: 4 additions & 3 deletions libs/components/src/lib/video-player/video-player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,9 @@ export class VideoPlayer extends FoundationElement {
* @internal
*/
#initVideo() {
const settings = this.#getSettings();
if (this.player) this.player.dispose();
const settings = this.#getSettings();
const noSourcesError = this.shadowRoot!.getElementById('no-sources');

this.#videoEle = document.createElement('video');
const trackEles = this.querySelectorAll('track');
Expand All @@ -189,13 +190,13 @@ export class VideoPlayer extends FoundationElement {
if (this.loop) this.#videoEle.setAttribute('loop', '');
if (this.autoplay) this.#videoEle.setAttribute('autoplay', '');
const control = this.shadowRoot!.querySelector('.control');
const noSourcesError = this.shadowRoot!.getElementById('no-sources');

if (settings.sources && control) {
noSourcesError?.classList.add('vjs-hidden');
control.appendChild(this.#videoEle);
this.player = videojs(this.#videoEle, settings);
this.shadowRoot!.querySelector('[lang]')!.removeAttribute('lang'); // removes lang="current" from the component
// removes lang="current" to avoid clash with vivid localization
this.shadowRoot!.querySelector('[lang]')!.removeAttribute('lang');

this.player.on('play', () => this.$emit('play'));
this.player.on('pause', () => this.$emit('pause'));
Expand Down

0 comments on commit 5ca2397

Please sign in to comment.