Skip to content

Commit

Permalink
tests & an example for graphql_client (#71)
Browse files Browse the repository at this point in the history
been putting this off forever
  • Loading branch information
obmarg committed Feb 10, 2024
1 parent fa97557 commit 864feaf
Show file tree
Hide file tree
Showing 7 changed files with 221 additions and 4 deletions.
5 changes: 3 additions & 2 deletions examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ publish = false

[dependencies]
async-std = { version = "1.9", features = ["attributes"] }
async-tungstenite = { version = "0.24", features = ["async-std-runtime", "tokio-runtime"] }
async_executors = { version = "0.7", features = ["async_std"] }
cynic = { version = "3" }
futures = { version = "0.3"}

async-tungstenite = { version = "0.24", features = ["async-std-runtime", "tokio-runtime"] }
graphql_client = { version = "0.13" }
serde = "1"
tokio = { version = "1.15", features = ["rt-multi-thread", "macros"] }

[dependencies.graphql-ws-client]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//! An example of running a multiple subscriptions on a single connection
//! using `graphql-ws-client`, `async-tungstenite` & the `async_std`
//! using `cynic`, `async-tungstenite` & the `async_std`
//! executor.
//!
//! Talks to the the tide subscription example in `async-graphql`
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//! An example of creating a connection and running a single subscription on it
//! using `graphql-ws-client` and `async-tungstenite`
//! using `cynic` and `async-tungstenite`
//!
//! Talks to the the tide subscription example in `async-graphql`

Expand Down
45 changes: 45 additions & 0 deletions examples/examples/graphql-client-single-subscription.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//! An example of creating a connection and running a single subscription on it
//! using `graphql-client` and `async-tungstenite`
//!
//! Talks to the the tide subscription example in `async-graphql`

use futures::StreamExt;
use graphql_client::GraphQLQuery;
use graphql_ws_client::graphql::StreamingOperation;

#[derive(GraphQLQuery)]
#[graphql(
query_path = "examples/graphql-client-subscription.graphql",
schema_path = "../schemas/books.graphql",
response_derives = "Debug"
)]
struct BooksChanged;

#[async_std::main]
async fn main() {
use async_tungstenite::tungstenite::{client::IntoClientRequest, http::HeaderValue};
use graphql_ws_client::Client;

let mut request = "ws://localhost:8000/graphql".into_client_request().unwrap();
request.headers_mut().insert(
"Sec-WebSocket-Protocol",
HeaderValue::from_str("graphql-transport-ws").unwrap(),
);

let (connection, _) = async_tungstenite::async_std::connect_async(request)
.await
.unwrap();

println!("Connected");

let mut subscription = Client::build(connection)
.subscribe(StreamingOperation::<BooksChanged>::new(
books_changed::Variables,
))
.await
.unwrap();

while let Some(item) = subscription.next().await {
println!("{:?}", item);
}
}
10 changes: 10 additions & 0 deletions examples/examples/graphql-client-subscription.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
subscription BooksChanged {
books(mutationType: CREATED) {
id
book {
id
name
author
}
}
}
10 changes: 10 additions & 0 deletions tests/graphql-client-subscription.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
subscription BooksChanged {
books(mutationType: CREATED) {
id
book {
id
name
author
}
}
}
151 changes: 151 additions & 0 deletions tests/graphql-client-tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
use std::{future::IntoFuture, time::Duration};

use assert_matches::assert_matches;
use graphql_client::GraphQLQuery;
use graphql_ws_client::graphql::StreamingOperation;
use subscription_server::SubscriptionServer;
use tokio::time::sleep;

mod subscription_server;

#[derive(GraphQLQuery)]
#[graphql(
query_path = "tests/graphql-client-subscription.graphql",
schema_path = "schemas/books.graphql",
response_derives = "Debug"
)]
struct BooksChanged;

#[tokio::test]
async fn main_test() {
use async_tungstenite::tungstenite::{client::IntoClientRequest, http::HeaderValue};
use futures::StreamExt;

let server = SubscriptionServer::start().await;

sleep(Duration::from_millis(20)).await;

let mut request = server.websocket_url().into_client_request().unwrap();
request.headers_mut().insert(
"Sec-WebSocket-Protocol",
HeaderValue::from_str("graphql-transport-ws").unwrap(),
);

let (connection, _) = async_tungstenite::tokio::connect_async(request)
.await
.unwrap();

println!("Connected");

let (mut client, actor) = graphql_ws_client::Client::build(connection).await.unwrap();

tokio::spawn(actor.into_future());

let stream = client.subscribe(build_query()).await.unwrap();

sleep(Duration::from_millis(100)).await;

let updates = [
subscription_server::BookChanged {
id: "123".into(),
book: None,
},
subscription_server::BookChanged {
id: "456".into(),
book: None,
},
subscription_server::BookChanged {
id: "789".into(),
book: None,
},
];

futures::join!(
async {
for update in &updates {
server.send(update.to_owned()).unwrap();
}
},
async {
let received_updates = stream.take(updates.len()).collect::<Vec<_>>().await;

for (expected, update) in updates.iter().zip(received_updates) {
let update = update.unwrap();
assert_matches!(update.errors, None);
let data = update.data.unwrap();
assert_eq!(data.books.id, expected.id.0);
}
}
);
}

#[tokio::test]
async fn oneshot_operation_test() {
use async_tungstenite::tungstenite::{client::IntoClientRequest, http::HeaderValue};
use futures::StreamExt;

let server = SubscriptionServer::start().await;

sleep(Duration::from_millis(20)).await;

let mut request = server.websocket_url().into_client_request().unwrap();
request.headers_mut().insert(
"Sec-WebSocket-Protocol",
HeaderValue::from_str("graphql-transport-ws").unwrap(),
);

let (connection, _) = async_tungstenite::tokio::connect_async(request)
.await
.unwrap();

println!("Connected");

let stream = graphql_ws_client::Client::build(connection)
.subscribe(build_query())
.await
.unwrap();

let updates = [
subscription_server::BookChanged {
id: "123".into(),
book: None,
},
subscription_server::BookChanged {
id: "456".into(),
book: None,
},
subscription_server::BookChanged {
id: "789".into(),
book: None,
},
];

futures::join!(
async {
sleep(Duration::from_millis(10)).await;
for update in &updates {
server.send(update.to_owned()).unwrap();
}
},
async {
let received_updates = stream.take(updates.len()).collect::<Vec<_>>().await;

for (expected, update) in updates.iter().zip(received_updates) {
let update = update.unwrap();
assert_matches!(update.errors, None);
let data = update.data.unwrap();
assert_eq!(data.books.id, expected.id.0);
}
}
);
}

fn build_query() -> graphql_ws_client::graphql::StreamingOperation<BooksChanged> {
StreamingOperation::new(books_changed::Variables)
}

impl PartialEq<subscription_server::Book> for books_changed::BooksChangedBooksBook {
fn eq(&self, other: &subscription_server::Book) -> bool {
self.id == other.id.0 && self.name == other.name && self.author == other.author
}
}

0 comments on commit 864feaf

Please sign in to comment.