waypoint management fix
Sonarqube Scanner / Build and analyze (push) Failing after 58s

This commit is contained in:
Florian Zumpe
2026-09-27 22:32:54 +02:00
parent b37712a2e3
commit 13538f6ca9
2 changed files with 68 additions and 8 deletions
+28 -5
View File
@@ -126,6 +126,26 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
return text(poi?.id ?? poi?.poiId);
}
function numericPoiId(value) {
const raw = text(value).trim();
if (!raw) return null;
const parsed = Number(raw);
return Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : null;
}
function nextLocalPoiId() {
let highest = -1;
for (const poi of state.pois) {
const identifier = numericPoiId(poi?.id ?? poi?.poiId);
if (identifier != null && identifier > highest) highest = identifier;
}
const next = highest + 1;
if (!Number.isSafeInteger(next)) {
throw new Error('Für diese lokale Strecke kann keine weitere Streckenpunkt-ID vergeben werden.');
}
return next;
}
function routeName(route) {
return text(route?.name || route?.title || 'Unbenannte Strecke');
}
@@ -479,7 +499,7 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
byId(ids.routeName).value = routeName(route) === 'Unbenannte Strecke' ? '' : routeName(route);
byId(ids.routeDescription).value = text(route?.description);
byId(ids.routeGpx).value = '';
setHidden(byId(ids.routeGpxGroup), !routeId(route));
setHidden(byId(ids.routeGpxGroup), state.currentSource !== 'server');
const uploadButton = byId(ids.routeUpload);
if (state.currentSource === 'local') {
@@ -983,7 +1003,9 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
const accuracy = Number(position?.accuracy);
state.currentPoi = null;
const identifier = state.currentSource === 'local' ? nextLocalPoiId() : null;
fillPoiForm({
...(identifier == null ? {} : { id: identifier }),
lat,
lon,
triggerRadiusM: Number.isFinite(accuracy) && accuracy > 0 ? accuracy : 25
@@ -1062,9 +1084,10 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
if (!Number.isFinite(values.lat) || !Number.isFinite(values.lon)) {
throw new TypeError('Für einen Streckenpunkt sind gültige Breiten- und Längengrade erforderlich.');
}
const currentId = Number(byId(ids.poiId).value);
const identifier = Number.isSafeInteger(currentId) ? currentId : ns.LocalRoutes.createPoiId();
const existing = state.pois.find(poi => Number(poi.id) === identifier) || state.currentPoi;
const currentId = numericPoiId(byId(ids.poiId).value);
const identifier = currentId ?? nextLocalPoiId();
byId(ids.poiId).value = String(identifier);
const existing = state.pois.find(poi => numericPoiId(poi?.id ?? poi?.poiId) === identifier) || state.currentPoi;
const media = await mediaFromLocalForm(existing, identifier);
const savedPoi = {
...existing,
@@ -1074,7 +1097,7 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
id: identifier,
sequence: existing?.sequence ?? state.pois.length
};
const index = state.pois.findIndex(poi => Number(poi.id) === identifier);
const index = state.pois.findIndex(poi => numericPoiId(poi?.id ?? poi?.poiId) === identifier);
if (index >= 0) state.pois[index] = savedPoi;
else state.pois.push(savedPoi);
+40 -3
View File
@@ -78,7 +78,7 @@ test('editor markup and source describe local draft creation instead of immediat
assert.match(ui, /sendForm\('\/routes',\s*'POST'/);
assert.match(ui, /serverRouteId/);
assert.match(ui, /position\?\.accuracy/);
assert.match(ui, /setHidden\(byId\(ids\.routeGpxGroup\), !routeId\(route\)\)/);
assert.match(ui, /setHidden\(byId\(ids\.routeGpxGroup\), state\.currentSource !== 'server'\)/);
});
class FakeElement extends EventTarget {
@@ -386,7 +386,7 @@ test('public editor workflow saves new route and GPX Streckenpunkt locally witho
assert.equal(elements.get('editor-status').textContent, 'Speichern erfolgreich.');
assert.equal(elements.get('editor-route-upload').hidden, false);
assert.equal(elements.get('editor-route-upload').disabled, false);
assert.equal(elements.get('editor-route-gpx-group').hidden, false);
assert.equal(elements.get('editor-route-gpx-group').hidden, true);
elements.get('editor-add-poi').dispatchEvent(pointerEvent());
assert.equal(elements.get('editor-poi-audio').clickCount, 0);
@@ -399,7 +399,7 @@ test('public editor workflow saves new route and GPX Streckenpunkt locally witho
assert.equal(elements.get('editor-poi-lon').value, '10.987654321');
assert.equal(elements.get('editor-poi-radius').value, '4.321');
elements.get('editor-poi-title').value = 'Aussicht';
elements.get('editor-poi-description').value = 'Text zur Station';
elements.get('editor-poi-description').value = 'Text zum Streckenpunkt';
elements.get('editor-poi-audio').files = [{ name: 'aussicht.mp3', size: 5, type: 'audio/mpeg' }];
elements.get('editor-poi-audio').dispatchEvent(new Event('change'));
elements.get('editor-poi-images').files = [{ name: 'aussicht.jpg', size: 7, type: 'image/jpeg' }];
@@ -488,6 +488,42 @@ test('public editor workflow saves new route and GPX Streckenpunkt locally witho
assert.equal(elements.get('editor-button').attributes.get('aria-expanded'), 'false');
});
test('local Streckenpunkt ids start at zero and increment from the highest existing id', async () => {
const sourcePath = path.join(root, 'public/js/editor-ui.js');
const source = await fs.readFile(sourcePath, 'utf8');
const { context, elements, packages } = buildEditorContext();
vm.runInNewContext(source, context, { filename: sourcePath });
await context.Wegwichtel.EditorUi.openNewLocalRoute();
elements.get('editor-route-name').value = 'ID-Test';
elements.get('editor-route-form').dispatchEvent(submitEvent());
await tick();
await tick();
elements.get('editor-add-poi').dispatchEvent(pointerEvent());
assert.equal(elements.get('editor-poi-id').value, '0');
elements.get('editor-poi-title').value = 'Erster Streckenpunkt';
elements.get('editor-poi-form').dispatchEvent(submitEvent());
await tick();
await tick();
elements.get('editor-add-poi').dispatchEvent(pointerEvent());
assert.equal(elements.get('editor-poi-id').value, '1');
elements.get('editor-poi-title').value = 'Zweiter Streckenpunkt';
elements.get('editor-poi-form').dispatchEvent(submitEvent());
await tick();
await tick();
const saved = packages.get('local-new');
assert.equal(saved.pois.length, 2);
assert.deepEqual(Array.from(saved.pois, poi => poi.id), [0, 1]);
assert.deepEqual(Array.from(saved.pois, poi => poi.title), ['Erster Streckenpunkt', 'Zweiter Streckenpunkt']);
const pointItems = elements.get('editor-poi-list').children.filter(child => child.dataset.poiId);
assert.equal(pointItems.length, 2);
});
test('route and Streckenpunkt list expose red delete actions and remove local data', async () => {
const sourcePath = path.join(root, 'public/js/editor-ui.js');
const source = await fs.readFile(sourcePath, 'utf8');
@@ -560,6 +596,7 @@ test('editing an activated server route uses PUT and never writes activation sta
await tick();
assert.equal(elements.get('editor-route-id').value, '1');
assert.equal(elements.get('editor-route-gpx-group').hidden, false);
assert.match(elements.get('editor-route-activated').textContent, /Veröffentlicht am/);
assert.equal(elements.get('editor-route-upload').hidden, true);