test(desktop): pin spaced MEDIA paths to two invariants
Replaces the contributed case list with one render invariant (line, inline, Windows, Artifacts share the whole path) and one streaming invariant (a split inside the path settles on the complete card); both red on main.
This commit is contained in:
@@ -1,75 +1,33 @@
|
||||
// Regression for #96657: an unquoted MEDIA: path with interior spaces rendered
|
||||
// a card for the text before the first space and left the rest as prose.
|
||||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
import { renderMediaTags } from './parts'
|
||||
import { appendAssistantTextPart, chatMessageText, mediaTagValues, renderMediaTags } from './parts'
|
||||
|
||||
describe('renderMediaTags', () => {
|
||||
it('renders a simple unquoted path without spaces', () => {
|
||||
const result = renderMediaTags('MEDIA:/home/user/report.pdf')
|
||||
expect(result).toContain('report.pdf')
|
||||
expect(result).not.toContain('MEDIA:')
|
||||
})
|
||||
const SPACED = '/home/hermes/Morten - Nobly Kickoff - Opening and cue cards EN.docx'
|
||||
const CARD = `[File: Morten - Nobly Kickoff - Opening and cue cards EN.docx](#media:${encodeURIComponent(SPACED)})`
|
||||
|
||||
it('renders a quoted path with spaces', () => {
|
||||
const result = renderMediaTags('MEDIA:"/home/user/My Document.docx"')
|
||||
expect(result).toContain('My Document.docx')
|
||||
expect(result).not.toContain('MEDIA:')
|
||||
})
|
||||
|
||||
it('renders an unquoted path with interior spaces (#96657)', () => {
|
||||
const input = 'MEDIA:/home/hermes/Morten - Nobly Kickoff - Opening and cue cards EN.docx'
|
||||
const result = renderMediaTags(input)
|
||||
// The full path must be captured — not truncated at the first space
|
||||
expect(result).toContain('Morten - Nobly Kickoff - Opening and cue cards EN.docx')
|
||||
expect(result).not.toContain('MEDIA:')
|
||||
// The entire input should be consumed (no leftover literal text)
|
||||
expect(result).toBe(renderMediaTags(input))
|
||||
})
|
||||
|
||||
it('renders a backtick-quoted path with spaces', () => {
|
||||
const result = renderMediaTags('MEDIA:`/home/user/My File.png`')
|
||||
expect(result).toContain('My File.png')
|
||||
expect(result).not.toContain('MEDIA:')
|
||||
})
|
||||
|
||||
it('renders a single-quote path with spaces', () => {
|
||||
const result = renderMediaTags("MEDIA:'/home/user/My Audio.mp3'")
|
||||
expect(result).toContain('My Audio.mp3')
|
||||
expect(result).not.toContain('MEDIA:')
|
||||
})
|
||||
|
||||
it('handles a MEDIA tag on its own line', () => {
|
||||
const text = `Some text\nMEDIA:/home/user/Report Final.pdf\nMore text`
|
||||
const result = renderMediaTags(text)
|
||||
expect(result).toContain('Report Final.pdf')
|
||||
expect(result).toContain('Some text')
|
||||
expect(result).toContain('More text')
|
||||
expect(result).not.toContain('MEDIA:')
|
||||
})
|
||||
|
||||
it('handles multiple MEDIA tags on separate lines', () => {
|
||||
const text = 'MEDIA:/home/user/First File.pdf\nMEDIA:/home/user/Second Image.png'
|
||||
const result = renderMediaTags(text)
|
||||
expect(result).toContain('First File.pdf')
|
||||
expect(result).toContain('Second Image.png')
|
||||
expect(result).not.toContain('MEDIA:')
|
||||
})
|
||||
|
||||
it('renders a Windows path with spaces', () => {
|
||||
const result = renderMediaTags(
|
||||
'MEDIA:C:\\Users\\Morten\\My Report.docx'
|
||||
describe('renderMediaTags with interior spaces', () => {
|
||||
it('keeps the whole spaced path in one card on every surface that reads MEDIA tags', () => {
|
||||
expect(renderMediaTags(`MEDIA:${SPACED}`)).toBe(CARD)
|
||||
expect(renderMediaTags(`Here you go: MEDIA:${SPACED} — enjoy`)).toBe(`Here you go: ${CARD} — enjoy`)
|
||||
expect(renderMediaTags('MEDIA:C:\\Users\\Morten\\My Report.docx')).toBe(
|
||||
'[File: My Report.docx](#media:C%3A%5CUsers%5CMorten%5CMy%20Report.docx)'
|
||||
)
|
||||
expect(result).toContain('My Report.docx')
|
||||
expect(result).not.toContain('MEDIA:')
|
||||
expect(mediaTagValues(`ready\nMEDIA:${SPACED}\nMEDIA:/tmp/a.png`)).toEqual([SPACED, '/tmp/a.png'])
|
||||
})
|
||||
|
||||
it('renders a ~/-relative path with spaces', () => {
|
||||
const result = renderMediaTags('MEDIA:~/Documents/My Notes.md')
|
||||
expect(result).toContain('My Notes.md')
|
||||
expect(result).not.toContain('MEDIA:')
|
||||
})
|
||||
it('settles on the complete path when the stream splits inside it', () => {
|
||||
const chunks = ['ready\nMEDIA:/tmp/AI', ' Brain/re', 'port.pdf', '\nall done']
|
||||
let parts = appendAssistantTextPart([], chunks[0])
|
||||
|
||||
it('leaves non-MEDIA text intact', () => {
|
||||
const result = renderMediaTags('Just some regular text without any media tags.')
|
||||
expect(result).toBe('Just some regular text without any media tags.')
|
||||
// Mid-stream the truncated prefix may render as a card; the next delta must undo it.
|
||||
for (const chunk of chunks.slice(1)) {
|
||||
parts = appendAssistantTextPart(parts, chunk)
|
||||
}
|
||||
|
||||
expect(chatMessageText({ id: 'a', parts, role: 'assistant' })).toBe(
|
||||
'ready\n[File: report.pdf](#media:%2Ftmp%2FAI%20Brain%2Freport.pdf)\nall done'
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user