Repository: vapor/vapor
File: Tests/VaporTests/WebSocketTests.swift (Swift)

Code before:

final class WebSocketTests: XCTestCase {
    func testWebSocketClient() throws {
        let server = Application(.testing)

        server.http.server.configuration.port = 0

        server.webSocket("echo") { req, ws in
            ws.onText { ws.send($1) }
        }
        server.environment.arguments = ["serve"]
        try server.start()

        let app = Application(.testing)
        defer {
            app.shutdown()
            server.shutdown()
        }

        guard let localAddress = server.http.server.shared.localAddress,
              let port = localAddress.port else {
                  XCTFail("couldn't get port from \(app.http.server.shared.localAddress.debugDescription)")
                  return
              }

        app.get("ws") { req -> EventLoopFuture<String> in
            let promise = req.eventLoop.makePromise(of: String.self)
            return WebSocket.connect(
                to: "ws://localhost:\(port)/echo",
                on: req.eventLoop
            ) { ws in
                ws.send("Hello, world!")
                ws.onText { ws, text in
                    promise.succeed(text)
                    ws.close().cascadeFailure(to: promise)
                }
            }.flatMap {
                return promise.futureResult
            }.flatMapError { error in
                promise.fail(error)
                return promise.futureResult
            }
        }

        try app.testable().test(.GET, "/ws") { res in
            XCTAssertEqual(res.status, .ok)
            XCTAssertEqual(res.body.string, "Hello, world!")
        }
    }



Review comment (suggestion):
Oh, why is the call to the websocket triggered in an `HTTPRequest`. I would guess, if you really want to use the WebSocket client, you could drop the `app = Application(.testing)` and just use the `WebSocket.connect`

Code after:

final class WebSocketTests: XCTestCase {
    func testWebSocketClient() throws {
        let server = Application(.testing)

        server.http.server.configuration.port = 0

        server.webSocket("echo") { req, ws in
            ws.onText { ws.send($1) }
        }
        server.environment.arguments = ["serve"]
        try server.start()

        defer {
            server.shutdown()
        }

        guard let localAddress = server.http.server.shared.localAddress, let port = localAddress.port else {
            XCTFail("couldn't get port from \(server.http.server.shared.localAddress.debugDescription)")
            return
        }

        let elg = MultiThreadedEventLoopGroup(numberOfThreads: 1)

        let promise = elg.next().makePromise(of: String.self)
        let string = try WebSocket.connect(
            to: "ws://localhost:\(port)/echo",
            on: elg.next()
        ) { ws in
            ws.send("Hello, world!")
            ws.onText { ws, text in
                promise.succeed(text)
                ws.close().cascadeFailure(to: promise)
            }
        }.flatMap {
            return promise.futureResult
        }.flatMapError { error in
            promise.fail(error)
            return promise.futureResult
        }.wait()
        XCTAssertEqual(string, "Hello, world!")
    }


    // https://github.com/vapor/vapor/issues/1997
    func testWebSocket404() throws {
        let app = Application(.testing)
        defer { app.shutdown() }

        app.http.server.configuration.port = 8085