1
0
Files
VR-Web-Player/tests/media-adapter.test.mjs
Aiden 857c9ac980
All checks were successful
Test / test (push) Successful in 9m32s
carosel images
2026-06-10 15:12:25 +10:00

303 lines
8.5 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import {
createMediaAdapter,
ImageCarouselMediaAdapter,
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,
listeners: {},
naturalWidth,
src: source,
style: { display: '' },
tagName: 'IMG',
addEventListener(type, listener) {
this.listeners[type] ??= [];
this.listeners[type].push(listener);
},
dispatch(type) {
for (const listener of this.listeners[type] ?? []) {
listener({ currentTarget: this });
}
},
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,
carousel: false,
dynamicTexture: true,
navigation: 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,
carousel: false,
dynamicTexture: false,
navigation: 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('ImageCarouselMediaAdapter exposes carousel image navigation', () => {
const firstImage = createImage({ title: 'First image', source: 'https://cdn.example.com/media/first.png' });
const secondImage = createImage({ title: 'Second image', source: 'https://cdn.example.com/media/second.png' });
const adapter = new ImageCarouselMediaAdapter([firstImage, secondImage]);
assert.deepEqual(adapter.capabilities, {
audio: false,
carousel: true,
dynamicTexture: false,
navigation: true,
playback: false,
timeline: false
});
assert.equal(adapter.element, firstImage);
assert.equal(adapter.textureSource, firstImage);
assert.equal(adapter.getTitle(), 'First image');
assert.equal(firstImage.style.display, '');
assert.equal(secondImage.style.display, 'none');
assert.deepEqual(firstImage.classList.values, ['vrwp-media', 'vrwp-image', 'vrwp-carousel-image']);
assert.deepEqual(secondImage.classList.values, ['vrwp-media', 'vrwp-image', 'vrwp-carousel-image']);
assert.equal(adapter.next(), true);
assert.equal(adapter.element, secondImage);
assert.equal(adapter.textureSource, secondImage);
assert.equal(adapter.getTitle(), 'Second image');
assert.equal(firstImage.style.display, 'none');
assert.equal(secondImage.style.display, '');
assert.equal(adapter.next(), true);
assert.equal(adapter.element, firstImage);
adapter.hideElement();
assert.equal(firstImage.style.display, 'none');
assert.equal(secondImage.style.display, 'none');
adapter.previous();
adapter.showElement();
assert.equal(adapter.element, secondImage);
assert.equal(firstImage.style.display, 'none');
assert.equal(secondImage.style.display, '');
adapter.load();
assert.equal(firstImage.loading, 'eager');
assert.equal(secondImage.loading, 'eager');
});
test('ImageCarouselMediaAdapter waits for all images before reporting ready', async () => {
const firstImage = createImage({ complete: false, naturalWidth: 0 });
const secondImage = createImage({ complete: false, naturalWidth: 0 });
const adapter = new ImageCarouselMediaAdapter([firstImage, secondImage]);
let readyCount = 0;
adapter.bindLoadState({
onError: () => {},
onReady: () => {
readyCount += 1;
}
});
await new Promise((resolve) => setImmediate(resolve));
assert.equal(readyCount, 0);
firstImage.complete = true;
firstImage.naturalWidth = 1920;
firstImage.dispatch('load');
assert.equal(readyCount, 0);
secondImage.complete = true;
secondImage.naturalWidth = 1920;
secondImage.dispatch('load');
assert.equal(readyCount, 1);
firstImage.dispatch('load');
assert.equal(readyCount, 1);
});
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 creates an image carousel when requested', () => {
const firstImage = createImage({ title: 'First image' });
const secondImage = createImage({ title: 'Second image' });
const playerContainer = {
dataset: { carousel: '' },
querySelectorAll(selector) {
return selector === 'video,img' ? [firstImage, secondImage] : [];
}
};
const adapter = createMediaAdapter(playerContainer);
assert.ok(adapter instanceof ImageCarouselMediaAdapter);
assert.equal(adapter.element, firstImage);
assert.equal(adapter.next(), true);
assert.equal(adapter.element, secondImage);
});
test('createMediaAdapter refuses missing or ambiguous media elements', () => {
const video = createVideo();
const image = createImage();
const secondImage = createImage();
assert.equal(createMediaAdapter({ querySelectorAll: () => [] }), null);
assert.equal(createMediaAdapter({ querySelectorAll: () => [video, image] }), null);
assert.equal(createMediaAdapter({ querySelectorAll: () => [image, secondImage] }), null);
assert.equal(createMediaAdapter({ dataset: { carousel: '' }, querySelectorAll: () => [image] }), null);
assert.equal(createMediaAdapter({ dataset: { carousel: '' }, querySelectorAll: () => [video, image] }), null);
});