From 1c68654090645cccf65da0cee6b4b27a746884ec Mon Sep 17 00:00:00 2001 From: rudywaltz Date: Tue, 31 May 2022 13:24:15 +0200 Subject: [PATCH] #475@minor: Adds support for HTMLMediaElement. --- packages/happy-dom/src/config/ElementTag.ts | 5 +- .../config/NonImplemenetedElementClasses.ts | 2 - .../html-media-element/HTMLMediaElement.ts | 137 ++++++++++++++++++ .../html-media-element/IHTMLMediaElement.ts | 52 +++++++ .../HTMLMediaElement.test.ts | 44 ++++++ 5 files changed, 236 insertions(+), 4 deletions(-) create mode 100644 packages/happy-dom/src/nodes/html-media-element/HTMLMediaElement.ts create mode 100644 packages/happy-dom/src/nodes/html-media-element/IHTMLMediaElement.ts create mode 100644 packages/happy-dom/test/nodes/html-media-element/HTMLMediaElement.test.ts diff --git a/packages/happy-dom/src/config/ElementTag.ts b/packages/happy-dom/src/config/ElementTag.ts index 0044d86cb..e0086390e 100644 --- a/packages/happy-dom/src/config/ElementTag.ts +++ b/packages/happy-dom/src/config/ElementTag.ts @@ -13,6 +13,7 @@ import HTMLLabelElement from '../nodes/html-label-element/HTMLLabelElement'; import HTMLSlotElement from '../nodes/html-slot-element/HTMLSlotElement'; import HTMLMetaElement from '../nodes/html-meta-element/HTMLMetaElement'; import HTMLBaseElement from '../nodes/html-base-element/HTMLBaseElement'; +import HTMLMediaElement from '../nodes/html-media-element/HTMLMediaElement'; export default { A: HTMLElement, @@ -21,7 +22,7 @@ export default { AREA: HTMLElement, ARTICLE: HTMLElement, ASIDE: HTMLElement, - AUDIO: HTMLElement, + AUDIO: HTMLMediaElement, B: HTMLElement, BASE: HTMLBaseElement, BDI: HTMLElement, @@ -140,6 +141,6 @@ export default { U: HTMLElement, UL: HTMLElement, VAR: HTMLElement, - VIDEO: HTMLElement, + VIDEO: HTMLMediaElement, WBR: HTMLElement }; diff --git a/packages/happy-dom/src/config/NonImplemenetedElementClasses.ts b/packages/happy-dom/src/config/NonImplemenetedElementClasses.ts index 98c177060..fbc49580b 100644 --- a/packages/happy-dom/src/config/NonImplemenetedElementClasses.ts +++ b/packages/happy-dom/src/config/NonImplemenetedElementClasses.ts @@ -54,7 +54,5 @@ export default [ 'HTMLEmbedElement', 'HTMLObjectElement', 'HTMLParamElement', - 'HTMLVideoElement', - 'HTMLAudioElement', 'HTMLTrackElement' ]; diff --git a/packages/happy-dom/src/nodes/html-media-element/HTMLMediaElement.ts b/packages/happy-dom/src/nodes/html-media-element/HTMLMediaElement.ts new file mode 100644 index 000000000..339db3d7e --- /dev/null +++ b/packages/happy-dom/src/nodes/html-media-element/HTMLMediaElement.ts @@ -0,0 +1,137 @@ +import HTMLElement from '../html-element/HTMLElement'; +import IHTMLMediaElement from './IHTMLMediaElement'; + +/** + * HTML Base Element. + * + * Reference: + * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base. + */ +export default class HTMLMediaElement extends HTMLElement implements IHTMLMediaElement { + /** + * Returns autoplay. + * + * @returns Autoplay. + */ + public get autoplay(): boolean { + return this.getAttributeNS(null, 'autoplay') !== null; + } + + /** + * Sets autoplay. + * + * @param autoplay Autoplay. + */ + public set autoplay(autoplay: boolean) { + if (!autoplay) { + this.removeAttributeNS(null, 'autoplay'); + } else { + this.setAttributeNS(null, 'autoplay', ''); + } + } + + /** + * Returns controls. + * + * @returns Controls. + */ + public get controls(): boolean { + return this.getAttributeNS(null, 'controls') !== null; + } + + /** + * Sets controls. + * + * @param controls Controls. + */ + public set controls(controls: boolean) { + if (!controls) { + this.removeAttributeNS(null, 'controls'); + } else { + this.setAttributeNS(null, 'controls', ''); + } + } + + /** + * Returns paused. + * + * @returns Paused. + */ + public get paused(): boolean { + return this.getAttributeNS(null, 'paused') !== null; + } + + /** + * Sets paused. + * + * @param paused Paused. + */ + public set paused(paused: boolean) { + if (!paused) { + this.removeAttributeNS(null, 'paused'); + } else { + this.setAttributeNS(null, 'paused', ''); + } + } + + /** + * Returns loop. + * + * @returns Loop. + */ + public get loop(): boolean { + return this.getAttributeNS(null, 'loop') !== null; + } + + /** + * Sets loop. + * + * @param loop Loop. + */ + public set loop(loop: boolean) { + if (!loop) { + this.removeAttributeNS(null, 'loop'); + } else { + this.setAttributeNS(null, 'loop', ''); + } + } + /** + * Returns muted. + * + * @returns muted. + */ + public get muted(): boolean { + return this.getAttributeNS(null, 'muted') !== null; + } + + /** + * Sets muted. + * + * @param muted muted. + */ + public set muted(muted: boolean) { + if (!muted) { + this.removeAttributeNS(null, 'muted'); + } else { + this.setAttributeNS(null, 'muted', ''); + } + } + + /** + * + */ + public pause(): void { + this.paused = true; + } + + /** + * Clones a node. + * + * @override + * @param [deep=false] "true" to clone deep. + * @returns Cloned node. + */ + public cloneNode(deep = false): IHTMLMediaElement { + return super.cloneNode(deep); + } +} diff --git a/packages/happy-dom/src/nodes/html-media-element/IHTMLMediaElement.ts b/packages/happy-dom/src/nodes/html-media-element/IHTMLMediaElement.ts new file mode 100644 index 000000000..34ceeba27 --- /dev/null +++ b/packages/happy-dom/src/nodes/html-media-element/IHTMLMediaElement.ts @@ -0,0 +1,52 @@ +import IHTMLElement from '../html-element/IHTMLElement'; + +/** + * HTML Media Element. + * + * Reference: + * https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement. + */ +export default interface IHTMLMediaElement extends IHTMLElement { + // AddTextTrack; + autoplay: boolean; + // Buffered; // TODO + // CaptureStream; // TODO + controls: boolean; + // ControlsList: string; // TODO + // CrossOrigin: string; // TODO: enum? + // CurrentSrc: string; // TODO + // CurrentTime; // TODO + // DefaultMuted: boolean; // TODO + // DefaultPlaybackRate; // TODO + // DisableRemotePlayback: boolean; // TODO + // Duration: number; // TODO + // Ended: boolean; // TODO + // Error; // TODO object + loop: boolean; + // MediaKeys; // TODO + muted: boolean; + // NetworkState; // TODO + paused: boolean; + // Played: boolean; // TODO + // PlaybackRate: number; // TODO + + /** + * The HTMLMediaElement.pause() method will pause playback of the media, if the media is already in a paused state this method will have no effect. + */ + + pause(): void; + + /** + * The HTMLMediaElement play() method attempts to begin playback of the media. It returns a Promise which is resolved when playback has been successfully started. + */ + // play(): Promise; // TODO function + + /** + * Clones a node. + * + * @override + * @param [deep=false] "true" to clone deep. + * @returns Cloned node. + */ + cloneNode(deep: boolean): IHTMLMediaElement; +} diff --git a/packages/happy-dom/test/nodes/html-media-element/HTMLMediaElement.test.ts b/packages/happy-dom/test/nodes/html-media-element/HTMLMediaElement.test.ts new file mode 100644 index 000000000..40cc4d713 --- /dev/null +++ b/packages/happy-dom/test/nodes/html-media-element/HTMLMediaElement.test.ts @@ -0,0 +1,44 @@ +import Window from '../../../src/window/Window'; +import IWindow from '../../../src/window/IWindow'; +import IDocument from '../../../src/nodes/document/IDocument'; +import IHTMLMediaElement from '../../../src/nodes/html-media-element/IHTMLMediaElement'; + +describe('HTMLMediaElement', () => { + let window: IWindow; + let document: IDocument; + let element: IHTMLMediaElement; + + beforeEach(() => { + window = new Window(); + document = window.document; + element = document.createElement('audio'); + }); + + afterEach(() => { + jest.restoreAllMocks(); + }); + + for (const property of ['autoplay', 'controls', 'paused', 'loop', 'muted']) { + describe(`get ${property}()`, () => { + it('Returns attribute value.', () => { + expect(element[property]).toBe(false); + element.setAttribute(property, ''); + expect(element[property]).toBe(true); + }); + }); + + describe(`set ${property}()`, () => { + it('Sets attribute value.', () => { + element[property] = true; + expect(element.getAttribute(property)).toBe(''); + }); + }); + } + + describe('paused', () => { + it('Set paused attribute as well', () => { + element.pause(); + expect(element.getAttribute('paused')).toBe(''); + }); + }); +});