Files
boos e0a5f57793 feat(desktop): embed BoosAPI Desktop client as a subproject
Vendor the rebranded BoosAPI Desktop client (Tauri + Vue) into metapi as
a monorepo subdirectory under desktop/. Source only — node_modules,
dist, Cargo target and the upstream .git history are excluded.

desktop/ keeps its own independent Cargo workspace (desktop/src-tauri
with crates/*); it is not part of the backend boosapi crate, so a
`cargo check` at the metapi root still compiles only the backend. Build
the desktop app from desktop/src-tauri per desktop/README.md.

Note: app icons are still placeholder assets pending the final BoosAPI
logo. The updater signing keys live outside the repo and are not
included.
2026-06-22 11:32:57 +08:00

130 lines
3.5 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import { parseFenceToken } from '../src'
function parseStreamingDiff(content: string, closed = false) {
return parseFenceToken({
type: 'fence',
info: 'diff json:package.json',
content,
map: [0, 1],
meta: { closed },
} as any)
}
describe('parseFenceToken - streaming unified diff stability', () => {
it('splits standard unified diff lines without requiring a space after the marker', () => {
const node = parseFenceToken({
type: 'fence',
info: 'diff typescript',
content: [
'diff --git a/src/render.ts b/src/render.ts',
'index 0000000..1111111 100644',
'--- a/src/render.ts',
'+++ b/src/render.ts',
'@@ -1,7 +1,12 @@',
'-export function render(input) {',
'- return input',
'+export function render(input: string) {',
'+ if (!input.trim())',
'+ return \'empty\'',
'+',
'+ const normalized = input.replace(/\\r\\n/g, \'\\n\')',
'+ return normalized',
' }',
].join('\n'),
map: [0, 1],
meta: { closed: true },
} as any)
expect(node.language).toBe('typescript')
expect(node.originalCode).toBe([
'export function render(input) {',
' return input',
'}',
].join('\n'))
expect(node.updatedCode).toBe([
'export function render(input: string) {',
' if (!input.trim())',
' return \'empty\'',
'',
' const normalized = input.replace(/\\r\\n/g, \'\\n\')',
' return normalized',
'}',
].join('\n'))
})
it('withholds an unfinished replacement hunk until the added side is available', () => {
const node = parseStreamingDiff([
'{',
' "name": "markstream-vue",',
'- "version": "0.0.49",',
].join('\n'))
expect(node.originalCode).toBe([
'{',
' "name": "markstream-vue",',
].join('\n'))
expect(node.updatedCode).toBe([
'{',
' "name": "markstream-vue",',
].join('\n'))
})
it('flushes a finished replacement hunk once the added line becomes stable', () => {
const node = parseStreamingDiff([
'{',
' "name": "markstream-vue",',
'- "version": "0.0.49",',
'+ "version": "0.0.54-beta.1",',
'',
].join('\n'))
expect(node.originalCode).toBe([
'{',
' "name": "markstream-vue",',
' "version": "0.0.49",',
].join('\n'))
expect(node.updatedCode).toBe([
'{',
' "name": "markstream-vue",',
' "version": "0.0.54-beta.1",',
].join('\n'))
})
it('withholds a trailing incomplete added line instead of leaking a mismatched preview', () => {
const node = parseStreamingDiff([
'{',
' "name": "markstream-vue",',
'- "version": "0.0.49",',
'+ "version": "0.0.54-b',
].join('\n'))
expect(node.originalCode).toBe([
'{',
' "name": "markstream-vue",',
].join('\n'))
expect(node.updatedCode).toBe([
'{',
' "name": "markstream-vue",',
].join('\n'))
})
it('flushes the trailing hunk once the fence is closed', () => {
const node = parseStreamingDiff([
'{',
' "name": "markstream-vue",',
'- "version": "0.0.49",',
].join('\n'), true)
expect(node.originalCode).toBe([
'{',
' "name": "markstream-vue",',
' "version": "0.0.49",',
].join('\n'))
expect(node.updatedCode).toBe([
'{',
' "name": "markstream-vue",',
].join('\n'))
})
})