129 lines
4.3 KiB
JavaScript
129 lines
4.3 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import fs from 'node:fs/promises';
|
|
import path from 'node:path';
|
|
import test from 'node:test';
|
|
import vm from 'node:vm';
|
|
|
|
const root = path.resolve(import.meta.dirname, '..');
|
|
|
|
function createHarness() {
|
|
const document = {};
|
|
const elements = new Map();
|
|
|
|
function makeElement(id) {
|
|
if (elements.has(id)) return elements.get(id);
|
|
const element = {
|
|
id,
|
|
attrs: {},
|
|
css: {},
|
|
hidden: false,
|
|
textValue: '',
|
|
toggled: null,
|
|
paused: false,
|
|
loadCount: 0,
|
|
pause() { this.paused = true; },
|
|
load() { this.loadCount += 1; },
|
|
play() { return Promise.resolve(); },
|
|
removeAttribute(name) {
|
|
delete this.attrs[name];
|
|
if (name === 'src') delete this.src;
|
|
},
|
|
getAttribute(name) {
|
|
if (name === 'src') return this.src ?? this.attrs.src ?? null;
|
|
return this.attrs[name] ?? null;
|
|
}
|
|
};
|
|
elements.set(id, element);
|
|
return element;
|
|
}
|
|
|
|
class Wrapper {
|
|
constructor(target) {
|
|
this.target = target;
|
|
this[0] = target;
|
|
this.length = target ? 1 : 0;
|
|
}
|
|
|
|
on() { return this; }
|
|
off() { return this; }
|
|
button() { return this; }
|
|
hide() { if (this.target) this.target.hidden = true; return this; }
|
|
removeAttr(name) {
|
|
this.target?.removeAttribute?.(name);
|
|
if (this.target && name === 'hidden') this.target.hidden = false;
|
|
return this;
|
|
}
|
|
attr(name, value) {
|
|
if (!this.target) return this;
|
|
if (value === undefined) return this.target.attrs?.[name];
|
|
this.target.attrs[name] = String(value);
|
|
if (name === 'src') this.target.src = String(value);
|
|
if (name === 'hidden') this.target.hidden = true;
|
|
return this;
|
|
}
|
|
css(name, value) { if (this.target) this.target.css[name] = value; return this; }
|
|
toggle(value) { if (this.target) this.target.toggled = Boolean(value); return this; }
|
|
text(value) { if (this.target) this.target.textValue = String(value); return this; }
|
|
prop(name, value) { if (this.target) this.target[name] = value; return this; }
|
|
hasClass() { return false; }
|
|
closest() { return { length: 0 }; }
|
|
}
|
|
|
|
function jquery(target) {
|
|
if (target === document) return new Wrapper(document);
|
|
if (typeof target === 'string' && target.startsWith('#')) return new Wrapper(makeElement(target.slice(1)));
|
|
return new Wrapper(target);
|
|
}
|
|
|
|
const context = {
|
|
Date,
|
|
Math,
|
|
Promise,
|
|
document,
|
|
globalThis: null,
|
|
jQuery: jquery,
|
|
Wegwichtel: {}
|
|
};
|
|
context.globalThis = context;
|
|
return { context, elements };
|
|
}
|
|
|
|
async function loadModule(relativePath, harness) {
|
|
const sourcePath = path.join(root, relativePath);
|
|
const source = await fs.readFile(sourcePath, 'utf8');
|
|
vm.runInNewContext(source, harness.context, { filename: sourcePath });
|
|
}
|
|
|
|
test('audio player preserves local data/blob URLs and cache-busts server URLs', async () => {
|
|
const harness = createHarness();
|
|
await loadModule('public/js/audio-player.js', harness);
|
|
|
|
const dataUrl = 'data:audio/mpeg;base64,QUJDRA==';
|
|
harness.context.Wegwichtel.AudioPlayer.load(dataUrl);
|
|
assert.equal(harness.elements.get('poi-audio').src, dataUrl);
|
|
|
|
const blobUrl = 'blob:https://wegwichtel.de/1234';
|
|
harness.context.Wegwichtel.AudioPlayer.load(blobUrl);
|
|
assert.equal(harness.elements.get('poi-audio').src, blobUrl);
|
|
|
|
harness.context.Wegwichtel.AudioPlayer.load('/api/routes/1/pois/2/audio');
|
|
assert.match(harness.elements.get('poi-audio').src, /^\/api\/routes\/1\/pois\/2\/audio\?v=\d+$/);
|
|
});
|
|
|
|
test('slideshow preserves local data/blob URLs and cache-busts server URLs', async () => {
|
|
const harness = createHarness();
|
|
await loadModule('public/js/slideshow.js', harness);
|
|
|
|
const dataUrl = 'data:image/jpeg;base64,QUJDRA==';
|
|
harness.context.Wegwichtel.Slideshow.show([{ url: dataUrl, caption: 'Lokal' }]);
|
|
assert.equal(harness.elements.get('slide-image').src, dataUrl);
|
|
assert.equal(harness.elements.get('slideshow').toggled, true);
|
|
|
|
const blobUrl = 'blob:https://wegwichtel.de/5678';
|
|
harness.context.Wegwichtel.Slideshow.show([{ url: blobUrl }]);
|
|
assert.equal(harness.elements.get('slide-image').src, blobUrl);
|
|
|
|
harness.context.Wegwichtel.Slideshow.show([{ url: '/api/routes/1/pois/2/pictures/3' }]);
|
|
assert.match(harness.elements.get('slide-image').src, /^\/api\/routes\/1\/pois\/2\/pictures\/3\?v=\d+$/);
|
|
});
|