diff --git a/packages/happy-dom/src/nodes/html-media-element/HTMLMediaElement.ts b/packages/happy-dom/src/nodes/html-media-element/HTMLMediaElement.ts
index 214d2b8f..4832ac2f 100644
--- a/packages/happy-dom/src/nodes/html-media-element/HTMLMediaElement.ts
+++ b/packages/happy-dom/src/nodes/html-media-element/HTMLMediaElement.ts
@@ -15,6 +15,8 @@ export default class HTMLMediaElement extends HTMLElement implements IHTMLMediaE
#paused = true;
#duration = NaN;
#currentTime = 0;
+ #playbackRate = 1;
+ #defaultPlaybackRate = 1;
/**
* Returns autoplay.
*
@@ -222,8 +224,62 @@ export default class HTMLMediaElement extends HTMLElement implements IHTMLMediaE
*
* @param currentTime CurrentTime.
*/
- public set currentTime(currentTime: number) {
- this.#currentTime = currentTime;
+ public set currentTime(currentTime: number | string) {
+ const parsedCurrentTime = Number(currentTime);
+ if (isNaN(parsedCurrentTime)) {
+ throw new TypeError(
+ `Failed to set the 'currentTime' property on 'HTMLMediaElement': The provided double value is non-finite.`
+ );
+ }
+ this.#currentTime = parsedCurrentTime;
+ }
+
+ /**
+ * Returns playbackRate.
+ *
+ * @returns playbackRate.
+ */
+ public get playbackRate(): number {
+ return this.#playbackRate;
+ }
+
+ /**
+ * Sets playbackRate.
+ *
+ * @param playbackRate playbackRate.
+ */
+ public set playbackRate(playbackRate: number | string) {
+ const parsedPlaybackRate = Number(playbackRate);
+ if (isNaN(parsedPlaybackRate)) {
+ throw new TypeError(
+ `Failed to set the 'playbackRate' property on 'HTMLMediaElement': The provided double value is non-finite.`
+ );
+ }
+ this.#playbackRate = parsedPlaybackRate;
+ }
+
+ /**
+ * Returns defaultPlaybackRate.
+ *
+ * @returns defaultPlaybackRate.
+ */
+ public get defaultPlaybackRate(): number {
+ return this.#defaultPlaybackRate;
+ }
+
+ /**
+ * Sets defaultPlaybackRate.
+ *
+ * @param defaultPlaybackRate defaultPlaybackRate.
+ */
+ public set defaultPlaybackRate(defaultPlaybackRate: number | string) {
+ const parsedDefaultPlaybackRate = Number(defaultPlaybackRate);
+ if (isNaN(parsedDefaultPlaybackRate)) {
+ throw new TypeError(
+ `Failed to set the 'defaultPlaybackRate' property on 'HTMLMediaElement': The provided double value is non-finite.`
+ );
+ }
+ this.#defaultPlaybackRate = parsedDefaultPlaybackRate;
}
/**
diff --git a/packages/happy-dom/src/nodes/html-media-element/IHTMLMediaElement.ts b/packages/happy-dom/src/nodes/html-media-element/IHTMLMediaElement.ts
index 2c92b52a..48ae30b4 100644
--- a/packages/happy-dom/src/nodes/html-media-element/IHTMLMediaElement.ts
+++ b/packages/happy-dom/src/nodes/html-media-element/IHTMLMediaElement.ts
@@ -17,20 +17,21 @@ export default interface IHTMLMediaElement extends IHTMLElement {
volume: number | string;
src: string;
crossOrigin: string; // Only anonymus and 'use-credentials' is valid
- currentTime: number;
+ currentTime: number | string;
+ playbackRate: number | string;
+ defaultPlaybackRate: number | string;
+
// AddTextTrack;
// Buffered; // TODO tameranges
// CaptureStream; // TODO
// ControlsList: string; // TODO
// DefaultMuted: boolean; // TODO
- // DefaultPlaybackRate; // TODO
// DisableRemotePlayback: boolean; // TODO
// Ended: boolean; // TODO readonly
// Error; // TODO object
// NetworkState; // TODO
// Played: // TODO timeranges
- // 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.
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
index e59f54db..557f1e90 100644
--- a/packages/happy-dom/test/nodes/html-media-element/HTMLMediaElement.test.ts
+++ b/packages/happy-dom/test/nodes/html-media-element/HTMLMediaElement.test.ts
@@ -35,6 +35,12 @@ describe('HTMLMediaElement', () => {
element[property] = true;
expect(element.getAttribute(property)).toBe('');
});
+
+ it('Remove attribute value.', () => {
+ element.setAttribute(property, '');
+ element[property] = false;
+ expect(element.getAttribute(property)).toBeNull();
+ });
});
}
@@ -70,6 +76,14 @@ describe('HTMLMediaElement', () => {
});
});
+ describe('currentSrc', () => {
+ it('Returns the current src', () => {
+ const src = 'https://src'
+ element.src = src;
+ expect(element.currentSrc).toBe(src);
+ })
+ })
+
describe('paused', () => {
it('Default is true', () => {
expect(element.paused).toBeTruthy();
@@ -137,12 +151,14 @@ describe('HTMLMediaElement', () => {
it(`Set ${crossOrigin} as a valid crossOrigin`, () => {
element.crossOrigin = crossOrigin;
expect(element.getAttribute('crossorigin')).toBe(crossOrigin);
+ expect(element.crossOrigin).toBe(crossOrigin);
});
}
it(`Return 'anonymous' if crossOrigin is not valid`, () => {
element.crossOrigin = 'randomString';
expect(element.getAttribute('crossorigin')).toBe('anonymous');
+ expect(element.crossOrigin).toBe('anonymous');
});
});
@@ -160,5 +176,67 @@ describe('HTMLMediaElement', () => {
element.currentTime = 42;
expect(element.currentTime).toBe(42);
});
+ it('Set value as a string', () => {
+ element.currentTime = '42';
+ expect(element.currentTime).toBe(42);
+ });
+
+ it('Throw type error if currentTime is not a number', () => {
+ expect(() => {
+ element.currentTime = 'zeropointfive';
+ }).toThrowError(
+ new TypeError(
+ `Failed to set the 'currentTime' property on 'HTMLMediaElement': The provided double value is non-finite.`
+ )
+ );
+ });
+ });
+
+ describe('playbackRate', () => {
+ it('Return default value', () => {
+ expect(element.playbackRate).toBe(1);
+ });
+ it('Set value', () => {
+ element.playbackRate = 2.3;
+ expect(element.playbackRate).toBe(2.3);
+ });
+ it('Set value as a string', () => {
+ element.playbackRate = '2.3';
+ expect(element.playbackRate).toBe(2.3);
+ });
+
+ it('Throw type error if playbackRate is not a number', () => {
+ expect(() => {
+ element.playbackRate = 'zeropointfive';
+ }).toThrowError(
+ new TypeError(
+ `Failed to set the 'playbackRate' property on 'HTMLMediaElement': The provided double value is non-finite.`
+ )
+ );
+ });
+ });
+
+ describe('defaultPlaybackRate', () => {
+ it('Return default value', () => {
+ expect(element.defaultPlaybackRate).toBe(1);
+ });
+ it('Set value', () => {
+ element.defaultPlaybackRate = 2.3;
+ expect(element.defaultPlaybackRate).toBe(2.3);
+ });
+ it('Set value as a string', () => {
+ element.defaultPlaybackRate = '0.3';
+ expect(element.defaultPlaybackRate).toBe(0.3);
+ });
+
+ it('Throw type error if defaultPlaybackRate is not a number', () => {
+ expect(() => {
+ element.defaultPlaybackRate = 'zeropointfive';
+ }).toThrowError(
+ new TypeError(
+ `Failed to set the 'defaultPlaybackRate' property on 'HTMLMediaElement': The provided double value is non-finite.`
+ )
+ );
+ });
});
});