Search code examples
rustactix-web

How to access the connection status of an awc websocket client?


I have a basic Actix Web server set up, and I have successfully been creating websocket connections in my tests using awc::client::Client.

Now I am trying to test that my server is closing all of the websocket connections when I tell it reset the status of the app.

My current planned test for this is:

#[test]
async fn reset_game_works_basic() {
    let server: TestServer = test_fixtures::get_test_server();
    let (_resp, mut chris_connection) = Client::new()
        .ws(server.url("/join-game?username=Chris"))
        .connect()
        .await
        .unwrap();

    let _ = server.post("/reset-game").send().await;
    let websocket_connected = chris_connection.websocket_connected_status();
                                            // ^^^^ Not a real function 
    assert_eq!(websocket_connected, false);
}

From the awc websocket docs, I have only been able to find a CloseCode enum, but that seems to be used for the client to tell the server why it is closing the connection.

I also fruitlessly tried to check if the connection was open by using is_write_ready(), but that returned true.

I have done manual testing with Postman, and the clients are being disconnected when you send a post request to /reset-game.

How should I ask the client if it still has an open connection?


Solution

  • I ended up finding a working (albiet fragile) test for this.

    When the websocket connection is closed, .next().await will return None, and when it is open, it will return Some, even if there is no next message!

    So this test successfully passes with the working code, and fails if I remove the code that actually closes the websocket!

    #[test]
    async fn reset_game_works_basic() {
        let server: TestServer = test_fixtures::get_test_server();
        let (_resp, mut chris_connection) = Client::new()
            .ws(server.url("/join-game?username=Chris"))
            .connect()
            .await
            .unwrap();
    
        let _ = server.post("/reset-game").send().await;
    
        let _join = chris_connection.next().await;
    
        let no_message = chris_connection.next().await;
    
        let websocket_disconnected = no_message.is_none();
    
        assert_eq!(websocket_disconnected, true);
    }
    

    It certainly is fragile to the problem that if I make the websocket send a second message before disconnecting it will break, but that is a separate problem to the one I was trying to solve here.