test(frontend): unit tests exercise named SSE events (fidelity) + cleanup
FakeEventSource.addEventListener was a no-op, so emit() only drove onmessage.
Production relies on addEventListener for the backend's NAMED events
(event: ui_request), so the unit tests could pass while prod silently broke.
- fakeEventSource: store named handlers in a Map<string,Set>; add emitNamed()
that dispatches to them; keep emit() for the unnamed/default onmessage path
- useSessionStream.test: ui_request now driven via emitNamed (production path);
add a separate test for the unnamed text_delta path via plain emit
- f1-loop.test: widget emission switched to emitNamed("ui_request", ...)
- verified: tests FAIL if addEventListener wiring is removed from
useSessionStream (then restored)
- cleanup: fake-pi.mjs drops unused execFileSync import, uses static spawnSync
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -4,15 +4,26 @@ export class FakeEventSource {
|
||||
onopen: (() => void) | null = null;
|
||||
onerror: (() => void) | null = null;
|
||||
closed = false;
|
||||
private listeners = new Map<string, Set<(e: { data: string }) => void>>();
|
||||
constructor(public url: string) {
|
||||
FakeEventSource.instances.push(this);
|
||||
}
|
||||
/** Dispatch to the default onmessage handler (unnamed `event: message`). */
|
||||
emit(obj: unknown) {
|
||||
this.onmessage?.({ data: JSON.stringify(obj) });
|
||||
}
|
||||
// no-op stubs so useSessionStream's addEventListener calls don't throw
|
||||
addEventListener(_type: string, _handler: unknown) {}
|
||||
removeEventListener(_type: string, _handler: unknown) {}
|
||||
/** Dispatch to handlers registered for a NAMED event (e.g. "ui_request"). */
|
||||
emitNamed(type: string, obj: unknown) {
|
||||
const data = JSON.stringify(obj);
|
||||
for (const h of this.listeners.get(type) ?? []) h({ data });
|
||||
}
|
||||
addEventListener(type: string, handler: (e: { data: string }) => void) {
|
||||
if (!this.listeners.has(type)) this.listeners.set(type, new Set());
|
||||
this.listeners.get(type)!.add(handler);
|
||||
}
|
||||
removeEventListener(type: string, handler: (e: { data: string }) => void) {
|
||||
this.listeners.get(type)?.delete(handler);
|
||||
}
|
||||
close() {
|
||||
this.closed = true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user