diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index e236792..e532bc9 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -45,3 +45,8 @@ jobs: - name: Run Cargo:test run: cargo test --verbose --all-features + + - name: Run WASM tests + if: matrix.os == 'ubuntu-latest' + run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh + run: wasm-pack test --node -- --verbose --all-features diff --git a/Cargo.toml b/Cargo.toml index be9e921..59963e1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,14 +26,13 @@ json = ["dep:serde", "dep:serde_json"] futures-util = { version = "0.3", default-features = false, features = ["sink"] } reqwest = { version = "0.12", default-features = false } thiserror = "1" -tokio-util = { version = "0.7", default-features = false, features = ["compat"] } tracing = "0.1" - serde = { version = "1.0", default-features = false, optional = true } serde_json = { version = "1.0", default-features = false, optional = true, features = ["alloc"] } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] async-tungstenite = { version = "0.26", default-features = false } +tokio-util = { version = "0.7", default-features = false, features = ["compat"] } tungstenite = { version = "0.23", default-features = false, features = ["handshake"] } [target.'cfg(target_arch = "wasm32")'.dependencies] @@ -41,6 +40,11 @@ web-sys = { version = "0.3", features = ["WebSocket", "CloseEvent", "ErrorEvent" tokio = { version = "1", default-features = false, features = ["sync", "macros"] } [dev-dependencies] -tokio = { version = "1", features = ["macros", "rt-multi-thread"] } +tokio = { version = "1", features = ["macros", "rt"] } reqwest = { version = "0.12", features = ["default-tls"] } serde = { version = "1.0", features = ["derive"] } +futures-util = { version = "0.3", default-features = false, features = ["sink", "alloc"] } + +[target.'cfg(target_arch = "wasm32")'.dev-dependencies] +wasm-bindgen-test = "0.3" +wasm-bindgen-futures = "0.4" diff --git a/examples/hello_world.rs b/examples/hello_world.rs index 1ef89ab..4e7b995 100644 --- a/examples/hello_world.rs +++ b/examples/hello_world.rs @@ -2,7 +2,7 @@ use futures_util::{SinkExt, StreamExt, TryStreamExt}; use reqwest::Client; use reqwest_websocket::{Error, Message, RequestBuilderExt}; -#[tokio::main] +#[tokio::main(flavor = "current_thread")] async fn main() -> Result<(), Error> { let websocket = Client::default() .get("wss://echo.websocket.org/") @@ -14,7 +14,7 @@ async fn main() -> Result<(), Error> { let (mut tx, mut rx) = websocket.split(); - tokio::spawn(async move { + tokio::task::spawn_local(async move { for i in 1..11 { tx.send(Message::Text(format!("Hello, World! #{i}"))) .await diff --git a/src/json.rs b/src/json.rs index 7c0eb61..55ad283 100644 --- a/src/json.rs +++ b/src/json.rs @@ -55,6 +55,7 @@ impl Message { match self { Self::Text(x) => serde_json::from_str(x).map_err(Into::into), Self::Binary(x) => serde_json::from_slice(x).map_err(Into::into), + #[allow(deprecated)] Self::Ping(_) | Self::Pong(_) | Self::Close { .. } => { Err(serde_json::Error::custom("neither text nor binary").into()) } diff --git a/src/lib.rs b/src/lib.rs index 3c6d61b..022808e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -236,6 +236,13 @@ impl WebSocket { } /// Closes the connection with a given code and (optional) reason. + /// + /// # WASM + /// + /// On wasm only `code` must be [`CloseCode::Normal`], + /// [`CloseCode::Iana(_)`], or [`CloseCode::Library(_)`]. Furthermore + /// `reason` must be at most 128 bytes long. Otherwise the call to + /// [`close`][Self::close] will fail. pub async fn close(self, code: CloseCode, reason: Option<&str>) -> Result<(), Error> { #[cfg(not(target_arch = "wasm32"))] { @@ -301,9 +308,11 @@ impl Sink for WebSocket { } #[cfg(test)] -mod tests { +pub mod tests { use futures_util::{SinkExt, TryStreamExt}; use reqwest::Client; + #[cfg(target_arch = "wasm32")] + use wasm_bindgen_test::wasm_bindgen_test; use super::{websocket, CloseCode, Message, RequestBuilderExt, WebSocket}; @@ -328,7 +337,8 @@ mod tests { panic!("didn't receive text back"); } - #[tokio::test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + #[cfg_attr(not(target_arch = "wasm32"), tokio::test)] async fn test_with_request_builder() { let websocket = Client::default() .get("https://echo.websocket.org/") @@ -343,29 +353,33 @@ mod tests { test_websocket(websocket).await; } - #[tokio::test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + #[cfg_attr(not(target_arch = "wasm32"), tokio::test)] async fn test_shorthand() { let websocket = websocket("https://echo.websocket.org/").await.unwrap(); test_websocket(websocket).await; } - #[tokio::test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + #[cfg_attr(not(target_arch = "wasm32"), tokio::test)] async fn test_with_ws_scheme() { let websocket = websocket("wss://echo.websocket.org/").await.unwrap(); test_websocket(websocket).await; } - #[tokio::test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + #[cfg_attr(not(target_arch = "wasm32"), tokio::test)] async fn test_close() { let websocket = websocket("https://echo.websocket.org/").await.unwrap(); websocket - .close(CloseCode::Protocol, Some("test")) + .close(CloseCode::Normal, Some("test")) .await .expect("close returned an error"); } - #[tokio::test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + #[cfg_attr(not(target_arch = "wasm32"), tokio::test)] async fn test_send_close_frame() { let mut websocket = websocket("https://echo.websocket.org/").await.unwrap(); websocket