Rework Failure #671

This commit is contained in:
Sunli 2021-11-04 19:37:22 +08:00
parent 246d72a9f0
commit d62aca8052
11 changed files with 199 additions and 174 deletions

View File

@ -1,6 +1,9 @@
use std::any::Any;
use std::collections::BTreeMap;
use std::error::Error as StdError;
use std::fmt::{self, Debug, Display, Formatter};
use std::marker::PhantomData;
use std::sync::Arc;
use serde::{Deserialize, Serialize};
use thiserror::Error;
@ -20,15 +23,13 @@ impl ErrorExtensionValues {
}
/// An error in a GraphQL server.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Clone, Serialize, Deserialize)]
pub struct ServerError {
/// An explanatory message of the error.
pub message: String,
/// An explanatory message of the error. (for debug)
///
/// This message comes from [`Failure<T>`].
/// The concrete error type, comes from [`Failure<T>`].
#[serde(skip)]
pub debug_message: Option<String>,
pub error: Option<Arc<dyn Any + Send + Sync>>,
/// Where the error occurred.
#[serde(skip_serializing_if = "Vec::is_empty", default)]
pub locations: Vec<Pos>,
@ -44,21 +45,53 @@ fn error_extensions_is_empty(values: &Option<ErrorExtensionValues>) -> bool {
values.as_ref().map_or(true, |values| values.0.is_empty())
}
impl Debug for ServerError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("ServerError")
.field("message", &self.message)
.field("locations", &self.locations)
.field("path", &self.path)
.field("extensions", &self.extensions)
.finish()
}
}
impl PartialEq for ServerError {
fn eq(&self, other: &Self) -> bool {
self.message.eq(&other.message)
&& self.locations.eq(&other.locations)
&& self.path.eq(&other.path)
&& self.extensions.eq(&other.extensions)
}
}
impl ServerError {
/// Create a new server error with the message.
pub fn new(message: impl Into<String>, pos: Option<Pos>) -> Self {
Self {
message: message.into(),
debug_message: None,
error: None,
locations: pos.map(|pos| vec![pos]).unwrap_or_default(),
path: Vec::new(),
extensions: None,
}
}
/// Returns `debug_message` if it is `Some`, otherwise returns `message`.
pub fn debug_message(&self) -> &str {
self.debug_message.as_deref().unwrap_or(&self.message)
/// Downcast the error object by reference.
///
/// # Examples
///
/// ```rust
/// use std::string::FromUtf8Error;
/// use async_graphql::{Failure, Error, ServerError, Pos};
///
/// let bytes = vec![0, 159];
/// let err: Error = String::from_utf8(bytes).map_err(Failure).unwrap_err().into();
/// let server_err: ServerError = err.into_server_error(Pos { line: 1, column: 1 });
/// assert!(server_err.concrete_error::<FromUtf8Error>().is_some());
/// ```
pub fn concrete_error<T: Any + Send + Sync>(&self) -> Option<&T> {
self.error.as_ref().map(|err| err.downcast_ref()).flatten()
}
#[doc(hidden)]
@ -83,7 +116,7 @@ impl From<parser::Error> for ServerError {
fn from(e: parser::Error) -> Self {
Self {
message: e.to_string(),
debug_message: None,
error: None,
locations: e.positions().collect(),
path: Vec::new(),
extensions: None,
@ -172,24 +205,39 @@ impl<T: InputType, E: Display> From<E> for InputValueError<T> {
pub type InputValueResult<T> = Result<T, InputValueError<T>>;
/// An error with a message and optional extensions.
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
#[derive(Clone, Serialize)]
pub struct Error {
/// The error message.
pub message: String,
/// The debug error message.
/// The concrete error type, comes from [`Failure<T>`].
#[serde(skip)]
pub debug_message: Option<String>,
pub error: Option<Arc<dyn Any + Send + Sync>>,
/// Extensions to the error.
#[serde(skip_serializing_if = "error_extensions_is_empty")]
pub extensions: Option<ErrorExtensionValues>,
}
impl Debug for Error {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("Error")
.field("message", &self.message)
.field("extensions", &self.extensions)
.finish()
}
}
impl PartialEq for Error {
fn eq(&self, other: &Self) -> bool {
self.message.eq(&other.message) && self.extensions.eq(&other.extensions)
}
}
impl Error {
/// Create an error from the given error message.
pub fn new(message: impl Into<String>) -> Self {
Self {
message: message.into(),
debug_message: None,
error: None,
extensions: None,
}
}
@ -199,7 +247,7 @@ impl Error {
pub fn into_server_error(self, pos: Pos) -> ServerError {
ServerError {
message: self.message,
debug_message: self.debug_message,
error: self.error,
locations: vec![pos],
path: Vec::new(),
extensions: self.extensions,
@ -207,21 +255,21 @@ impl Error {
}
}
impl<T: Display> From<T> for Error {
impl<T: Display + Send + Sync + 'static> From<T> for Error {
fn from(e: T) -> Self {
Self {
message: e.to_string(),
debug_message: None,
error: None,
extensions: None,
}
}
}
impl<T: Display + Debug> From<Failure<T>> for Error {
fn from(err: Failure<T>) -> Self {
impl<T: StdError + Send + Sync + 'static> From<Failure<T>> for Error {
fn from(e: Failure<T>) -> Self {
Self {
message: format!("{}", err.0),
debug_message: Some(format!("{:?}", err.0)),
message: e.0.to_string(),
error: Some(Arc::new(e.0)),
extensions: None,
}
}
@ -307,7 +355,7 @@ pub trait ErrorExtensions: Sized {
let Error {
message,
debug_message,
error,
extensions,
} = self.extend();
@ -316,7 +364,7 @@ pub trait ErrorExtensions: Sized {
Error {
message,
debug_message,
error,
extensions: Some(extensions),
}
}
@ -330,17 +378,17 @@ impl ErrorExtensions for Error {
// implementing for &E instead of E gives the user the possibility to implement for E which does
// not conflict with this implementation acting as a fallback.
impl<E: std::fmt::Display> ErrorExtensions for &E {
impl<E: Display> ErrorExtensions for &E {
fn extend(self) -> Error {
Error {
message: self.to_string(),
debug_message: None,
error: None,
extensions: None,
}
}
}
impl<T: Display + Debug> ErrorExtensions for Failure<T> {
impl<T: StdError + Send + Sync + 'static> ErrorExtensions for Failure<T> {
fn extend(self) -> Error {
Error::from(self)
}
@ -381,19 +429,17 @@ where
}
}
/// An error type contains `T` that implements `Display` and `Debug`.
///
/// This type can solve the problem described in [#671](https://github.com/async-graphql/async-graphql/issues/671).
/// A wrapper around a dynamic error type.
#[derive(Debug)]
pub struct Failure<T>(pub T);
impl<T: Display + Debug> From<T> for Failure<T> {
impl<T: Any + Send + Sync> From<T> for Failure<T> {
fn from(err: T) -> Self {
Self(err)
}
}
impl<T: Display + Debug> Failure<T> {
impl<T: Any + Send + Sync> Failure<T> {
/// Create a new failure.
#[inline]
pub fn new(err: T) -> Self {

View File

@ -851,7 +851,7 @@ impl From<RuleError> for ServerError {
fn from(e: RuleError) -> Self {
Self {
message: e.message,
debug_message: None,
error: None,
locations: e.locations,
path: Vec::new(),
extensions: e.extensions,

View File

@ -1,5 +1,4 @@
use async_graphql::*;
use std::fmt::{self, Display, Formatter};
#[tokio::test]
pub async fn test_error_extensions() {
@ -79,13 +78,13 @@ pub async fn test_error_extensions() {
#[tokio::test]
pub async fn test_failure() {
#[derive(Debug)]
struct MyError;
#[derive(thiserror::Error, Debug, PartialEq)]
enum MyError {
#[error("error1")]
Error1,
impl Display for MyError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "my error")
}
#[error("error2")]
Error2,
}
struct Query;
@ -93,23 +92,23 @@ pub async fn test_failure() {
#[Object]
impl Query {
async fn failure(&self) -> Result<i32> {
Err(Failure(MyError).into())
Err(Failure(MyError::Error1).into())
}
async fn failure2(&self) -> Result<i32> {
Err(Failure(MyError))?;
Err(Failure(MyError::Error2))?;
Ok(1)
}
async fn failure3(&self) -> Result<i32> {
Err(Failure(MyError)
Err(Failure(MyError::Error1)
.extend_with(|_, values| values.set("a", 1))
.extend_with(|_, values| values.set("b", 2)))?;
Ok(1)
}
async fn failure4(&self) -> Result<i32> {
Err(Failure(MyError))
Err(Failure(MyError::Error2))
.extend_err(|_, values| values.set("a", 1))
.extend_err(|_, values| values.set("b", 2))?;
Ok(1)
@ -117,73 +116,53 @@ pub async fn test_failure() {
}
let schema = Schema::new(Query, EmptyMutation, EmptySubscription);
let err = schema
.execute("{ failure }")
.await
.into_result()
.unwrap_err()
.remove(0);
assert_eq!(err.concrete_error::<MyError>().unwrap(), &MyError::Error1);
let err = schema
.execute("{ failure2 }")
.await
.into_result()
.unwrap_err()
.remove(0);
assert_eq!(err.concrete_error::<MyError>().unwrap(), &MyError::Error2);
let err = schema
.execute("{ failure3 }")
.await
.into_result()
.unwrap_err()
.remove(0);
assert_eq!(err.concrete_error::<MyError>().unwrap(), &MyError::Error1);
assert_eq!(
schema
.execute("{ failure }")
.await
.into_result()
.unwrap_err(),
vec![ServerError {
message: "my error".to_string(),
debug_message: Some("MyError".to_string()),
locations: vec![Pos { line: 1, column: 3 }],
path: vec![PathSegment::Field("failure".to_string())],
extensions: None
}]
err.extensions,
Some({
let mut values = ErrorExtensionValues::default();
values.set("a", 1);
values.set("b", 2);
values
})
);
let err = schema
.execute("{ failure4 }")
.await
.into_result()
.unwrap_err()
.remove(0);
assert_eq!(err.concrete_error::<MyError>().unwrap(), &MyError::Error2);
assert_eq!(
schema
.execute("{ failure2 }")
.await
.into_result()
.unwrap_err(),
vec![ServerError {
message: "my error".to_string(),
debug_message: Some("MyError".to_string()),
locations: vec![Pos { line: 1, column: 3 }],
path: vec![PathSegment::Field("failure2".to_string())],
extensions: None
}]
);
assert_eq!(
schema
.execute("{ failure3 }")
.await
.into_result()
.unwrap_err(),
vec![ServerError {
message: "my error".to_string(),
debug_message: Some("MyError".to_string()),
locations: vec![Pos { line: 1, column: 3 }],
path: vec![PathSegment::Field("failure3".to_string())],
extensions: Some({
let mut values = ErrorExtensionValues::default();
values.set("a", 1);
values.set("b", 2);
values
})
}]
);
assert_eq!(
schema
.execute("{ failure4 }")
.await
.into_result()
.unwrap_err(),
vec![ServerError {
message: "my error".to_string(),
debug_message: Some("MyError".to_string()),
locations: vec![Pos { line: 1, column: 3 }],
path: vec![PathSegment::Field("failure4".to_string())],
extensions: Some({
let mut values = ErrorExtensionValues::default();
values.set("a", 1);
values.set("b", 2);
values
})
}]
err.extensions,
Some({
let mut values = ErrorExtensionValues::default();
values.set("a", 1);
values.set("b", 2);
values
})
);
}

View File

@ -242,7 +242,7 @@ pub async fn test_find_entity_with_context() {
schema.execute(query).await.into_result().unwrap_err(),
vec![ServerError {
message: "Not found".to_string(),
debug_message: None,
error: None,
locations: vec![Pos {
line: 2,
column: 13

View File

@ -85,7 +85,7 @@ pub async fn test_field_features() {
vec![ServerError {
message: r#"Unknown field "valueAbc" on type "QueryRoot". Did you mean "value"?"#
.to_owned(),
debug_message: None,
error: None,
locations: vec![Pos { column: 3, line: 1 }],
path: Vec::new(),
extensions: None,
@ -114,7 +114,7 @@ pub async fn test_field_features() {
vec![ServerError {
message: r#"Unknown field "valueAbc" on type "MyObj". Did you mean "value"?"#
.to_owned(),
debug_message: None,
error: None,
locations: vec![Pos { column: 9, line: 1 }],
path: Vec::new(),
extensions: None,
@ -150,7 +150,7 @@ pub async fn test_field_features() {
.errors,
vec![ServerError {
message: r#"Unknown field "valuesAbc" on type "SubscriptionRoot". Did you mean "values", "valuesBson"?"#.to_owned(),
debug_message: None,
error: None,
locations: vec![Pos {
column: 16,
line: 1

View File

@ -99,7 +99,7 @@ pub async fn test_guard_simple_rule() {
.unwrap_err(),
vec![ServerError {
message: "Forbidden".to_string(),
debug_message: None,
error: None,
locations: vec![Pos { line: 1, column: 3 }],
path: vec![PathSegment::Field("value".to_owned())],
extensions: None,
@ -128,7 +128,7 @@ pub async fn test_guard_simple_rule() {
.errors,
vec![ServerError {
message: "Forbidden".to_string(),
debug_message: None,
error: None,
locations: vec![Pos {
line: 1,
column: 16
@ -178,7 +178,7 @@ pub async fn test_guard_and_operator() {
.unwrap_err(),
vec![ServerError {
message: "Forbidden".to_string(),
debug_message: None,
error: None,
locations: vec![Pos { line: 1, column: 3 }],
path: vec![PathSegment::Field("value".to_owned())],
extensions: None,
@ -198,7 +198,7 @@ pub async fn test_guard_and_operator() {
.unwrap_err(),
vec![ServerError {
message: "Forbidden".to_string(),
debug_message: None,
error: None,
locations: vec![Pos { line: 1, column: 3 }],
path: vec![PathSegment::Field("value".to_owned())],
extensions: None,
@ -218,7 +218,7 @@ pub async fn test_guard_and_operator() {
.unwrap_err(),
vec![ServerError {
message: "Forbidden".to_string(),
debug_message: None,
error: None,
locations: vec![Pos { line: 1, column: 3 }],
path: vec![PathSegment::Field("value".to_owned())],
extensions: None,
@ -288,7 +288,7 @@ pub async fn test_guard_or_operator() {
.unwrap_err(),
vec![ServerError {
message: "Forbidden".to_string(),
debug_message: None,
error: None,
locations: vec![Pos { line: 1, column: 3 }],
path: vec![PathSegment::Field("value".to_owned())],
extensions: None,
@ -338,7 +338,7 @@ pub async fn test_guard_chain_operator() {
.unwrap_err(),
vec![ServerError {
message: "Forbidden".to_string(),
debug_message: None,
error: None,
locations: vec![Pos { line: 1, column: 3 }],
path: vec![PathSegment::Field("value".to_owned())],
extensions: None,
@ -359,7 +359,7 @@ pub async fn test_guard_chain_operator() {
.unwrap_err(),
vec![ServerError {
message: "Forbidden".to_string(),
debug_message: None,
error: None,
locations: vec![Pos { line: 1, column: 3 }],
path: vec![PathSegment::Field("value".to_owned())],
extensions: None,
@ -380,7 +380,7 @@ pub async fn test_guard_chain_operator() {
.unwrap_err(),
vec![ServerError {
message: "Forbidden".to_string(),
debug_message: None,
error: None,
locations: vec![Pos { line: 1, column: 3 }],
path: vec![PathSegment::Field("value".to_owned())],
extensions: None,
@ -401,7 +401,7 @@ pub async fn test_guard_chain_operator() {
.unwrap_err(),
vec![ServerError {
message: "Forbidden".to_string(),
debug_message: None,
error: None,
locations: vec![Pos { line: 1, column: 3 }],
path: vec![PathSegment::Field("value".to_owned())],
extensions: None,
@ -493,7 +493,7 @@ pub async fn test_guard_race_operator() {
.unwrap_err(),
vec![ServerError {
message: "Forbidden".to_string(),
debug_message: None,
error: None,
locations: vec![Pos { line: 1, column: 3 }],
path: vec![PathSegment::Field("value".to_owned())],
extensions: None,
@ -549,7 +549,7 @@ pub async fn test_guard_use_params() {
.unwrap_err(),
vec![ServerError {
message: "Forbidden".to_string(),
debug_message: None,
error: None,
locations: vec![Pos { line: 1, column: 3 }],
path: vec![PathSegment::Field("get".to_owned())],
extensions: None,

View File

@ -67,7 +67,7 @@ pub async fn test_input_validator_string_min_length() {
.expect_err(&should_fail_msg),
vec![ServerError {
message: field_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 17
@ -85,7 +85,7 @@ pub async fn test_input_validator_string_min_length() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: object_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 14
@ -179,7 +179,7 @@ pub async fn test_input_validator_string_max_length() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: field_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 17
@ -197,7 +197,7 @@ pub async fn test_input_validator_string_max_length() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: object_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 14
@ -290,7 +290,7 @@ pub async fn test_input_validator_chars_min_length() {
.expect_err(&should_fail_msg),
vec![ServerError {
message: field_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 17
@ -308,7 +308,7 @@ pub async fn test_input_validator_chars_min_length() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: object_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 14
@ -403,7 +403,7 @@ pub async fn test_input_validator_chars_max_length() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: field_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 17
@ -421,7 +421,7 @@ pub async fn test_input_validator_chars_max_length() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: object_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 14
@ -542,7 +542,7 @@ pub async fn test_input_validator_string_email() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: field_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 17
@ -561,7 +561,7 @@ pub async fn test_input_validator_string_email() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: object_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 14
@ -692,7 +692,7 @@ pub async fn test_input_validator_string_mac() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: field_error_msg.clone(),
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 17
@ -711,7 +711,7 @@ pub async fn test_input_validator_string_mac() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: object_error_msg.clone(),
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 14
@ -729,7 +729,7 @@ pub async fn test_input_validator_string_mac() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: field_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 17
@ -748,7 +748,7 @@ pub async fn test_input_validator_string_mac() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: object_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 14
@ -806,7 +806,7 @@ pub async fn test_input_validator_string_mac() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: field_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 17
@ -825,7 +825,7 @@ pub async fn test_input_validator_string_mac() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: object_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 14
@ -867,7 +867,7 @@ pub async fn test_input_validator_string_mac() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: field_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 17
@ -886,7 +886,7 @@ pub async fn test_input_validator_string_mac() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: object_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 14
@ -947,7 +947,7 @@ pub async fn test_input_validator_int_range() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: field_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 17
@ -965,7 +965,7 @@ pub async fn test_input_validator_int_range() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: object_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 14
@ -1054,7 +1054,7 @@ pub async fn test_input_validator_int_less_than() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: field_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 17
@ -1072,7 +1072,7 @@ pub async fn test_input_validator_int_less_than() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: object_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 14
@ -1163,7 +1163,7 @@ pub async fn test_input_validator_int_greater_than() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: field_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 17
@ -1181,7 +1181,7 @@ pub async fn test_input_validator_int_greater_than() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: object_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 14
@ -1265,7 +1265,7 @@ pub async fn test_input_validator_int_nonzero() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: field_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 17
@ -1283,7 +1283,7 @@ pub async fn test_input_validator_int_nonzero() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: object_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 14
@ -1371,7 +1371,7 @@ pub async fn test_input_validator_int_equal() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: field_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 17
@ -1389,7 +1389,7 @@ pub async fn test_input_validator_int_equal() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: object_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 14
@ -1489,7 +1489,7 @@ pub async fn test_input_validator_list_max_length() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: field_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 17
@ -1507,7 +1507,7 @@ pub async fn test_input_validator_list_max_length() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: object_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 14
@ -1607,7 +1607,7 @@ pub async fn test_input_validator_list_min_length() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: field_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 17
@ -1625,7 +1625,7 @@ pub async fn test_input_validator_list_min_length() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: object_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 14
@ -1733,7 +1733,7 @@ pub async fn test_input_validator_operator_or() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: field_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 17
@ -1751,7 +1751,7 @@ pub async fn test_input_validator_operator_or() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: object_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 14
@ -1852,7 +1852,7 @@ pub async fn test_input_validator_operator_and() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: field_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 17
@ -1870,7 +1870,7 @@ pub async fn test_input_validator_operator_and() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: object_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 14
@ -1974,7 +1974,7 @@ pub async fn test_input_validator_variable() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: field_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 37
@ -1992,7 +1992,7 @@ pub async fn test_input_validator_variable() {
.expect_err(&should_fail_msg[..]),
vec![ServerError {
message: object_error_msg,
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 34
@ -2079,7 +2079,7 @@ pub async fn test_custom_input_validator_with_extensions() {
.expect_err(should_fail_msg),
vec![ServerError {
message: field_error_msg.into(),
debug_message: None,
error: None,
locations: vec!(Pos {
line: 1,
column: 17

View File

@ -18,7 +18,7 @@ pub async fn test_input_value_custom_error() {
vec![ServerError {
message: "Failed to parse \"Int\": Only integers from -128 to 127 are accepted."
.to_owned(),
debug_message: None,
error: None,
locations: vec![Pos {
line: 1,
column: 14,

View File

@ -167,7 +167,7 @@ pub async fn test_array_type() {
vec![ServerError {
message: r#"Failed to parse "[Int!]": Expected input type "[Int; 6]", found [Int; 5]."#
.to_owned(),
debug_message: None,
error: None,
locations: vec![Pos {
line: 1,
column: 22,

View File

@ -34,14 +34,14 @@ pub async fn test_fieldresult() {
errors: vec![
ServerError {
message: "TestError".to_string(),
debug_message: None,
error: None,
locations: vec![Pos { line: 1, column: 3 }],
path: vec![PathSegment::Field("error1".to_owned())],
extensions: None,
},
ServerError {
message: "TestError".to_string(),
debug_message: None,
error: None,
locations: vec![Pos {
line: 1,
column: 19,
@ -62,7 +62,7 @@ pub async fn test_fieldresult() {
.unwrap_err(),
vec![ServerError {
message: "TestError".to_string(),
debug_message: None,
error: None,
locations: vec![Pos { line: 1, column: 3 }],
path: vec![PathSegment::Field("optError".to_owned())],
extensions: None,
@ -77,7 +77,7 @@ pub async fn test_fieldresult() {
.unwrap_err(),
vec![ServerError {
message: "TestError".to_string(),
debug_message: None,
error: None,
locations: vec![Pos { line: 1, column: 3 }],
path: vec![
PathSegment::Field("vecError".to_owned()),
@ -192,7 +192,7 @@ pub async fn test_error_propagation() {
cache_control: Default::default(),
errors: vec![ServerError {
message: "myerror".to_string(),
debug_message: None,
error: None,
locations: vec![Pos {
line: 1,
column: 20,
@ -220,7 +220,7 @@ pub async fn test_error_propagation() {
cache_control: Default::default(),
errors: vec![ServerError {
message: "myerror".to_string(),
debug_message: None,
error: None,
locations: vec![Pos {
line: 1,
column: 23,
@ -244,7 +244,7 @@ pub async fn test_error_propagation() {
cache_control: Default::default(),
errors: vec![ServerError {
message: "myerror".to_string(),
debug_message: None,
error: None,
locations: vec![Pos {
line: 1,
column: 23,
@ -274,7 +274,7 @@ pub async fn test_error_propagation() {
cache_control: Default::default(),
errors: vec![ServerError {
message: "myerror".to_string(),
debug_message: None,
error: None,
locations: vec![Pos {
line: 1,
column: 23,

View File

@ -345,7 +345,7 @@ pub async fn test_subscription_error() {
stream.next().await,
Some(Err(vec![ServerError {
message: "TestError".to_string(),
debug_message: None,
error: None,
locations: vec![Pos {
line: 1,
column: 25
@ -391,7 +391,7 @@ pub async fn test_subscription_fieldresult() {
cache_control: Default::default(),
errors: vec![ServerError {
message: "StreamErr".to_string(),
debug_message: None,
error: None,
locations: vec![Pos {
line: 1,
column: 16