Skip to content

Commit

Permalink
capricorn86#475@minor: Add crossOrigin and canPlayType to HTMLMediaEl…
Browse files Browse the repository at this point in the history
…ement.
  • Loading branch information
rudywaltz committed Jun 10, 2022
1 parent d91afa1 commit ce22cad
Show file tree
Hide file tree
Showing 3 changed files with 168 additions and 34 deletions.
107 changes: 84 additions & 23 deletions packages/happy-dom/src/nodes/html-media-element/HTMLMediaElement.ts
@@ -1,3 +1,4 @@
import Event from '../../event/Event';
import DOMException from '../../exception/DOMException';
import DOMExceptionNameEnum from '../../exception/DOMExceptionNameEnum';
import HTMLElement from '../html-element/HTMLElement';
Expand All @@ -11,6 +12,7 @@ import IHTMLMediaElement from './IHTMLMediaElement';
*/
export default class HTMLMediaElement extends HTMLElement implements IHTMLMediaElement {
#volume = 1;
#paused = true;
/**
* Returns autoplay.
*
Expand Down Expand Up @@ -55,28 +57,6 @@ export default class HTMLMediaElement extends HTMLElement implements IHTMLMediaE
}
}

/**
* 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.
*
Expand Down Expand Up @@ -120,6 +100,36 @@ export default class HTMLMediaElement extends HTMLElement implements IHTMLMediaE
}
}

/**
* Returns src.
*
* @returns Src.
*/
public get src(): string {
return this.getAttributeNS(null, 'src') || '';
}

/**
* Sets src.
*
* @param src Src.
*/
public set src(src: string) {
this.setAttributeNS(null, 'src', src);
if (Boolean(src)) {
this.dispatchEvent(new Event('canplay', { bubbles: false, cancelable: false }));
}
}

/**
* Returns currentSrc.
*
* @returns CurrentrSrc.
*/
public get currentSrc(): string {
return this.src;
}

/**
* Returns volume.
*
Expand Down Expand Up @@ -151,11 +161,62 @@ export default class HTMLMediaElement extends HTMLElement implements IHTMLMediaE
this.#volume = parsedVolume;
}

/**
* Returns crossOrigin.
*
* @returns CrossOrigin.
*/
public get crossOrigin(): string {
return this.getAttributeNS(null, 'crossorigin');
}

/**
* Sets crossOrigin.
*
* @param crossOrigin CrossOrigin.
*/
public set crossOrigin(crossOrigin: string | null) {
if (crossOrigin === null) {
return
}

if (['', 'use-credentials', 'anonymous'].includes(crossOrigin)) {
this.setAttributeNS(null, 'crossorigin', crossOrigin);
} else {
this.setAttributeNS(null, 'crossorigin', 'anonymous');
}
}

/**
* Returns paused.
*
* @returns Paused.
*/
public get paused(): boolean {
return this.#paused;
}

/**
*
*/
public pause(): void {
this.paused = true;
this.#paused = true;
}

/**
*
*/
public async play(): Promise<void> {
this.#paused = false;
return Promise.resolve();
}

/**
*
* @param _type
*/
public canPlayType(_type: string): string {
return '';
}

/**
Expand Down
Expand Up @@ -7,13 +7,20 @@ import IHTMLElement from '../html-element/IHTMLElement';
* https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement.
*/
export default interface IHTMLMediaElement extends IHTMLElement {
// AddTextTrack;
readonly currentSrc: string;
autoplay: boolean;
controls: boolean;
loop: boolean;
muted: boolean;
paused: boolean; // TODO readonly?
volume: number | string;
src: string;
crossOrigin: string; // Only anonymus and 'use-credentials' is valid

// AddTextTrack;
// Buffered; // TODO
// CaptureStream; // TODO
controls: boolean;
// ControlsList: string; // TODO
// CrossOrigin: string; // TODO: enum?
// CurrentSrc: string; // TODO
// CurrentTime; // TODO
// DefaultMuted: boolean; // TODO
Expand All @@ -22,14 +29,10 @@ export default interface IHTMLMediaElement extends IHTMLElement {
// Duration: number; // TODO
// Ended: boolean; // TODO readonly
// Error; // TODO object
loop: boolean;
// MediaKeys; // TODO
muted: boolean;
// NetworkState; // TODO
paused: boolean; // TODO readonly?
// Played: // TODO timeranges
// PlaybackRate: number; // TODO
volume: number | string;

/**
* 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.
Expand All @@ -40,7 +43,14 @@ export default interface IHTMLMediaElement extends IHTMLElement {
/**
* 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<void>; // TODO function
play(): Promise<void>;

/**
* The HTMLMediaElement method canPlayType() reports how likely it is that the current browser will be able to play media of a given MIME type.
* Https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/canPlayType
* possible return value: "" | "probably" | "maybe".
*/
canPlayType(_type: string): string;

/**
* Clones a node.
Expand Down
Expand Up @@ -4,6 +4,7 @@ import DOMException from '../../../src/exception/DOMException';
import DOMExceptionNameEnum from '../../../src/exception/DOMExceptionNameEnum';
import IDocument from '../../../src/nodes/document/IDocument';
import IHTMLMediaElement from '../../../src/nodes/html-media-element/IHTMLMediaElement';
import Event from '../../../src/event/Event';

describe('HTMLMediaElement', () => {
let window: IWindow;
Expand All @@ -20,7 +21,7 @@ describe('HTMLMediaElement', () => {
jest.restoreAllMocks();
});

for (const property of ['autoplay', 'controls', 'paused', 'loop', 'muted']) {
for (const property of ['autoplay', 'controls', 'loop', 'muted']) {
describe(`get ${property}()`, () => {
it('Returns attribute value.', () => {
expect(element[property]).toBe(false);
Expand All @@ -37,10 +38,52 @@ describe('HTMLMediaElement', () => {
});
}

for (const property of ['src']) {
describe(`get ${property}()`, () => {
it(`Returns the "${property}" attribute.`, () => {
element.setAttribute(property, 'test');
expect(element[property]).toBe('test');
});
});

describe(`set ${property}()`, () => {
it(`Sets the attribute "${property}".`, () => {
element[property] = 'test';
expect(element.getAttribute(property)).toBe('test');
});
});
}

describe('canplay event', () => {
it('Should dispatch after src set', () => {
let dispatchedEvent: Event = null;
element.addEventListener('canplay', (event: Event) => (dispatchedEvent = event));
element.src = 'https://songURL';
expect(dispatchedEvent.cancelable).toBe(false);
expect(dispatchedEvent.bubbles).toBe(false);
});
it('Should not dispatch if src is empty', () => {
let dispatchedEvent: Event = null;
element.addEventListener('canplay', (event: Event) => (dispatchedEvent = event));
element.src = '';
expect(dispatchedEvent).toBeNull();
});
});

describe('paused', () => {
it('Set paused attribute as well', () => {
it('Default is true', () => {
expect(element.paused).toBeTruthy();
});

it('Set false with play', () => {
element.play();
expect(element.paused).toBeFalsy();
});

it('Set true with pause', () => {
element.play();
element.pause();
expect(element.getAttribute('paused')).toBe('');
expect(element.paused).toBeTruthy();
});
});

Expand Down Expand Up @@ -82,4 +125,24 @@ describe('HTMLMediaElement', () => {
});
}
});

describe('canPlayType', () => {
it('Returns empty string', () => {
expect(element.canPlayType('notValidMIMEtype')).toBe('');
});
});

describe('CrossOrigin', () => {
for (const crossOrigin of ['', null, 'use-credentials', 'anonymous']) {
it(`Set ${crossOrigin} as a valid crossOrigin`, () => {
element.crossOrigin = crossOrigin;
expect(element.getAttribute('crossorigin')).toBe(crossOrigin);
});
}

it(`Return 'anonymous' if crossOrigin is not valid`, () => {
element.crossOrigin = 'randomString';
expect(element.getAttribute('crossorigin')).toBe('anonymous');
});
});
});

0 comments on commit ce22cad

Please sign in to comment.