Implement OutputType for FieldResult
This commit is contained in:
parent
4aaba01a88
commit
f3697e6a1a
37
src/base.rs
37
src/base.rs
|
@ -1,5 +1,5 @@
|
|||
use crate::registry::Registry;
|
||||
use crate::{registry, Context, ContextSelectionSet, QueryError, Result, ID};
|
||||
use crate::{registry, Context, ContextSelectionSet, FieldResult, QueryError, Result, ID};
|
||||
use graphql_parser::query::Value;
|
||||
use graphql_parser::Pos;
|
||||
use std::borrow::Cow;
|
||||
|
@ -238,3 +238,38 @@ impl<T: OutputValueType + Send + Sync> OutputValueType for Arc<T> {
|
|||
T::resolve(&*value, ctx, pos).await
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Type> Type for FieldResult<T> {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
T::type_name()
|
||||
}
|
||||
|
||||
fn qualified_type_name() -> String {
|
||||
T::qualified_type_name()
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut registry::Registry) -> String {
|
||||
T::create_type_info(registry);
|
||||
T::type_name().to_string()
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<T: OutputValueType + Sync> OutputValueType for FieldResult<T> {
|
||||
async fn resolve(
|
||||
value: &Self,
|
||||
ctx: &ContextSelectionSet<'_>,
|
||||
pos: Pos,
|
||||
) -> crate::Result<serde_json::Value> where {
|
||||
match value.as_ref() {
|
||||
Ok(value) => Ok(OutputValueType::resolve(value, ctx, pos).await?),
|
||||
Err(err) => Err(err.clone().into_error_with_path(
|
||||
pos,
|
||||
match &ctx.path_node {
|
||||
Some(path) => path.to_json(),
|
||||
None => serde_json::Value::Null,
|
||||
},
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
59
tests/fieldresult.rs
Normal file
59
tests/fieldresult.rs
Normal file
|
@ -0,0 +1,59 @@
|
|||
use async_graphql::*;
|
||||
|
||||
#[async_std::test]
|
||||
pub async fn test_fieldresult() {
|
||||
struct Query;
|
||||
|
||||
#[Object]
|
||||
impl Query {
|
||||
async fn error(&self) -> FieldResult<i32> {
|
||||
Err("TestError".into())
|
||||
}
|
||||
|
||||
async fn opt_error(&self) -> Option<FieldResult<i32>> {
|
||||
Some(Err("TestError".into()))
|
||||
}
|
||||
|
||||
async fn vec_error(&self) -> Vec<FieldResult<i32>> {
|
||||
vec![Ok(1), Err("TestError".into())]
|
||||
}
|
||||
}
|
||||
|
||||
let schema = Schema::new(Query, EmptyMutation, EmptySubscription);
|
||||
|
||||
assert_eq!(
|
||||
schema.execute("{ error }").await.unwrap_err(),
|
||||
Error::Query {
|
||||
pos: Pos { line: 1, column: 3 },
|
||||
path: Some(serde_json::json!(["error"])),
|
||||
err: QueryError::FieldError {
|
||||
err: "TestError".to_string(),
|
||||
extended_error: None,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
schema.execute("{ optError }").await.unwrap_err(),
|
||||
Error::Query {
|
||||
pos: Pos { line: 1, column: 3 },
|
||||
path: Some(serde_json::json!(["optError"])),
|
||||
err: QueryError::FieldError {
|
||||
err: "TestError".to_string(),
|
||||
extended_error: None,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
schema.execute("{ vecError }").await.unwrap_err(),
|
||||
Error::Query {
|
||||
pos: Pos { line: 1, column: 3 },
|
||||
path: Some(serde_json::json!(["vecError", 1])),
|
||||
err: QueryError::FieldError {
|
||||
err: "TestError".to_string(),
|
||||
extended_error: None,
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
|
@ -489,3 +489,52 @@ pub async fn test_subscription_error() {
|
|||
|
||||
assert!(stream.next().await.is_none());
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
pub async fn test_subscription_fieldresult() {
|
||||
struct QueryRoot;
|
||||
|
||||
#[Object]
|
||||
impl QueryRoot {}
|
||||
|
||||
struct SubscriptionRoot;
|
||||
|
||||
#[Subscription]
|
||||
impl SubscriptionRoot {
|
||||
async fn values(&self) -> impl Stream<Item = FieldResult<i32>> {
|
||||
futures::stream::iter(0..5)
|
||||
.map(FieldResult::Ok)
|
||||
.chain(futures::stream::once(
|
||||
async move { Err("StreamErr".into()) },
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
let schema = Schema::new(QueryRoot, EmptyMutation, SubscriptionRoot);
|
||||
let mut stream = schema
|
||||
.create_subscription_stream("subscription { values }", None, Default::default(), None)
|
||||
.await
|
||||
.unwrap();
|
||||
for i in 0i32..5 {
|
||||
assert_eq!(
|
||||
Some(Ok(serde_json::json!({ "values": i }))),
|
||||
stream.next().await
|
||||
);
|
||||
}
|
||||
assert_eq!(
|
||||
stream.next().await,
|
||||
Some(Err(Error::Query {
|
||||
pos: Pos {
|
||||
line: 1,
|
||||
column: 16
|
||||
},
|
||||
path: Some(serde_json::json!(["values"])),
|
||||
err: QueryError::FieldError {
|
||||
err: "StreamErr".to_string(),
|
||||
extended_error: None,
|
||||
},
|
||||
}))
|
||||
);
|
||||
|
||||
assert!(stream.next().await.is_none());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user