remove /media endpoint

This commit is contained in:
Florian Zumpe
2026-06-17 00:10:46 +02:00
parent c98f304ffa
commit 833b5ad3a4
12 changed files with 443 additions and 365 deletions
+34 -24
View File
@@ -26,11 +26,11 @@ async function requestJson(url, options = {}, expectedStatus = 200) {
return { response, body };
}
async function requestBytes(url, expectedStatus = 200) {
async function requestBuffer(url, expectedStatus = 200) {
const response = await fetch(url);
const bytes = Buffer.from(await response.arrayBuffer());
assert.equal(response.status, expectedStatus, bytes.toString());
return { response, bytes };
const body = Buffer.from(await response.arrayBuffer());
assert.equal(response.status, expectedStatus);
return { response, body };
}
async function waitForServer(baseUrl, child, output) {
@@ -47,7 +47,7 @@ async function waitForServer(baseUrl, child, output) {
throw new Error(`Serverstart hat das Zeitlimit überschritten.\n${output.join('')}`);
}
test('pictures and per-POI audio are delivered and managed through REST API resources', { timeout: 30000 }, async t => {
test('pictures and audio are managed as individual REST resources', { timeout: 30000 }, async t => {
const runtime = await fs.mkdtemp(path.join(os.tmpdir(), 'wegwichtel-media-api-'));
const port = await freePort();
const baseUrl = `http://127.0.0.1:${port}`;
@@ -84,6 +84,10 @@ test('pictures and per-POI audio are delivered and managed through REST API reso
method: 'POST',
body: routeForm
}, 201);
assert.equal(route.gpxUrl, `/api/routes/${route.id}/gpx`);
const { response: gpxResponse, body: downloadedGpx } = await requestBuffer(`${baseUrl}${route.gpxUrl}`);
assert.match(gpxResponse.headers.get('content-type') || '', /application\/gpx\+xml/);
assert.deepEqual(downloadedGpx, gpx);
const { body: poi } = await requestJson(`${baseUrl}/api/routes/${route.id}/pois`, {
method: 'POST',
@@ -111,17 +115,16 @@ test('pictures and per-POI audio are delivered and managed through REST API reso
assert.equal(pictureResponse.headers.get('location'), `/api/routes/${route.id}/pictures/${picture.id}`);
assert.equal(picture.poiId, poi.id);
assert.equal(picture.caption, 'Erste Bildbeschreibung');
assert.equal(picture.url, `/api/routes/${route.id}/pictures/${picture.id}`);
const { response: pictureFileResponse, body: pictureFile } = await requestBuffer(`${baseUrl}${picture.url}`);
assert.match(pictureFileResponse.headers.get('content-type') || '', /image\/png/);
assert.equal(pictureFile.toString(), 'picture-one');
const { body: pictureMetadata } = await requestJson(`${baseUrl}${picture.url}?metadata=true`);
assert.equal(pictureMetadata.caption, 'Erste Bildbeschreibung');
const { body: pictureList } = await requestJson(`${baseUrl}/api/routes/${route.id}/pictures?poiId=${poi.id}`);
assert.equal(pictureList.pictures.length, 1);
assert.equal(pictureList.pictures[0].id, picture.id);
assert.equal(pictureList.pictures[0].url, `/api/routes/${route.id}/pictures/${picture.id}`);
const { response: pictureContentResponse, bytes: pictureBytes } = await requestBytes(
`${baseUrl}/api/routes/${route.id}/pictures/${picture.id}`
);
assert.equal(pictureContentResponse.headers.get('content-type'), 'image/png');
assert.equal(pictureBytes.toString(), 'picture-one');
const { body: updatedPicture } = await requestJson(
`${baseUrl}/api/routes/${route.id}/pictures/${picture.id}`,
@@ -142,8 +145,14 @@ test('pictures and per-POI audio are delivered and managed through REST API reso
{ method: 'POST', body: audioForm },
201
);
assert.equal(audioResponse.headers.get('location'), `/api/routes/${route.id}/audio?poiId=${poi.id}`);
assert.equal(audioResponse.headers.get('location'), `/api/routes/${route.id}/audio/${poi.id}`);
assert.equal(audio.poiId, poi.id);
assert.equal(audio.url, `/api/routes/${route.id}/audio/${poi.id}`);
const { response: audioFileResponse, body: audioFile } = await requestBuffer(`${baseUrl}${audio.url}`);
assert.match(audioFileResponse.headers.get('content-type') || '', /audio\/mpeg/);
assert.equal(audioFile.toString(), 'audio-one');
const { body: audioMetadata } = await requestJson(`${baseUrl}${audio.url}?metadata=true`);
assert.equal(audioMetadata.poiId, poi.id);
const duplicateAudio = new FormData();
duplicateAudio.append('poiId', String(poi.id));
@@ -156,24 +165,25 @@ test('pictures and per-POI audio are delivered and managed through REST API reso
const replacementAudio = new FormData();
replacementAudio.append('audio', new Blob(['audio-two'], { type: 'audio/ogg' }), 'ansage-neu.ogg');
const { body: replacedAudio } = await requestJson(
`${baseUrl}/api/routes/${route.id}/audio?poiId=${poi.id}`,
`${baseUrl}/api/routes/${route.id}/audio/${poi.id}`,
{ method: 'PUT', body: replacementAudio }
);
assert.equal(replacedAudio.url, `/api/routes/${route.id}/audio?poiId=${poi.id}`);
assert.equal(replacedAudio.url, `/api/routes/${route.id}/audio/${poi.id}`);
const { response: replacedAudioResponse, body: replacedAudioFile } = await requestBuffer(`${baseUrl}${replacedAudio.url}`);
assert.match(replacedAudioResponse.headers.get('content-type') || '', /audio\/ogg/);
assert.equal(replacedAudioFile.toString(), 'audio-two');
const { body: routeWithMedia } = await requestJson(`${baseUrl}/api/routes/${route.id}`);
assert.equal(routeWithMedia.pois[0].images[0].caption, 'Aktualisierte Bildbeschreibung');
assert.equal(routeWithMedia.gpxUrl, `/api/routes/${route.id}/gpx`);
assert.equal(routeWithMedia.pois[0].audioUrl, `/api/routes/${route.id}/audio/${poi.id}`);
assert.equal(routeWithMedia.pois[0].images[0].url, `/api/routes/${route.id}/pictures/${picture.id}`);
assert.equal(routeWithMedia.pois[0].audioUrl, `/api/routes/${route.id}/audio?poiId=${poi.id}`);
const { response: audioContentResponse, bytes: audioBytes } = await requestBytes(
`${baseUrl}/api/routes/${route.id}/audio?poiId=${poi.id}`
);
assert.equal(audioContentResponse.headers.get('content-type'), 'audio/ogg');
assert.equal(audioBytes.toString(), 'audio-two');
assert.doesNotMatch(JSON.stringify(routeWithMedia), /\/media\//);
const legacyMediaResponse = await fetch(`${baseUrl}/media/routes/${route.id}/route.gpx`);
assert.equal(legacyMediaResponse.status, 404);
const { body: deletedAudio } = await requestJson(
`${baseUrl}/api/routes/${route.id}/audio?poiId=${poi.id}`,
`${baseUrl}/api/routes/${route.id}/audio/${poi.id}`,
{ method: 'DELETE' }
);
assert.equal(deletedAudio.deleted, true);
@@ -185,5 +195,5 @@ test('pictures and per-POI audio are delivered and managed through REST API reso
assert.equal(deletedPicture.deleted, true);
await requestJson(`${baseUrl}/api/routes/${route.id}/pictures/${picture.id}`, {}, 404);
await requestJson(`${baseUrl}/api/routes/${route.id}/audio?poiId=${poi.id}`, {}, 404);
await requestJson(`${baseUrl}/api/routes/${route.id}/audio/${poi.id}`, {}, 404);
});