Network Stack: XMLHttpRequest + WebSocket + EventSource + sendBeacon #5

Closed
opened 2026-06-17 13:37:43 +00:00 by Artur · 1 comment
Owner

Goal

Implement XMLHttpRequest, WebSocket (fake), EventSource (fake), and navigator.sendBeacon.

What to Build

src/network/xhr.ts

export function createXMLHttpRequest(cookieJar: CookieJar, networkLog: NetworkLog): typeof XMLHttpRequest {
  // Full XHR implementation with:
  // - open(method, url, async, user, password)
  // - setRequestHeader(name, value)
  // - send(body)
  // - abort()
  // - getAllResponseHeaders(), getResponseHeader(name)
  // - overrideMimeType(mime)
  // - Event sequence: readystatechange, loadstart, progress, load, loadend, error, abort, timeout
  // - readyState: UNSENT(0), OPENED(1), HEADERS_RECEIVED(2), LOADING(3), DONE(4)
  // - Cookie jar integration
  // - Network log integration
}

src/network/websocket.ts

export class WrappedWebSocket extends EventTarget {
  constructor(url: string, protocols?: string | string[]);
  // Fake implementation:
  // - readyState: CONNECTING(0) -> OPEN(1) via setTimeout
  // - send(data): logs to NetworkLog, does nothing
  // - close(): fires close event
  // - onopen, onmessage, onclose, onerror
  // - binaryType, bufferedAmount, extensions, protocol, url
}

export function createWebSocket(networkLog: NetworkLog): typeof WebSocket;

// Also:
// - navigator.sendBeacon(url, data) -> POST with no response handling, logs to NetworkLog
// - EventSource(url) -> fake SSE, fires onmessage with dummy data (configurable)

Event Sequences

API Event Sequence
XHR send() readystatechange(1) -> loadstart -> readystatechange(2) -> readystatechange(3) -> readystatechange(4) -> load -> loadend
XHR error readystatechange(4) -> error -> loadend
XHR abort readystatechange(4) -> abort -> loadend
WebSocket open open event after ~1ms
WebSocket message message event on next microtask
WebSocket close close event(code, reason, wasClean)

Tests

Unit Tests

Test Verifies
xhr.basic.test.ts GET request -> status, responseText, readyState sequence
xhr.post.test.ts POST with body, correct method in log
xhr.headers.test.ts setRequestHeader/getResponseHeader round-trip
xhr.abort.test.ts abort() fires abort event, readyState becomes DONE
xhr.event-order.test.ts Events fire in correct order (loadstart -> ... -> loadend)
xhr.error.test.ts Network error fires error + loadend
xhr.cookies.test.ts Cookies attached from jar
websocket.open.test.ts onopen fires, readyState becomes OPEN(1)
websocket.send.test.ts send() logged to NetworkLog
websocket.close.test.ts close() fires close event
websocket.event-target.test.ts addEventListener works
send-beacon.test.ts sendBeacon() POSTs, logged
event-source.test.ts EventSource fires onmessage

Edge Cases

Test Verifies
xhr.unsent-read.test.ts Reading responseText in UNSENT state returns empty string
xhr.double-send.test.ts Calling send() twice throws or ignores
xhr.timeout.test.ts timeout property works
websocket.url-parse.test.ts ws:// and wss:// URLs accepted
websocket.protocol.test.ts protocols parameter handled

Definition of Done

  • src/network/xhr.ts implemented
  • src/network/websocket.ts implemented
  • sendBeacon implemented
  • EventSource implemented (fake)
  • Cookie jar integration
  • Network log integration
  • All tests pass
  • 100% line + branch coverage
## Goal Implement XMLHttpRequest, WebSocket (fake), EventSource (fake), and navigator.sendBeacon. ## What to Build ### src/network/xhr.ts ``` export function createXMLHttpRequest(cookieJar: CookieJar, networkLog: NetworkLog): typeof XMLHttpRequest { // Full XHR implementation with: // - open(method, url, async, user, password) // - setRequestHeader(name, value) // - send(body) // - abort() // - getAllResponseHeaders(), getResponseHeader(name) // - overrideMimeType(mime) // - Event sequence: readystatechange, loadstart, progress, load, loadend, error, abort, timeout // - readyState: UNSENT(0), OPENED(1), HEADERS_RECEIVED(2), LOADING(3), DONE(4) // - Cookie jar integration // - Network log integration } ``` ### src/network/websocket.ts ``` export class WrappedWebSocket extends EventTarget { constructor(url: string, protocols?: string | string[]); // Fake implementation: // - readyState: CONNECTING(0) -> OPEN(1) via setTimeout // - send(data): logs to NetworkLog, does nothing // - close(): fires close event // - onopen, onmessage, onclose, onerror // - binaryType, bufferedAmount, extensions, protocol, url } export function createWebSocket(networkLog: NetworkLog): typeof WebSocket; // Also: // - navigator.sendBeacon(url, data) -> POST with no response handling, logs to NetworkLog // - EventSource(url) -> fake SSE, fires onmessage with dummy data (configurable) ``` ### Event Sequences | API | Event Sequence | |-----|---------------| | XHR send() | readystatechange(1) -> loadstart -> readystatechange(2) -> readystatechange(3) -> readystatechange(4) -> load -> loadend | | XHR error | readystatechange(4) -> error -> loadend | | XHR abort | readystatechange(4) -> abort -> loadend | | WebSocket open | open event after ~1ms | | WebSocket message | message event on next microtask | | WebSocket close | close event(code, reason, wasClean) | ## Tests ### Unit Tests | Test | Verifies | |------|----------| | xhr.basic.test.ts | GET request -> status, responseText, readyState sequence | | xhr.post.test.ts | POST with body, correct method in log | | xhr.headers.test.ts | setRequestHeader/getResponseHeader round-trip | | xhr.abort.test.ts | abort() fires abort event, readyState becomes DONE | | xhr.event-order.test.ts | Events fire in correct order (loadstart -> ... -> loadend) | | xhr.error.test.ts | Network error fires error + loadend | | xhr.cookies.test.ts | Cookies attached from jar | | websocket.open.test.ts | onopen fires, readyState becomes OPEN(1) | | websocket.send.test.ts | send() logged to NetworkLog | | websocket.close.test.ts | close() fires close event | | websocket.event-target.test.ts | addEventListener works | | send-beacon.test.ts | sendBeacon() POSTs, logged | | event-source.test.ts | EventSource fires onmessage | ### Edge Cases | Test | Verifies | |------|----------| | xhr.unsent-read.test.ts | Reading responseText in UNSENT state returns empty string | | xhr.double-send.test.ts | Calling send() twice throws or ignores | | xhr.timeout.test.ts | timeout property works | | websocket.url-parse.test.ts | ws:// and wss:// URLs accepted | | websocket.protocol.test.ts | protocols parameter handled | ## Definition of Done - [ ] src/network/xhr.ts implemented - [ ] src/network/websocket.ts implemented - [ ] sendBeacon implemented - [ ] EventSource implemented (fake) - [ ] Cookie jar integration - [ ] Network log integration - [ ] All tests pass - [ ] 100% line + branch coverage
Author
Owner

Network Stack: XMLHttpRequest + WebSocket + EventSource + sendBeacon. Implementiert. Tests: xhr.test.ts, websocket.test.ts, beacon.test.ts.

Network Stack: XMLHttpRequest + WebSocket + EventSource + sendBeacon. ✅ Implementiert. Tests: xhr.test.ts, websocket.test.ts, beacon.test.ts.
Artur closed this issue 2026-06-18 06:28:02 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
glow-all/true-headless-browser#5
No description provided.