import { describe, expect, it } from
"vitest" ;
import { splitMediaFromOutput } from
"./parse.js" ;
describe(
"splitMediaFromOutput" , () => {
function expectParsedMediaOutputCase(
input: string,
expected: {
mediaUrls?: string[];
text?: string;
audioAsVoice?:
boolean ;
},
) {
const result = splitMediaFromOutput(input);
expect(result.text).toBe(expected.text ??
"" );
if (
"audioAsVoice" in expected) {
expect(result.audioAsVoice).toBe(expected.audioAsVoice);
}
else {
expect(result.audioAsVoice).toBeUndefined();
}
if (
"mediaUrls" in expected) {
expect(result.mediaUrls).toEqual(expected.mediaUrls);
expect(result.mediaUrl).toBe(expected.mediaUrls?.[
0 ]);
}
else {
expect(result.mediaUrls).toBeUndefined();
expect(result.mediaUrl).toBeUndefined();
}
}
function expectStableAudioAsVoiceDetectionCase(input: string) {
for (
const output of [splitMediaFromOutput(input), splitMediaFromOutput(input)]) {
expect(output.audioAsVoice).toBe(
true );
}
}
function expectAcceptedMediaPathCase(expectedPath: string, input: string) {
expectParsedMediaOutputCase(input, { mediaUrls: [expectedPath] });
}
function expectRejectedMediaPathCase(input: string) {
expectParsedMediaOutputCase(input, { mediaUrls: undefined });
}
it.each([
[
"/Users/pete/My File.png" ,
"MEDIA:/Users/pete/My File.png" ],
[
"/Users/pete/My File.png" ,
'MEDIA:"/Users/pete/My File.png"' ],
[
"./screenshots/image.png" ,
"MEDIA:./screenshots/image.png" ],
[
"media/inbound/image.png" ,
"MEDIA:media/inbound/image.png" ],
[
"./screenshot.png" ,
" MEDIA:./screenshot.png" ],
[
"C:\\Users\\pete\\Pictures\\snap.png" ,
"MEDIA:C:\\Users\\pete\\Pictures\\snap.png" ],
[
"/tmp/tts-fAJy8C/voice-1770246885083.opus" ,
"MEDIA:/tmp/tts-fAJy8C/voice-1770246885083.opus" ],
[
"image.png" ,
"MEDIA:image.png" ],
] as
const )(
"accepts supported media path variant: %s" , (expectedPath, input) => {
expectAcceptedMediaPathCase(expectedPath, input);
});
it.each([
"MEDIA:../../../etc/passwd" ,
"MEDIA:../../.env" ,
"MEDIA:~/.ssh/id_rsa" ,
"MEDIA:~/Pictures/My File.png" ,
"MEDIA:./foo/../../../etc/shadow" ,
] as
const )(
"rejects traversal and home-dir path: %s" , (input) => {
expectRejectedMediaPathCase(input);
});
it.each([
{
name:
"detects audio_as_voice tag and strips it" ,
input:
"Hello [[audio_as_voice]] world" ,
expected: { audioAsVoice:
true , text:
"Hello world" },
},
{
name:
"keeps MEDIA mentions in prose" ,
input:
"The MEDIA: tag fails to deliver" ,
expected: { mediaUrls: undefined, text:
"The MEDIA: tag fails to deliver" },
},
{
name:
"rejects bare words without file extensions" ,
input:
"MEDIA:screenshot" ,
expected: { mediaUrls: undefined, text:
"MEDIA:screenshot" },
},
{
name:
"keeps audio_as_voice detection stable across calls" ,
input:
"Hello [[audio_as_voice]]" ,
expected: { audioAsVoice:
true , text:
"Hello" },
assertStable:
true ,
},
] as
const )(
"$name" , ({ input, expected, assertStable }) => {
expectParsedMediaOutputCase(input, expected);
if (assertStable) {
expectStableAudioAsVoiceDetectionCase(input);
}
});
it(
"returns ordered text and media segments while ignoring fenced MEDIA lines" , () => {
const result = splitMediaFromOutput(
"Before\nMEDIA:https://example.com/a.png\n```text\nMEDIA:https://example.com/ignored.png\n```\nAfter ",
);
expect(result.segments).toEqual([
{ type:
"text" , text:
"Before" },
{ type:
"media" , url:
"https://example.com/a.png " },
{ type:
"text" , text:
"```text\nMEDIA:https://example.com/ignored.png\n```\nAfter " },
]);
});
it(
"extracts markdown image urls while keeping surrounding caption text" , () => {
expectParsedMediaOutputCase(
"Caption\n\n ", {
text:
"Caption" ,
mediaUrls: [
"https://example.com/chart.png "],
});
});
it(
"keeps inline caption text around markdown images" , () => {
expectParsedMediaOutputCase(
"Look  now", {
text:
"Look now" ,
mediaUrls: [
"https://example.com/chart.png "],
});
});
it(
"extracts multiple markdown image urls in order" , () => {
expectParsedMediaOutputCase(
"Before\n\nMiddle\n\nAfter ",
{
text:
"Before\nMiddle\nAfter" ,
mediaUrls: [
"https://example.com/one.png ", "https://example.com/two.png"],
},
);
});
it(
"strips markdown image title suffixes from extracted urls" , () => {
expectParsedMediaOutputCase(
'Caption ',
{
text:
"Caption" ,
mediaUrls: [
"https://example.com/chart.png "],
},
);
});
it(
"keeps balanced parentheses inside markdown image urls" , () => {
expectParsedMediaOutputCase(
"Chart .png) now", {
text:
"Chart now" ,
mediaUrls: [
"https://example.com/a_(1).png "],
});
});
it.each([
"",
"" ,
"" ,
] as
const )(
"does not lift local markdown image target: %s" , (input) => {
expectParsedMediaOutputCase(input, {
text: input,
mediaUrls: undefined,
});
});
it(
"does not lift markdown image urls that fail media validation" , () => {
const longUrl = `}.png)`;
expectParsedMediaOutputCase(longUrl, {
text: longUrl,
mediaUrls: undefined,
});
});
it(
"leaves very long markdown-image candidate lines as text" , () => {
const input = `${
"prefix " .repeat(
3000 )}`;
expectParsedMediaOutputCase(input, {
text: input,
mediaUrls: undefined,
});
});
});
Messung V0.5 in Prozent C=98 H=95 G=96
¤ Dauer der Verarbeitung: 0.17 Sekunden
(vorverarbeitet am 2026-06-10)
¤
*© Formatika GbR, Deutschland