import test from 'node:test'; import assert from 'node:assert/strict'; import { createMediaAdapter, ImageMediaAdapter, VideoMediaAdapter } from '../vr180player/media/media-adapter.js'; function createClassList() { return { values: [], add(...values) { this.values.push(...values); } }; } function createVideo({ ended = false, paused = false, source = 'https://cdn.example.com/videos/demo-video.mp4', title = '' } = {}) { return { HAVE_METADATA: 1, classList: createClassList(), ended, loadCount: 0, paused, readyState: 0, style: { display: '' }, tagName: 'VIDEO', addEventListener() {}, getAttribute(name) { return name === 'title' ? title : ''; }, load() { this.loadCount += 1; }, querySelector(selector) { if (selector !== 'source' || !source) { return null; } return { src: source }; } }; } function createImage({ alt = '', complete = true, naturalWidth = 1920, source = 'https://cdn.example.com/images/demo-image.png', title = '' } = {}) { return { alt, classList: createClassList(), complete, currentSrc: source, naturalWidth, src: source, style: { display: '' }, tagName: 'IMG', addEventListener() {}, getAttribute(name) { if (name === 'title') return title; if (name === 'alt') return alt; return ''; } }; } test('VideoMediaAdapter exposes video capabilities and lifecycle helpers', () => { const video = createVideo({ title: 'Demo Title' }); const adapter = new VideoMediaAdapter(video); assert.deepEqual(adapter.capabilities, { audio: true, dynamicTexture: true, playback: true, timeline: true }); assert.equal(adapter.element, video); assert.equal(adapter.textureSource, video); assert.equal(adapter.getTitle(), 'Demo Title'); adapter.hideElement(); assert.equal(video.style.display, 'none'); adapter.showElement(); assert.equal(video.style.display, ''); adapter.load(); assert.equal(video.loadCount, 1); }); test('VideoMediaAdapter falls back to source filename and tracks texture update state', () => { const video = createVideo({ source: 'https://cdn.example.com/media/flat-sbs-demo.mp4' }); const adapter = new VideoMediaAdapter(video); assert.equal(adapter.getTitle(), 'flat sbs demo'); assert.equal(adapter.shouldUpdateTexture(), true); video.paused = true; assert.equal(adapter.shouldUpdateTexture(), false); video.paused = false; video.ended = true; assert.equal(adapter.shouldUpdateTexture(), false); }); test('ImageMediaAdapter exposes static image capabilities and lifecycle helpers', async () => { const image = createImage({ alt: 'Alt Title' }); const adapter = new ImageMediaAdapter(image); let readyCount = 0; adapter.bindLoadState({ onError: () => {}, onReady: () => { readyCount += 1; } }); await new Promise((resolve) => setImmediate(resolve)); assert.deepEqual(adapter.capabilities, { audio: false, dynamicTexture: false, playback: false, timeline: false }); assert.equal(adapter.element, image); assert.equal(adapter.textureSource, image); assert.equal(adapter.getTitle(), 'Alt Title'); assert.equal(adapter.shouldUpdateTexture(), false); assert.equal(readyCount, 1); adapter.hideElement(); assert.equal(image.style.display, 'none'); adapter.showElement(); assert.equal(image.style.display, ''); }); test('ImageMediaAdapter falls back to source filename', () => { const image = createImage({ alt: '', source: 'https://cdn.example.com/media/static-sbs-demo.png' }); const adapter = new ImageMediaAdapter(image); assert.equal(adapter.getTitle(), 'static sbs demo'); }); test('createMediaAdapter finds and marks the supported video element', () => { const video = createVideo(); const playerContainer = { querySelectorAll(selector) { return selector === 'video,img' ? [video] : []; } }; const adapter = createMediaAdapter(playerContainer); assert.ok(adapter instanceof VideoMediaAdapter); assert.equal(adapter.element, video); assert.deepEqual(video.classList.values, ['vrwp-media', 'vrwp-video']); }); test('createMediaAdapter finds and marks the supported image element', () => { const image = createImage(); const playerContainer = { querySelectorAll(selector) { return selector === 'video,img' ? [image] : []; } }; const adapter = createMediaAdapter(playerContainer); assert.ok(adapter instanceof ImageMediaAdapter); assert.equal(adapter.element, image); assert.deepEqual(image.classList.values, ['vrwp-media', 'vrwp-image']); }); test('createMediaAdapter refuses missing or ambiguous media elements', () => { const video = createVideo(); const image = createImage(); assert.equal(createMediaAdapter({ querySelectorAll: () => [] }), null); assert.equal(createMediaAdapter({ querySelectorAll: () => [video, image] }), null); });