Multiple improvements
Sonarqube Scanner / Prepare environment (push) Successful in 10s
Sonarqube Scanner / Build and test (push) Successful in 28s
Sonarqube Scanner / SonarQube analysis (push) Successful in 1m8s
Sonarqube Scanner / Deploy to Server (push) Successful in 8s

This commit is contained in:
2026-10-05 01:18:14 +02:00
parent 2b07e9bc47
commit 49a9de0355
27 changed files with 797 additions and 80 deletions
+99
View File
@@ -302,6 +302,13 @@ function buildEditorContext() {
type: file.type || 'application/octet-stream'
}),
get: id => packages.get(String(id)) || null,
getPoiWithMedia: async (id, poiId) => {
const value = packages.get(String(id))?.pois.find(poi => String(poi.id) === String(poiId));
if (!value) return null;
return { ...value, audio: value.audio ? { ...value.audio, url: 'blob:test-audio' } : null,
images: (value.images || []).map(image => ({ ...image, url: 'blob:test-image' })) };
},
releasePoiMedia() {},
getWithMedia: async id => {
const value = packages.get(String(id));
if (!value) return null;
@@ -659,6 +666,7 @@ test('editing an activated server route uses PUT and never writes activation sta
await context.Wegwichtel.EditorUi.open();
const routeList = elements.get('editor-route-list');
await tick();
const serverItem = routeList.children.find(child => child.dataset.routeSource === 'server');
const serverActions = serverItem.children[1];
assert.equal(serverActions.children.length, 1);
@@ -737,3 +745,94 @@ test('local media picker keeps File System Access handles for later upload', asy
assert.equal(imageStore.handle, handle);
assert.equal(imageStore.file, imageFile);
});
test('local drafts can be opened and saved while the server request is still pending', async () => {
const { context, elements, packages } = buildEditorContext();
context.fetch = () => new Promise(() => {});
await loadI18n(context);
vm.runInNewContext(await fs.readFile(path.join(root, 'public/js/editor-ui.js'), 'utf8'), context);
await context.Wegwichtel.EditorUi.open();
const list = elements.get('editor-route-list');
const item = list.children.find(child => child.dataset.routeId === 'local-existing');
assert.ok(item);
list.dispatchEvent(pointerEvent(item.children[1].children[0]));
await tick();
assert.equal(elements.get('editor-route-id').value, 'local-existing');
elements.get('editor-route-name').value = 'Offline geändert';
elements.get('editor-route-form').dispatchEvent(submitEvent());
await tick(); await tick();
assert.equal(packages.get('local-existing').route.name, 'Offline geändert');
assert.equal(elements.get('editor-status').textContent, 'Gespeichert.');
});
test('a failed public route request preserves local drafts and late replies use the latest local data', async () => {
const { context, elements, packages } = buildEditorContext();
const requests = [];
context.fetch = () => new Promise((resolve, reject) => requests.push({ resolve, reject }));
await loadI18n(context);
vm.runInNewContext(await fs.readFile(path.join(root, 'public/js/editor-ui.js'), 'utf8'), context);
await context.Wegwichtel.EditorUi.open();
requests[0].reject(new Error('offline')); await tick();
assert.match(elements.get('editor-status').textContent, /nicht erreichbar/);
assert.ok(elements.get('editor-route-list').children.some(child => child.dataset.routeId === 'local-existing'));
await context.Wegwichtel.EditorUi.refresh();
packages.delete('local-existing');
requests[1].resolve(jsonResponse({ routes: [{ id: 7, name: 'Veröffentlicht' }] }));
await tick(); await tick();
assert.equal(elements.get('editor-route-list').children.some(child => child.dataset.routeId === 'local-existing'), false);
assert.ok(elements.get('editor-route-list').children.some(child => child.dataset.routeSource === 'server'));
});
test('opening and saving a draft does not load files; editing a station loads only that station', async () => {
const { context, elements, packages } = buildEditorContext();
const local = packages.get('local-existing');
local.pois = [0, 1].map(id => ({ id, title: `Station ${id}`, sequence: id, images: [{ id: `image-${id}`, mediaKey: `key-${id}` }] }));
const loads = [];
context.Wegwichtel.LocalRoutes.getWithMedia = () => { throw new Error('Full route hydration must not run'); };
const original = context.Wegwichtel.LocalRoutes.getPoiWithMedia;
context.Wegwichtel.LocalRoutes.getPoiWithMedia = (...args) => { loads.push(args); return original(...args); };
await loadI18n(context);
vm.runInNewContext(await fs.readFile(path.join(root, 'public/js/editor-ui.js'), 'utf8'), context);
await context.Wegwichtel.EditorUi.open();
const list = elements.get('editor-route-list');
const item = list.children.find(child => child.dataset.routeId === 'local-existing');
list.dispatchEvent(pointerEvent(item.children[1].children[0])); await tick();
assert.equal(loads.length, 0);
elements.get('editor-route-name').value = 'Nur Name geändert';
elements.get('editor-route-form').dispatchEvent(submitEvent()); await tick(); await tick();
assert.equal(loads.length, 0);
const poiList = elements.get('editor-poi-list');
const poiItem = poiList.children.find(child => child.dataset.poiId === '1');
poiList.dispatchEvent(pointerEvent(poiItem.children[1].children[2])); await tick();
assert.equal(loads.length, 1);
assert.equal(loads[0][1], 1);
assert.equal(elements.get('editor-poi-media-preview').children.length, 1);
elements.get('editor-poi-title').value = 'Titel geändert';
elements.get('editor-poi-form').dispatchEvent(submitEvent()); await tick(); await tick();
assert.equal(loads.length, 1);
assert.equal(packages.get('local-existing').pois[1].title, 'Titel geändert');
});
test('late station previews are released after the editor closes without replacing unsaved input', async () => {
const { context, elements, packages } = buildEditorContext();
packages.get('local-existing').pois = [{ id: 0, title: 'Station', images: [] }];
let finish;
const released = [];
context.Wegwichtel.LocalRoutes.getPoiWithMedia = () => new Promise(resolve => { finish = resolve; });
context.Wegwichtel.LocalRoutes.releasePoiMedia = poi => { if(poi) released.push(poi); };
await loadI18n(context);
vm.runInNewContext(await fs.readFile(path.join(root, 'public/js/editor-ui.js'), 'utf8'), context);
await context.Wegwichtel.EditorUi.open();
const list = elements.get('editor-route-list');
const item = list.children.find(child => child.dataset.routeId === 'local-existing');
list.dispatchEvent(pointerEvent(item.children[1].children[0])); await tick();
const poiList = elements.get('editor-poi-list');
poiList.dispatchEvent(pointerEvent(poiList.children[0].children[1].children[2])); await tick();
elements.get('editor-poi-title').value = 'Noch nicht gespeichert';
context.Wegwichtel.EditorUi.close();
finish({ id: 0, title: 'Alter Titel', images: [{ url: 'blob:late' }] }); await tick();
assert.equal(released.length, 1);
assert.equal(elements.get('editor-poi-title').value, 'Noch nicht gespeichert');
});