disable cachebuster to show local media
Sonarqube Scanner / Build and analyze (push) Successful in 1m13s
Sonarqube Scanner / Build and analyze (push) Successful in 1m13s
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
|
||||
function mediaUrl(url) {
|
||||
if (!url) return '';
|
||||
if (url.startsWith('data:') || url.startsWith('blob:')) return url;
|
||||
const separator = url.includes('?') ? '&' : '?';
|
||||
return `${url}${separator}v=${Date.now()}`;
|
||||
}
|
||||
@@ -23,7 +24,6 @@
|
||||
load(url) {
|
||||
unload();
|
||||
if (!url) return;
|
||||
|
||||
const audio = element();
|
||||
audio.src = mediaUrl(url);
|
||||
$(audio).removeAttr('hidden').css('display', 'block');
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
function mediaUrl(url) {
|
||||
if (!url) return '';
|
||||
if (url.startsWith('data:') || url.startsWith('blob:')) return url;
|
||||
const separator = url.includes('?') ? '&' : '?';
|
||||
return `${url}${separator}v=${Date.now()}`;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
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+$/);
|
||||
});
|
||||
Reference in New Issue
Block a user