UNPKG

@haxtheweb/a11y-media-player

Version:

A feature rich, highly accessible video player

584 lines (480 loc) 19 kB
import { fixture, expect, html } from "@open-wc/testing"; import "../a11y-media-player.js"; describe("a11y-media-player test", () => { let element; beforeEach(async () => { element = await fixture( html`<a11y-media-player accent-color="red" youtube-id="BKorP55Aqvg" ></a11y-media-player>`, ); }); it("basic setup", async () => { expect(element).to.exist; expect(element.tagName.toLowerCase()).to.equal("a11y-media-player"); }); it("passes the a11y audit", async () => { await expect(element).shadowDom.to.be.accessible(); }); describe("Property validation with accessibility", () => { let testElement; beforeEach(async () => { testElement = await fixture(html` <a11y-media-player> <video> <source src="test-video.mp4" type="video/mp4" /> <track kind="subtitles" src="test-captions.vtt" srclang="en" label="English" /> </video> </a11y-media-player> `); await testElement.updateComplete; }); describe("Boolean properties", () => { it("should handle audioOnly property", async () => { expect(testElement.audioOnly).to.equal(false); testElement.audioOnly = true; await testElement.updateComplete; expect(testElement.audioOnly).to.equal(true); expect(testElement.hasAttribute("audio-only")).to.be.true; await expect(testElement).shadowDom.to.be.accessible(); }); it("should handle autoplay property", async () => { expect(testElement.autoplay).to.equal(false); testElement.autoplay = true; await testElement.updateComplete; expect(testElement.autoplay).to.equal(true); await expect(testElement).shadowDom.to.be.accessible(); }); it("should handle cc property", async () => { expect(testElement.cc).to.equal(false); testElement.cc = true; await testElement.updateComplete; expect(testElement.cc).to.equal(true); await expect(testElement).shadowDom.to.be.accessible(); }); it("should handle muted property", async () => { expect(testElement.muted).to.equal(false); testElement.muted = true; await testElement.updateComplete; expect(testElement.muted).to.equal(true); await expect(testElement).shadowDom.to.be.accessible(); }); it("should handle loop property", async () => { expect(testElement.loop).to.equal(false); testElement.loop = true; await testElement.updateComplete; expect(testElement.loop).to.equal(true); await expect(testElement).shadowDom.to.be.accessible(); }); it("should handle hideTranscript property", async () => { expect(testElement.hideTranscript).to.equal(false); testElement.hideTranscript = true; await testElement.updateComplete; expect(testElement.hideTranscript).to.equal(true); expect(testElement.hasAttribute("hide-transcript")).to.be.true; await expect(testElement).shadowDom.to.be.accessible(); }); it("should handle standAlone property", async () => { expect(testElement.standAlone).to.equal(false); testElement.standAlone = true; await testElement.updateComplete; expect(testElement.standAlone).to.equal(true); expect(testElement.hasAttribute("stand-alone")).to.be.true; await expect(testElement).shadowDom.to.be.accessible(); }); }); describe("String properties", () => { it("should handle mediaTitle property", async () => { expect(testElement.mediaTitle).to.equal(""); testElement.mediaTitle = "Test Media Title"; await testElement.updateComplete; expect(testElement.mediaTitle).to.equal("Test Media Title"); await expect(testElement).shadowDom.to.be.accessible(); }); it("should handle lang property", async () => { expect(testElement.lang).to.equal("en"); testElement.lang = "es"; await testElement.updateComplete; expect(testElement.lang).to.equal("es"); await expect(testElement).shadowDom.to.be.accessible(); }); it("should handle mediaLang property", async () => { expect(testElement.mediaLang).to.equal("en"); testElement.mediaLang = "fr"; await testElement.updateComplete; expect(testElement.mediaLang).to.equal("fr"); await expect(testElement).shadowDom.to.be.accessible(); }); it("should handle preload property", async () => { expect(testElement.preload).to.equal("metadata"); testElement.preload = "auto"; await testElement.updateComplete; expect(testElement.preload).to.equal("auto"); expect(testElement.hasAttribute("preload")).to.be.true; await expect(testElement).shadowDom.to.be.accessible(); }); }); describe("Number properties", () => { it("should handle volume property", async () => { expect(testElement.volume).to.equal(70); testElement.volume = 50; await testElement.updateComplete; expect(testElement.volume).to.equal(50); await expect(testElement).shadowDom.to.be.accessible(); }); it("should handle playbackRate property", async () => { expect(testElement.playbackRate).to.equal(1); testElement.playbackRate = 1.5; await testElement.updateComplete; expect(testElement.playbackRate).to.equal(1.5); await expect(testElement).shadowDom.to.be.accessible(); }); }); }); describe("Slot functionality", () => { it("should handle default slot with media elements", async () => { const testElement = await fixture(html` <a11y-media-player> <video controls> <source src="test-video.mp4" type="video/mp4" /> </video> </a11y-media-player> `); await testElement.updateComplete; const slot = testElement.shadowRoot.querySelector("slot"); expect(slot).to.exist; const assignedNodes = slot.assignedNodes({ flatten: true }); expect(assignedNodes.length).to.be.greaterThan(0); await expect(testElement).shadowDom.to.be.accessible(); }); }); describe("YouTube functionality", () => { it("should handle YouTube ID property", async () => { const youtubeElement = await fixture(html` <a11y-media-player youtube-id="dQw4w9WgXcQ"></a11y-media-player> `); await youtubeElement.updateComplete; expect(youtubeElement.youtubeId).to.equal("dQw4w9WgXcQ"); expect(youtubeElement.hasAttribute("youtube-id")).to.be.true; expect(youtubeElement.isYoutube).to.be.true; await expect(youtubeElement).shadowDom.to.be.accessible(); }); it("should generate correct poster URL for YouTube", async () => { const youtubeElement = await fixture(html` <a11y-media-player youtube-id="dQw4w9WgXcQ"></a11y-media-player> `); await youtubeElement.updateComplete; expect(youtubeElement.poster).to.include("img.youtube.com"); expect(youtubeElement.poster).to.include("dQw4w9WgXcQ"); }); }); describe("Media controls and interactions", () => { it("should handle play/pause functionality", async () => { const testElement = await fixture(html` <a11y-media-player> <video> <source src="test-video.mp4" type="video/mp4" /> </video> </a11y-media-player> `); await testElement.updateComplete; // Initial state should be paused expect(testElement.__playing).to.equal(false); // Test play button exists const playButton = testElement.shadowRoot.querySelector( "a11y-media-play-button", ); expect(playButton).to.exist; await expect(testElement).shadowDom.to.be.accessible(); }); it("should handle volume controls", async () => { const testElement = await fixture(html` <a11y-media-player volume="80"> <video> <source src="test-video.mp4" type="video/mp4" /> </video> </a11y-media-player> `); await testElement.updateComplete; expect(testElement.volume).to.equal(80); const volumeSlider = testElement.shadowRoot.querySelector("#volume"); expect(volumeSlider).to.exist; await expect(testElement).shadowDom.to.be.accessible(); }); it("should handle fullscreen functionality", async () => { const testElement = await fixture(html` <a11y-media-player> <video> <source src="test-video.mp4" type="video/mp4" /> </video> </a11y-media-player> `); await testElement.updateComplete; expect(testElement.fullscreenButton).to.be.true; // Should have fullscreen capability await expect(testElement).shadowDom.to.be.accessible(); }); }); describe("Responsive behavior", () => { it("should handle responsive size changes", async () => { const testElement = await fixture(html` <a11y-media-player responsive-size="sm"> <video> <source src="test-video.mp4" type="video/mp4" /> </video> </a11y-media-player> `); await testElement.updateComplete; expect(testElement.responsiveSize).to.equal("sm"); expect(testElement.hasAttribute("responsive-size")).to.be.true; testElement.responsiveSize = "xs"; await testElement.updateComplete; expect(testElement.responsiveSize).to.equal("xs"); await expect(testElement).shadowDom.to.be.accessible(); }); it("should handle width and height constraints", async () => { const testElement = await fixture(html` <a11y-media-player width="400" height="300"> <video> <source src="test-video.mp4" type="video/mp4" /> </video> </a11y-media-player> `); await testElement.updateComplete; expect(testElement.width).to.equal("400"); expect(testElement.height).to.equal("300"); await expect(testElement).shadowDom.to.be.accessible(); }); }); describe("Accessibility features", () => { it("should handle audio-only mode accessibility", async () => { const audioElement = await fixture(html` <a11y-media-player audio-only> <audio> <source src="test-audio.mp3" type="audio/mp3" /> </audio> </a11y-media-player> `); await audioElement.updateComplete; expect(audioElement.audioOnly).to.be.true; expect(audioElement.audioNoThumb).to.be.true; // No thumbnail provided await expect(audioElement).shadowDom.to.be.accessible(); }); it("should handle captions and transcript", async () => { const testElement = await fixture(html` <a11y-media-player cc> <video> <source src="test-video.mp4" type="video/mp4" /> <track kind="subtitles" src="test-captions.vtt" srclang="en" label="English" /> </video> </a11y-media-player> `); await testElement.updateComplete; expect(testElement.cc).to.be.true; // Check for transcript section const transcriptSection = testElement.shadowRoot.querySelector( "#transcript-section", ); expect(transcriptSection).to.exist; await expect(testElement).shadowDom.to.be.accessible(); }); it("should handle learning mode restrictions", async () => { const testElement = await fixture(html` <a11y-media-player learning-mode> <video> <source src="test-video.mp4" type="video/mp4" /> </video> </a11y-media-player> `); await testElement.updateComplete; expect(testElement.learningMode).to.be.true; expect(testElement.disableSeek).to.be.true; // Should disable seeking in learning mode expect(testElement.hideTranscript).to.be.true; // Should hide transcript in learning mode await expect(testElement).shadowDom.to.be.accessible(); }); }); describe("Settings and controls", () => { it("should handle settings menu functionality", async () => { const testElement = await fixture(html` <a11y-media-player> <video> <source src="test-video.mp4" type="video/mp4" /> </video> </a11y-media-player> `); await testElement.updateComplete; const settingsButton = testElement.shadowRoot.querySelector("#settings-button"); expect(settingsButton).to.exist; const settingsMenu = testElement.shadowRoot.querySelector("#settings"); expect(settingsMenu).to.exist; await expect(testElement).shadowDom.to.be.accessible(); }); it("should handle sticky mode", async () => { const testElement = await fixture(html` <a11y-media-player sticky sticky-corner="top-right"> <video> <source src="test-video.mp4" type="video/mp4" /> </video> </a11y-media-player> `); await testElement.updateComplete; expect(testElement.sticky).to.be.true; expect(testElement.stickyCorner).to.equal("top-right"); await expect(testElement).shadowDom.to.be.accessible(); }); }); describe("Edge cases and error handling", () => { it("should handle missing media gracefully", async () => { const testElement = await fixture(html` <a11y-media-player></a11y-media-player> `); await testElement.updateComplete; expect(testElement.media).to.be.null; expect(testElement.duration).to.equal(0); await expect(testElement).shadowDom.to.be.accessible(); }); it("should handle unusual property values", async () => { const testElement = await fixture(html` <a11y-media-player></a11y-media-player> `); const unusualValues = [ " \t\n ", // whitespace "🎬 media player 🎬", // emoji "Very long media title that might cause display issues or layout problems", "Multi\nline\ntitle", // multiline "Title with 'quotes' and \"double quotes\" and special chars: !@#$%^&*()", ]; for (const value of unusualValues) { testElement.mediaTitle = value; testElement.mediaLang = value; await testElement.updateComplete; expect(testElement.mediaTitle).to.equal(value); expect(testElement.mediaLang).to.equal(value); await expect(testElement).shadowDom.to.be.accessible(); } }); it("should handle extreme volume values", async () => { const testElement = await fixture(html` <a11y-media-player></a11y-media-player> `); const extremeValues = [0, 50, 100, -10, 150]; for (const value of extremeValues) { testElement.volume = value; await testElement.updateComplete; expect(testElement.volume).to.equal(value); await expect(testElement).shadowDom.to.be.accessible(); } }); it("should handle extreme playback rates", async () => { const testElement = await fixture(html` <a11y-media-player></a11y-media-player> `); const rateValues = [0.25, 0.5, 1, 1.5, 2, 2.5]; for (const rate of rateValues) { testElement.playbackRate = rate; await testElement.updateComplete; expect(testElement.playbackRate).to.equal(rate); await expect(testElement).shadowDom.to.be.accessible(); } }); }); describe("Computed properties", () => { it("should compute aspect ratio correctly", async () => { const testElement = await fixture(html` <a11y-media-player></a11y-media-player> `); await testElement.updateComplete; expect(testElement.aspect).to.equal(16 / 9); // Default aspect ratio }); it("should compute media caption correctly", async () => { const testElement = await fixture(html` <a11y-media-player media-title="Test Video"></a11y-media-player> `); await testElement.updateComplete; expect(testElement.mediaCaption).to.equal("Test Video"); testElement.audioOnly = true; await testElement.updateComplete; expect(testElement.mediaCaption).to.include("Audio"); }); it("should compute print caption correctly", async () => { const testElement = await fixture(html` <a11y-media-player media-title="Test Video"></a11y-media-player> `); await testElement.updateComplete; expect(testElement.printCaption).to.include("Test Video"); expect(testElement.printCaption).to.include("Video"); }); it("should compute flex layout correctly", async () => { const testElement = await fixture(html` <a11y-media-player></a11y-media-player> `); await testElement.updateComplete; // Without captions, should not be in flex layout expect(testElement.flexLayout).to.be.false; }); }); }); /* describe("A11y/chai axe tests", () => { it("a11y-media-player passes accessibility test", async () => { const el = await fixture(html` <a11y-media-player></a11y-media-player> `); await expect(el).to.be.accessible(); }); it("a11y-media-player passes accessibility negation", async () => { const el = await fixture( html`<a11y-media-player aria-labelledby="a11y-media-player" ></a11y-media-player>` ); await assert.isNotAccessible(el); }); }); /* // Custom properties test describe("Custom Property Test", () => { it("a11y-media-player can instantiate a element with custom properties", async () => { const el = await fixture(html`<a11y-media-player .foo=${'bar'}></a11y-media-player>`); expect(el.foo).to.equal('bar'); }) }) */ /* // Test if element is mobile responsive describe('Test Mobile Responsiveness', () => { before(async () => {z await setViewport({width: 375, height: 750}); }) it('sizes down to 360px', async () => { const el = await fixture(html`<a11y-media-player ></a11y-media-player>`); const width = getComputedStyle(el).width; expect(width).to.equal('360px'); }) }) */ /* // Test if element sizes up for desktop behavior describe('Test Desktop Responsiveness', () => { before(async () => { await setViewport({width: 1000, height: 1000}); }) it('sizes up to 410px', async () => { const el = await fixture(html`<a11y-media-player></a11y-media-player>`); const width = getComputedStyle(el).width; expect(width).to.equal('410px'); }) it('hides mobile menu', async () => { const el await fixture(html`<a11y-media-player></a11y-media-player>`); const hidden = el.getAttribute('hidden'); expect(hidden).to.equal(true); }) }) */