Files
opencode-mobile/src/lib/sse.test.ts
engineer dd55ca471d test(lib): cover SSE event-stream framing (20→29 tests)
Extract the SSE chunk-buffering from sdk.ts into a pure SSEParser (sdk.ts delegates;
behavior unchanged) and pin the framing rules that are easy to break when an event
splits across network reads: partial trailing lines held until completed, frames
reassembled across 2-3 reads, [DONE] sentinel and empty/non-data lines filtered,
each frame emitted exactly once. typecheck clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 13:58:19 -07:00

64 lines
2.3 KiB
TypeScript

import { test } from "node:test"
import assert from "node:assert/strict"
import { SSEParser } from "./sse.ts"
// The opencode live chat is driven by this SSE stream. The hard cases are framing:
// events that arrive split across network reads must not be dropped or corrupted.
test("parses a single complete data frame in one chunk", () => {
const p = new SSEParser()
assert.deepEqual(p.push('data: {"x":1}\n'), ['{"x":1}'])
})
test("parses multiple frames in one chunk in order", () => {
const p = new SSEParser()
assert.deepEqual(p.push("data: a\ndata: b\ndata: c\n"), ["a", "b", "c"])
})
test("holds a partial trailing line until the next chunk completes it", () => {
const p = new SSEParser()
// First read ends mid-frame (no trailing newline yet).
assert.deepEqual(p.push('data: {"hello":'), [])
// Second read delivers the rest plus the terminating newline.
assert.deepEqual(p.push('"world"}\n'), ['{"hello":"world"}'])
})
test("reassembles a frame split across three reads", () => {
const p = new SSEParser()
assert.deepEqual(p.push("dat"), [])
assert.deepEqual(p.push("a: par"), [])
assert.deepEqual(p.push("tial\n"), ["partial"])
})
test("filters the [DONE] sentinel", () => {
const p = new SSEParser()
assert.deepEqual(p.push("data: [DONE]\n"), [])
assert.deepEqual(p.push("data: real\ndata: [DONE]\n"), ["real"])
})
test("ignores empty data payloads and non-data lines", () => {
const p = new SSEParser()
// keepalive comment, an event: line, a blank line, and an empty data payload
assert.deepEqual(p.push(": keepalive\nevent: ping\n\ndata: \ndata: x\n"), ["x"])
})
test("a frame held across chunks is emitted exactly once", () => {
const p = new SSEParser()
const first = p.push("data: one\ndata: tw")
const second = p.push("o\ndata: three\n")
assert.deepEqual(first, ["one"])
assert.deepEqual(second, ["two", "three"])
})
test("blank chunk yields nothing and preserves the held buffer", () => {
const p = new SSEParser()
assert.deepEqual(p.push("data: held"), [])
assert.deepEqual(p.push(""), [])
assert.deepEqual(p.push("\n"), ["held"])
})
test("data payload preserves internal colons and spaces (only the 'data: ' prefix is stripped)", () => {
const p = new SSEParser()
assert.deepEqual(p.push('data: {"url":"http://x:1"}\n'), ['{"url":"http://x:1"}'])
})