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

feat(audio): auto disable audio when invalid src (VIV-877) #1394

Merged
merged 17 commits into from
Apr 19, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
5 changes: 4 additions & 1 deletion components/audio/src/vwc-audio.scss
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ $disabled: var(--vvd-color-neutral-50);
align-items: center;
justify-content: flex-start;

&.disabled {
pointer-events: none;
}

> .scrubber {
#{media-controls-variables.$vwc-media-controls-scrubber-color}: var(#{connotation.$vvd-color-connotation});
min-width: 200px;
Expand All @@ -49,7 +53,6 @@ $disabled: var(--vvd-color-neutral-50);
#{media-controls-variables.$vwc-media-controls-scrubber-color}: #{$disabled};
--disable-scrub: #{$disabled};
cursor: not-allowed;
pointer-events: none;
}
> .control-button {
> .icon {
Expand Down
16 changes: 14 additions & 2 deletions components/audio/src/vwc-audio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,14 @@ export class VWCAudio extends LitElement {

@internalProperty()
private _playheadPosition = 0;
#faultySrc = true;

protected override firstUpdated(_changedProperties: PropertyValues): void {
super.firstUpdated(_changedProperties);
setEvents(this._audio, {
error: () => this.toggleFaultySrcState(),
/* istanbul ignore next */
loadedmetadata: () => this._duration = this._audio.duration,
loadedmetadata: () => { this.toggleFaultySrcState(); this._duration = this._audio.duration; },
/* istanbul ignore next */
timeupdate: () => this._playheadPosition = this._audio.currentTime,
/* istanbul ignore next */
Expand All @@ -113,8 +115,15 @@ export class VWCAudio extends LitElement {
/* istanbul ignore next */
pause: () => this._isPlaying = false
});
this.toggleFaultySrcState();
}

private toggleFaultySrcState() {
this.#faultySrc = !this.src || this._audio?.error !== null;
if (this.hasUpdated) {
this.requestUpdate();
}
}
play(): Promise<void> {
return this._audio.play();
}
Expand All @@ -134,12 +143,15 @@ export class VWCAudio extends LitElement {
override update(_changedProperties: PropertyValues): void {
this._scrubber?.setPosition(this._playheadPosition / this._duration);
super.update(_changedProperties);
if(_changedProperties.has('src')) {
this.toggleFaultySrcState();
}
}

protected getRenderClasses(): ClassInfo {
return {
[`connotation-${this.connotation}`]: !!this.connotation,
['disabled']: this.disabled,
['disabled']: this.disabled || this.#faultySrc,
loading: this._loading
};
}
Expand Down
2 changes: 1 addition & 1 deletion components/audio/stories/audio.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const StoryShell = (

<div class="component-container">
${innerStory(args)}
</div>`, { args: { src: "https://file-examples-com.github.io/uploads/2017/11/file_example_MP3_700KB.mp3", ...defaultArgs } }
</div>`, { args: { src: "https://download.samplelib.com/mp3/sample-6s.mp3", ...defaultArgs } }
);
};

Expand Down
51 changes: 50 additions & 1 deletion components/audio/test/audio.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,52 @@ describe('vwc-audio', () => {
expect(audioElement instanceof VWCAudio).to.eq(true);
});


describe('src', function () {
it(`should set the src property if src attribute is set`, async function () {
const url = 'https://file-examples-com.github.io/uploads/2017/11/file_example_MP3_5MG.mp3';
const [actualElement] = addElements(textToDomToParent(`<vwc-audio src="${url}"></vwc-audio>`));
expect(actualElement.src).to.eq(url);
});

it('should set disabled class when src is empty', async function () {
const [actualElement] = addElements(textToDomToParent(`<vwc-audio></vwc-audio>`));
await actualElement.updateComplete;
expect(actualElement.shadowRoot?.querySelector('.audio').classList.contains('disabled')).to.eq(true);
});

it('should remove disabled class when src is set and no error', async function () {
const url = 'https://file-examples-com.github.io/uploads/2017/11/file_example_MP3_5MG.mp3';
const [actualElement] = addElements(textToDomToParent(`<vwc-audio src="${url}"></vwc-audio>`));
await actualElement.updateComplete;
actualElement._audio.dispatchEvent(new Event('loadedmetadata'));
await actualElement.updateComplete;
expect(actualElement.shadowRoot?.querySelector('.audio').classList.contains('disabled')).to.eq(false);
});

it('should set disabled class when src removed', async function () {
const url = 'https://file-examples-com.github.io/uploads/2017/11/file_example_MP3_5MG.mp3';
const [actualElement] = addElements(textToDomToParent(`<vwc-audio src="${url}"></vwc-audio>`));
await actualElement.updateComplete;
actualElement.src = '';
await actualElement.updateComplete;
await actualElement.updateComplete;
expect(actualElement.shadowRoot?.querySelector('.audio').classList.contains('disabled')).to.eq(true);
});

it('should set disabled class when src is falty', async function () {
const url = 'https://file-examples-com.github.io/uploads/2017/11/file_example_MP3_5MG.mp3';
const [actualElement] = addElements(textToDomToParent(`<vwc-audio src="${url}"></vwc-audio>`));
await actualElement.updateComplete;
actualElement._audio.addEventListener('error', () => {
expect(actualElement.shadowRoot?.querySelector('.audio').classList.contains('disabled')).to.eq(true);
});
Object.defineProperty(actualElement._audio, 'error', {
get: () => {
return { code: 4 };
}
});
actualElement._audio.dispatchEvent(new Event('error'));
});
});

describe('currentTime', function () {
Expand Down Expand Up @@ -80,6 +119,16 @@ describe('vwc-audio', () => {
await audioElement.updateComplete;
expect(audioElement.shadowRoot.querySelector('.audio').classList.contains('disabled')).to.eq(true);
});

it('should set disabled true if set on the element', async function () {
const [audioElement] = addElements(textToDomToParent(`<vwc-audio></vwc-audio>`));
await audioElement.updateComplete;
audioElement.src = 'https://download.samplelib.com/mp3/sample-9s.mp3';
await audioElement.updateComplete;
audioElement.disabled = true;
await audioElement.updateComplete;
expect(audioElement.hasAttribute('disabled')).to.eq(true);
});
});

describe('scrub-bar', function () {
Expand Down
4 changes: 2 additions & 2 deletions components/media-controller/src/vwc-scrub-bar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -286,9 +286,9 @@ class VWCScrubBar extends HTMLElement {
.map(prop('value'))
.onValue(
percentage => (trackEl.style.backgroundImage = `linear-gradient(90deg, ${TRACK_ACTIVE_COLOR} 0%, ${TRACK_ACTIVE_COLOR} ${
percentage * 100
(!isNaN(percentage) ? percentage : 0) * 100
}%, ${TRACK_INACTIVE_COLOR} ${
percentage * 100
(!isNaN(percentage) ? percentage : 0) * 100
}%, ${TRACK_INACTIVE_COLOR} 100%)`)
);

Expand Down
2 changes: 1 addition & 1 deletion components/tags/test/tag.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ describe('Tag', () => {
});

describe('shouldRenderRipple', async function () {
const [actualElement] = (
const [actualElement] = addElement(
textToDomToParent(`<${COMPONENT_NAME} selectable removable text="Tag Text">Button Text</${COMPONENT_NAME}>`)
);
actualElement.shouldRenderRipple = true;
Expand Down
5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@
"lodash": "^4.17.21",
"minimist": "^1.2.5",
"mocha": "^8.1.3",
"playwright": "1.32.3",
"prism": "^4.1.2",
"remove-dir-safe": "^2.0.0",
"semver-compare": "^1.0.0",
Expand Down Expand Up @@ -159,7 +160,5 @@
"**/glob-parent": "^6.0.2",
"**/minimist": "^1.2.6"
},
"dependencies": {
"playwright": "^1.32.3"
}
"dependencies": {}
}
Binary file modified ui-tests/snapshots/vwc-audio.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 22 additions & 12 deletions ui-tests/tests/vwc-audio/index.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,39 @@
import vvdCore from '@vonage/vvd-core';
import '@vonage/vwc-audio';

async function setAudioSrcWithInfinityDuration() {
const audio = document.querySelector('#infinity-duration');
Object.defineProperty(audio._audio, 'duration', {value: Infinity});

audio._audio.dispatchEvent(new Event('loadedmetadata'));

await audio.updateComplete;
}

export async function createElementVariations(wrapper) {
const testWrapper = document.createElement('div');
wrapper.classList.add('grid');
testWrapper.classList.add('grid');
testWrapper.innerHTML =
`
<vwc-audio timestamp></vwc-audio>
<vwc-audio connotation="primary"></vwc-audio>
<vwc-audio src="https://download.samplelib.com/mp3/sample-6s.mp3" timestamp></vwc-audio>
<vwc-audio id="badSrc" timestamp></vwc-audio>
<vwc-audio src="https://download.samplelib.com/mp3/sample-6s.mp3" connotation="primary"></vwc-audio>
<vwc-audio src="https://download.samplelib.com/mp3/sample-6s.mp3" disabled connotation="primary"></vwc-audio>
<vwc-audio id="infinity-duration" timestamp></vwc-audio>
<vwc-audio timestamp connotation="primary"></vwc-audio>
<vwc-audio noseek="true"></vwc-audio>
<vwc-audio disabled connotation="primary"></vwc-audio>
<vwc-audio disabled connotation="cta" timestamp></vwc-audio>
<vwc-audio src="https://download.samplelib.com/mp3/sample-6s.mp3" timestamp connotation="primary"></vwc-audio>
<vwc-audio src="https://download.samplelib.com/mp3/sample-6s.mp3" noseek="true"></vwc-audio>
<vwc-audio src="https://download.samplelib.com/mp3/sample-6s.mp3" disabled connotation="primary"></vwc-audio>
<vwc-audio src="https://download.samplelib.com/mp3/sample-6s.mp3" disabled connotation="cta" timestamp></vwc-audio>
`;

wrapper.appendChild(testWrapper);
const audios = Array.from(document.querySelectorAll('vwc-audio'));
await Promise.all(audios.map(audio => audio.updateComplete));
const sourcedAudios = audios.filter(audio => audio.src);
await Promise.all(sourcedAudios.map(audio => new Promise(res => audio._audio.addEventListener('loadedmetadata', res))));

const audio = document.querySelector('#infinity-duration');
await audio.updateComplete;
Object.defineProperty(audio._audio, 'duration', {value: Infinity});
audio._audio.dispatchEvent(new Event('loadedmetadata'));

await audio.updateComplete;
await setAudioSrcWithInfinityDuration();

await vvdCore.settled;
}
Expand Down
2 changes: 1 addition & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -15120,7 +15120,7 @@ [email protected]:
resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.32.3.tgz#e6dc7db0b49e9b6c0b8073c4a2d789a96f519c48"
integrity sha512-SB+cdrnu74ZIn5Ogh/8278ngEh9NEEV0vR4sJFmK04h2iZpybfbqBY0bX6+BLYWVdV12JLLI+JEFtSnYgR+mWg==

playwright@^1.32.3:
[email protected]:
version "1.32.3"
resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.32.3.tgz#88583167880e42ca04fa8c4cc303680f4ff457d0"
integrity sha512-h/ylpgoj6l/EjkfUDyx8cdOlfzC96itPpPe8BXacFkqpw/YsuxkpPyVbzEq4jw+bAJh5FLgh31Ljg2cR6HV3uw==
Expand Down