@@ -270,7 +270,25 @@ pub const default_browser_headers: List(#(String, String)) = [
270
270
]
271
271
272
272
/// Create a websocket upgrade request with proper headers.
273
- /// This creates a request that simulates a WebSocket upgrade handshake.
273
+ ///
274
+ /// This creates a request that simulates a WebSocket upgrade handshake by
275
+ /// setting the necessary headers: `connection`, `upgrade`, `sec-websocket-key`,
276
+ /// and `sec-websocket-version`.
277
+ ///
278
+ /// ## Example
279
+ ///
280
+ /// ```gleam
281
+ /// let request = simulate.websocket_request(http.Get, "/chat")
282
+ /// let response = handle_request(request)
283
+ ///
284
+ /// case response.body {
285
+ /// wisp.WebSocket(upgrade) -> {
286
+ /// let handler = wisp.upgrade_to_websocket(upgrade)
287
+ /// // Test the websocket handler
288
+ /// }
289
+ /// _ -> panic as "Expected WebSocket upgrade"
290
+ /// }
291
+ /// ```
274
292
///
275
293
pub fn websocket_request(method: http.Method, path: String) -> Request {
276
294
request(method, path)
@@ -280,9 +298,24 @@ pub fn websocket_request(method: http.Method, path: String) -> Request {
280
298
|> header("sec-websocket-version", "13")
281
299
}
282
300
283
- /// A websocket mock that captures sent messages for testing.
284
- /// This allows you to verify what messages your websocket handler sends
285
- /// in response to incoming messages.
301
+ /// A websocket mock for testing websocket handlers.
302
+ ///
303
+ /// This opaque type represents a test websocket connection that captures all
304
+ /// messages sent by the handler. It maintains the handler's state and tracks
305
+ /// all text and binary messages sent through the connection.
306
+ ///
307
+ /// You cannot construct this type directly - use `create_websocket` to create
308
+ /// a test websocket from a websocket handler.
309
+ ///
310
+ /// ## Functions
311
+ ///
312
+ /// - `create_websocket` - Create a new test websocket
313
+ /// - `send_websocket_text` - Send a text message to the handler
314
+ /// - `send_websocket_binary` - Send a binary message to the handler
315
+ /// - `websocket_sent_text_messages` - Get all text messages sent by the handler
316
+ /// - `websocket_sent_binary_messages` - Get all binary messages sent by the handler
317
+ /// - `reset_websocket` - Reset to initial state
318
+ /// - `close_websocket` - Close the connection
286
319
///
287
320
pub opaque type WebSocket {
288
321
WebSocket(
@@ -316,8 +349,39 @@ type WebSocketMessage {
316
349
IsClosed(reply_with: process.Subject(Bool))
317
350
}
318
351
319
- /// Create a new websocket mock that captures all sent messages.
320
- /// Returns both the websocket and the websocket connection.
352
+ /// Create a new websocket mock for testing.
353
+ ///
354
+ /// This function creates a test websocket that captures all messages sent by the
355
+ /// handler, allowing you to verify the handler's behavior without needing a real
356
+ /// WebSocket connection. The mock automatically tracks text and binary messages
357
+ /// sent through the connection.
358
+ ///
359
+ /// ## Example
360
+ ///
361
+ /// ```gleam
362
+ /// let handler = websocket.new(
363
+ /// on_init: fn(_conn) { 0 },
364
+ /// on_message: fn(state, message, connection) {
365
+ /// case message {
366
+ /// websocket.Text(text) -> {
367
+ /// websocket.send_text(connection, "Echo: " <> text)
368
+ /// websocket.Continue(state + 1)
369
+ /// }
370
+ /// _ -> websocket.Continue(state)
371
+ /// }
372
+ /// },
373
+ /// on_close: fn(_state) { Nil },
374
+ /// )
375
+ ///
376
+ /// let assert Ok(ws) = simulate.create_websocket(handler)
377
+ /// let assert Ok(ws) = simulate.send_websocket_text(ws, "Hello")
378
+ /// let assert ["Echo: Hello"] = simulate.websocket_sent_text_messages(ws)
379
+ /// ```
380
+ ///
381
+ /// ## Returns
382
+ ///
383
+ /// - `Ok(WebSocket)` - A test websocket that can be used with other simulate functions
384
+ /// - `Error(actor.StartError)` - If the underlying actor fails to start
321
385
///
322
386
pub fn create_websocket(
323
387
handler websocket: websocket.WebSocket,
@@ -421,21 +485,67 @@ fn handle_message(
421
485
}
422
486
}
423
487
424
- /// Get all text messages that were sent through the mock connection.
425
- /// Messages are returned in the order they were sent.
488
+ /// Get all text messages that have been sent by the websocket handler.
489
+ ///
490
+ /// Messages are returned in the order they were sent. This is useful for
491
+ /// verifying that your handler sends the expected messages in response to
492
+ /// incoming messages.
493
+ ///
494
+ /// ## Example
495
+ ///
496
+ /// ```gleam
497
+ /// let assert Ok(ws) = simulate.create_websocket(handler)
498
+ /// let assert Ok(ws) = simulate.send_websocket_text(ws, "Hello")
499
+ /// let assert Ok(ws) = simulate.send_websocket_text(ws, "World")
500
+ ///
501
+ /// let messages = simulate.websocket_sent_text_messages(ws)
502
+ /// assert messages == ["Response 1", "Response 2"]
503
+ /// ```
426
504
///
427
505
pub fn websocket_sent_text_messages(websocket: WebSocket) -> List(String) {
428
506
process.call(websocket.subject, 1000, GetSentTextMessages)
429
507
}
430
508
431
- /// Get all binary messages that were sent through the mock connection.
432
- /// Messages are returned in the order they were sent.
509
+ /// Get all binary messages that have been sent by the websocket handler.
510
+ ///
511
+ /// Messages are returned in the order they were sent. This is useful for
512
+ /// verifying that your handler sends the expected binary data in response to
513
+ /// incoming messages.
514
+ ///
515
+ /// ## Example
516
+ ///
517
+ /// ```gleam
518
+ /// let assert Ok(ws) = simulate.create_websocket(handler)
519
+ /// let assert Ok(ws) = simulate.send_websocket_binary(ws, <<1, 2, 3>>)
520
+ ///
521
+ /// let messages = simulate.websocket_sent_binary_messages(ws)
522
+ /// assert messages == [<<1, 2, 3>>]
523
+ /// ```
433
524
///
434
525
pub fn websocket_sent_binary_messages(websocket: WebSocket) -> List(BitArray) {
435
526
process.call(websocket.subject, 1000, GetSentBinaryMessages)
436
527
}
437
528
438
- /// Reset the mock to its initial state, clearing all captured messages.
529
+ /// Reset the websocket to its initial state, clearing all captured messages.
530
+ ///
531
+ /// This calls the handler's `on_init` callback again and clears the list of
532
+ /// sent messages. The websocket is also marked as not closed, allowing you to
533
+ /// send messages again after a close.
534
+ ///
535
+ /// ## Example
536
+ ///
537
+ /// ```gleam
538
+ /// let assert Ok(ws) = simulate.create_websocket(handler)
539
+ /// let assert Ok(ws) = simulate.send_websocket_text(ws, "Hello")
540
+ /// let assert ["Response"] = simulate.websocket_sent_text_messages(ws)
541
+ ///
542
+ /// // Reset to initial state
543
+ /// let ws = simulate.reset_websocket(ws)
544
+ /// let assert [] = simulate.websocket_sent_text_messages(ws)
545
+ ///
546
+ /// // Can send messages again from a clean slate
547
+ /// let assert Ok(ws) = simulate.send_websocket_text(ws, "Hello again")
548
+ /// ```
439
549
///
440
550
pub fn reset_websocket(websocket: WebSocket) -> WebSocket {
441
551
let WebSocket(websocket: internal_websocket, connection:, state: _, subject:) =
@@ -446,8 +556,28 @@ pub fn reset_websocket(websocket: WebSocket) -> WebSocket {
446
556
WebSocket(websocket: internal_websocket, connection:, state:, subject:)
447
557
}
448
558
449
- /// Simulate sending a text message to a websocket handler.
450
- /// Returns the updated state and any effects that occurred.
559
+ /// Simulate sending a text message to the websocket handler.
560
+ ///
561
+ /// This calls the handler's `on_message` callback with a `Text` message. The
562
+ /// handler's state is updated based on the callback's response. Any messages
563
+ /// sent by the handler can be retrieved using `websocket_sent_text_messages`
564
+ /// or `websocket_sent_binary_messages`.
565
+ ///
566
+ /// If the websocket has been closed, this function returns the websocket
567
+ /// unchanged without calling the handler.
568
+ ///
569
+ /// ## Example
570
+ ///
571
+ /// ```gleam
572
+ /// let assert Ok(ws) = simulate.create_websocket(handler)
573
+ /// let assert Ok(ws) = simulate.send_websocket_text(ws, "Hello")
574
+ /// let assert ["Echo: Hello"] = simulate.websocket_sent_text_messages(ws)
575
+ /// ```
576
+ ///
577
+ /// ## Returns
578
+ ///
579
+ /// - `Ok(WebSocket)` - The websocket with updated state
580
+ /// - `Error(Nil)` - If the handler returns `Stop` or `StopWithError`
451
581
///
452
582
pub fn send_websocket_text(
453
583
ws: WebSocket,
@@ -471,8 +601,28 @@ pub fn send_websocket_text(
471
601
}
472
602
}
473
603
474
- /// Simulate sending a binary message to a websocket handler.
475
- /// Returns the updated state and any effects that occurred.
604
+ /// Simulate sending a binary message to the websocket handler.
605
+ ///
606
+ /// This calls the handler's `on_message` callback with a `Binary` message. The
607
+ /// handler's state is updated based on the callback's response. Any messages
608
+ /// sent by the handler can be retrieved using `websocket_sent_text_messages`
609
+ /// or `websocket_sent_binary_messages`.
610
+ ///
611
+ /// If the websocket has been closed, this function returns the websocket
612
+ /// unchanged without calling the handler.
613
+ ///
614
+ /// ## Example
615
+ ///
616
+ /// ```gleam
617
+ /// let assert Ok(ws) = simulate.create_websocket(handler)
618
+ /// let assert Ok(ws) = simulate.send_websocket_binary(ws, <<1, 2, 3>>)
619
+ /// let assert [<<1, 2, 3>>] = simulate.websocket_sent_binary_messages(ws)
620
+ /// ```
621
+ ///
622
+ /// ## Returns
623
+ ///
624
+ /// - `Ok(WebSocket)` - The websocket with updated state
625
+ /// - `Error(Nil)` - If the handler returns `Stop` or `StopWithError`
476
626
///
477
627
pub fn send_websocket_binary(
478
628
ws: WebSocket,
@@ -496,8 +646,32 @@ pub fn send_websocket_binary(
496
646
}
497
647
}
498
648
499
- /// Simulate closing a websocket connection.
500
- /// Returns the updated state representing the closed connection.
649
+ /// Simulate closing the websocket connection.
650
+ ///
651
+ /// This calls the handler's `on_close` callback with the current handler state.
652
+ /// After closing, any subsequent calls to `send_websocket_text` or
653
+ /// `send_websocket_binary` will be ignored without calling the handler.
654
+ ///
655
+ /// Use `reset_websocket` to re-open the connection for further testing.
656
+ ///
657
+ /// ## Example
658
+ ///
659
+ /// ```gleam
660
+ /// let assert Ok(ws) = simulate.create_websocket(handler)
661
+ /// let assert Ok(ws) = simulate.send_websocket_text(ws, "Hello")
662
+ ///
663
+ /// // Close the connection
664
+ /// let assert Ok(Nil) = simulate.close_websocket(ws)
665
+ ///
666
+ /// // Further messages are ignored
667
+ /// let assert Ok(ws) = simulate.send_websocket_text(ws, "After close")
668
+ /// let assert ["Response 1"] = simulate. websocket_sent_text_messages( ws)
669
+ /// ```
670
+ ///
671
+ /// ## Returns
672
+ ///
673
+ /// - `Ok(Nil)` - If the connection was closed successfully
674
+ /// - `Error(WebSocketError)` - If closing the connection failed
501
675
///
502
676
pub fn close_websocket (
503
677
websocket : WebSocket ,
0 commit comments