Add entity lookup support for MergedObject.
Add some GraphQL specification constraints for all derived macros. Use `Registry::create_dummy_type` to create a merged type.
This commit is contained in:
parent
b5e602342d
commit
e3d693da28
|
@ -83,6 +83,8 @@ pub struct SimpleObject {
|
|||
#[darling(default)]
|
||||
pub internal: bool,
|
||||
#[darling(default)]
|
||||
pub dummy: bool,
|
||||
#[darling(default)]
|
||||
pub name: Option<String>,
|
||||
#[darling(default)]
|
||||
pub rename_fields: Option<RenameRule>,
|
||||
|
|
|
@ -111,6 +111,14 @@ pub fn generate(enum_args: &args::Enum) -> GeneratorResult<TokenStream> {
|
|||
None
|
||||
};
|
||||
|
||||
if schema_enum_items.is_empty() {
|
||||
return Err(Error::new_spanned(
|
||||
&ident,
|
||||
"An GraphQL Enum type must define one or more unique enum values.",
|
||||
)
|
||||
.into());
|
||||
}
|
||||
|
||||
let expanded = quote! {
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #crate_name::resolver_utils::EnumType for #ident {
|
||||
|
|
|
@ -67,9 +67,9 @@ pub fn generate(object_args: &args::InputObject) -> GeneratorResult<TokenStream>
|
|||
schema_fields.push(quote! {
|
||||
#crate_name::static_assertions::assert_impl_one!(#ty: #crate_name::InputObjectType);
|
||||
#ty::create_type_info(registry);
|
||||
if let Some(#crate_name::registry::MetaType::InputObject { input_fields, .. }) =
|
||||
registry.types.get(&*<#ty as #crate_name::Type>::type_name()) {
|
||||
fields.extend(::std::clone::Clone::clone(input_fields));
|
||||
if let #crate_name::registry::MetaType::InputObject { input_fields, .. } =
|
||||
registry.create_dummy_type::<#ty>() {
|
||||
fields.extend(input_fields);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -151,6 +151,14 @@ pub fn generate(object_args: &args::InputObject) -> GeneratorResult<TokenStream>
|
|||
})
|
||||
}
|
||||
|
||||
if get_fields.is_empty() {
|
||||
return Err(Error::new_spanned(
|
||||
&ident,
|
||||
"An GraphQL Input Object type must define one or more input fields.",
|
||||
)
|
||||
.into());
|
||||
}
|
||||
|
||||
let expanded = quote! {
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #crate_name::Type for #ident {
|
||||
|
|
|
@ -121,6 +121,14 @@ pub fn generate(interface_args: &args::Interface) -> GeneratorResult<TokenStream
|
|||
let mut schema_fields = Vec::new();
|
||||
let mut resolvers = Vec::new();
|
||||
|
||||
if interface_args.fields.is_empty() {
|
||||
return Err(Error::new_spanned(
|
||||
&ident,
|
||||
"An GraphQL Interface type must define one or more fields.",
|
||||
)
|
||||
.into());
|
||||
}
|
||||
|
||||
for InterfaceField {
|
||||
name,
|
||||
method,
|
||||
|
|
|
@ -62,18 +62,16 @@ pub fn generate(object_args: &args::MergedObject) -> GeneratorResult<TokenStream
|
|||
|
||||
fn create_type_info(registry: &mut #crate_name::registry::Registry) -> ::std::string::String {
|
||||
registry.create_type::<Self, _>(|registry| {
|
||||
#merged_type::create_type_info(registry);
|
||||
|
||||
let mut fields = ::std::default::Default::default();
|
||||
let mut cache_control = ::std::default::Default::default();
|
||||
|
||||
if let ::std::option::Option::Some(#crate_name::registry::MetaType::Object {
|
||||
if let #crate_name::registry::MetaType::Object {
|
||||
fields: obj_fields,
|
||||
cache_control: obj_cache_control,
|
||||
..
|
||||
}) = registry.types.get(&*#merged_type::type_name()) {
|
||||
fields = ::std::clone::Clone::clone(obj_fields);
|
||||
cache_control = *obj_cache_control;
|
||||
} = registry.create_dummy_type::<#merged_type>() {
|
||||
fields = obj_fields;
|
||||
cache_control = obj_cache_control;
|
||||
}
|
||||
|
||||
#crate_name::registry::MetaType::Object {
|
||||
|
@ -94,6 +92,10 @@ pub fn generate(object_args: &args::MergedObject) -> GeneratorResult<TokenStream
|
|||
async fn resolve_field(&self, ctx: &#crate_name::Context<'_>) -> #crate_name::ServerResult<::std::option::Option<#crate_name::Value>> {
|
||||
#create_merged_obj.resolve_field(ctx).await
|
||||
}
|
||||
|
||||
async fn find_entity(&self, ctx: &#crate_name::Context<'_>, params: &#crate_name::Value) -> #crate_name::ServerResult<::std::option::Option<#crate_name::Value>> {
|
||||
#create_merged_obj.find_entity(ctx, params).await
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
|
|
|
@ -53,15 +53,13 @@ pub fn generate(object_args: &args::MergedSubscription) -> GeneratorResult<Token
|
|||
|
||||
fn create_type_info(registry: &mut #crate_name::registry::Registry) -> ::std::string::String {
|
||||
registry.create_type::<Self, _>(|registry| {
|
||||
#merged_type::create_type_info(registry);
|
||||
|
||||
let mut fields = ::std::default::Default::default();
|
||||
|
||||
if let ::std::option::Option::Some(#crate_name::registry::MetaType::Object {
|
||||
if let #crate_name::registry::MetaType::Object {
|
||||
fields: obj_fields,
|
||||
..
|
||||
}) = registry.types.get(&*#merged_type::type_name()) {
|
||||
fields = ::std::clone::Clone::clone(obj_fields);
|
||||
} = registry.create_dummy_type::<#merged_type>() {
|
||||
fields = obj_fields;
|
||||
}
|
||||
|
||||
#crate_name::registry::MetaType::Object {
|
||||
|
|
|
@ -471,6 +471,14 @@ pub fn generate(
|
|||
find_entities.sort_by(|(a, _), (b, _)| b.cmp(a));
|
||||
let find_entities_iter = find_entities.iter().map(|(_, code)| code);
|
||||
|
||||
if resolvers.is_empty() && create_entity_types.is_empty() {
|
||||
return Err(Error::new_spanned(
|
||||
&self_ty,
|
||||
"An GraphQL Object type must define one or more fields.",
|
||||
)
|
||||
.into());
|
||||
}
|
||||
|
||||
let expanded = quote! {
|
||||
#item_impl
|
||||
|
||||
|
|
|
@ -129,6 +129,14 @@ pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult<TokenStream
|
|||
});
|
||||
}
|
||||
|
||||
if !object_args.dummy && resolvers.is_empty() {
|
||||
return Err(Error::new_spanned(
|
||||
&ident,
|
||||
"An GraphQL Object type must define one or more fields.",
|
||||
)
|
||||
.into());
|
||||
}
|
||||
|
||||
let cache_control = {
|
||||
let public = object_args.cache_control.is_public();
|
||||
let max_age = object_args.cache_control.max_age;
|
||||
|
@ -181,7 +189,6 @@ pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult<TokenStream
|
|||
#[allow(clippy::all, clippy::pedantic)]
|
||||
#[#crate_name::async_trait::async_trait]
|
||||
impl #generics #crate_name::OutputValueType for #ident #generics #where_clause {
|
||||
|
||||
async fn resolve(&self, ctx: &#crate_name::ContextSelectionSet<'_>, _field: &#crate_name::Positioned<#crate_name::parser::types::Field>) -> #crate_name::ServerResult<#crate_name::Value> {
|
||||
#crate_name::resolver_utils::resolve_container(ctx, self).await
|
||||
}
|
||||
|
|
|
@ -364,6 +364,14 @@ pub fn generate(
|
|||
}
|
||||
}
|
||||
|
||||
if create_stream.is_empty() {
|
||||
return Err(Error::new_spanned(
|
||||
&self_ty,
|
||||
"An GraphQL Object type must define one or more fields.",
|
||||
)
|
||||
.into());
|
||||
}
|
||||
|
||||
let expanded = quote! {
|
||||
#item_impl
|
||||
|
||||
|
|
|
@ -106,19 +106,18 @@ pub fn generate(union_args: &args::Union) -> GeneratorResult<TokenStream> {
|
|||
});
|
||||
}
|
||||
|
||||
registry_types.push(quote! {
|
||||
<#p as #crate_name::Type>::create_type_info(registry);
|
||||
});
|
||||
|
||||
if !variant.flatten {
|
||||
registry_types.push(quote! {
|
||||
<#p as #crate_name::Type>::create_type_info(registry);
|
||||
});
|
||||
possible_types.push(quote! {
|
||||
possible_types.insert(<#p as #crate_name::Type>::type_name().into_owned());
|
||||
});
|
||||
} else {
|
||||
possible_types.push(quote! {
|
||||
if let Some(#crate_name::registry::MetaType::Union { possible_types: possible_types2, .. }) =
|
||||
registry.types.get(&*<#p as #crate_name::Type>::type_name()) {
|
||||
possible_types.extend(::std::clone::Clone::clone(possible_types2));
|
||||
if let #crate_name::registry::MetaType::Union { possible_types: possible_types2, .. } =
|
||||
registry.create_dummy_type::<#p>() {
|
||||
possible_types.extend(possible_types2);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -141,6 +140,14 @@ pub fn generate(union_args: &args::Union) -> GeneratorResult<TokenStream> {
|
|||
}
|
||||
}
|
||||
|
||||
if possible_types.is_empty() {
|
||||
return Err(Error::new_spanned(
|
||||
&ident,
|
||||
"A GraphQL Union type must include one or more unique member types.",
|
||||
)
|
||||
.into());
|
||||
}
|
||||
|
||||
let expanded = quote! {
|
||||
#(#type_into_impls)*
|
||||
|
||||
|
|
|
@ -142,8 +142,13 @@ async fn upload() -> Result<()> {
|
|||
|
||||
async_std::task::spawn(async move {
|
||||
struct QueryRoot;
|
||||
|
||||
#[Object]
|
||||
impl QueryRoot {}
|
||||
impl QueryRoot {
|
||||
async fn value(&self) -> i32 {
|
||||
10
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, SimpleObject)]
|
||||
pub struct FileInfo {
|
||||
|
|
|
@ -17,7 +17,12 @@ use warp::{Filter, Rejection, Reply};
|
|||
/// struct QueryRoot;
|
||||
///
|
||||
/// #[Object]
|
||||
/// impl QueryRoot {}
|
||||
/// impl QueryRoot {
|
||||
/// async fn value(&self) -> i32 {
|
||||
/// // An GraphQL Object type must define one or more fields.
|
||||
/// 100
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// struct SubscriptionRoot;
|
||||
///
|
||||
|
|
|
@ -254,6 +254,7 @@ pub struct MetaDirective {
|
|||
pub args: IndexMap<&'static str, MetaInputValue>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Registry {
|
||||
pub types: IndexMap<String, MetaType>,
|
||||
pub directives: HashMap<String, MetaDirective>,
|
||||
|
@ -288,6 +289,18 @@ impl Registry {
|
|||
T::qualified_type_name()
|
||||
}
|
||||
|
||||
pub fn create_dummy_type<T: crate::Type>(&mut self) -> MetaType {
|
||||
let mut dummy_registry = Registry::default();
|
||||
T::create_type_info(&mut dummy_registry);
|
||||
if let Some(ty) = dummy_registry.types.remove(&*T::type_name()) {
|
||||
self.types.extend(dummy_registry.types);
|
||||
self.implements.extend(dummy_registry.implements);
|
||||
ty
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_directive(&mut self, directive: MetaDirective) {
|
||||
self.directives
|
||||
.insert(directive.name.to_string(), directive);
|
||||
|
|
|
@ -55,6 +55,10 @@ impl<T: ContainerType + Send + Sync> ContainerType for &T {
|
|||
async fn resolve_field(&self, ctx: &Context<'_>) -> ServerResult<Option<Value>> {
|
||||
T::resolve_field(*self, ctx).await
|
||||
}
|
||||
|
||||
async fn find_entity(&self, ctx: &Context<'_>, params: &Value) -> ServerResult<Option<Value>> {
|
||||
T::find_entity(*self, ctx, params).await
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolve an container by executing each of the fields concurrently.
|
||||
|
|
|
@ -70,9 +70,15 @@ impl<Query, Mutation, Subscription> SchemaBuilder<Query, Mutation, Subscription>
|
|||
/// ```rust
|
||||
/// use async_graphql::*;
|
||||
///
|
||||
/// #[derive(SimpleObject)]
|
||||
/// struct Query;
|
||||
///
|
||||
/// #[Object]
|
||||
/// impl Query {
|
||||
/// async fn value(&self) -> i32 {
|
||||
/// 100
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// let schema = Schema::build(Query, EmptyMutation,EmptySubscription)
|
||||
/// .extension(extensions::Logger)
|
||||
/// .finish();
|
||||
|
|
|
@ -52,11 +52,10 @@ where
|
|||
|
||||
fn create_type_info(registry: &mut registry::Registry) -> String {
|
||||
registry.create_type::<Self, _>(|registry| {
|
||||
E::create_type_info(registry);
|
||||
let additional_fields = if let Some(registry::MetaType::Object { fields, .. }) =
|
||||
registry.types.get(E::type_name().as_ref())
|
||||
let additional_fields = if let registry::MetaType::Object { fields, .. } =
|
||||
registry.create_dummy_type::<E>()
|
||||
{
|
||||
fields.clone()
|
||||
fields
|
||||
} else {
|
||||
unreachable!()
|
||||
};
|
||||
|
|
|
@ -16,7 +16,7 @@ pub use page_info::PageInfo;
|
|||
|
||||
/// Empty additional fields
|
||||
#[derive(SimpleObject)]
|
||||
#[graphql(internal)]
|
||||
#[graphql(internal, dummy)]
|
||||
pub struct EmptyFields;
|
||||
|
||||
/// Parses the parameters and executes the query.
|
||||
|
|
|
@ -19,7 +19,12 @@ use crate::{
|
|||
/// struct QueryRoot;
|
||||
///
|
||||
/// #[Object]
|
||||
/// impl QueryRoot {}
|
||||
/// impl QueryRoot {
|
||||
/// async fn value(&self) -> i32 {
|
||||
/// // An GraphQL Object type must define one or more fields.
|
||||
/// 100
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// let schema = Schema::new(QueryRoot, EmptyMutation, EmptySubscription);
|
||||
/// ```
|
||||
|
|
|
@ -9,6 +9,7 @@ use crate::{
|
|||
CacheControl, ContainerType, Context, ContextSelectionSet, ObjectType, OutputValueType,
|
||||
Positioned, ServerResult, SimpleObject, Type, Value,
|
||||
};
|
||||
use async_graphql_value::ConstValue;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct MergedObject<A, B>(pub A, pub B);
|
||||
|
@ -23,25 +24,23 @@ impl<A: Type, B: Type> Type for MergedObject<A, B> {
|
|||
let mut fields = IndexMap::new();
|
||||
let mut cc = CacheControl::default();
|
||||
|
||||
A::create_type_info(registry);
|
||||
if let Some(MetaType::Object {
|
||||
if let MetaType::Object {
|
||||
fields: a_fields,
|
||||
cache_control: a_cc,
|
||||
..
|
||||
}) = registry.types.get(&*A::type_name())
|
||||
} = registry.create_dummy_type::<A>()
|
||||
{
|
||||
fields.extend(a_fields.clone());
|
||||
fields.extend(a_fields);
|
||||
cc = cc.merge(&a_cc);
|
||||
}
|
||||
|
||||
B::create_type_info(registry);
|
||||
if let Some(MetaType::Object {
|
||||
if let MetaType::Object {
|
||||
fields: b_fields,
|
||||
cache_control: b_cc,
|
||||
..
|
||||
}) = registry.types.get(&*B::type_name())
|
||||
} = registry.create_dummy_type::<B>()
|
||||
{
|
||||
fields.extend(b_fields.clone());
|
||||
fields.extend(b_fields);
|
||||
cc = cc.merge(&b_cc);
|
||||
}
|
||||
|
||||
|
@ -70,6 +69,18 @@ where
|
|||
Err(err) => Err(err),
|
||||
}
|
||||
}
|
||||
|
||||
async fn find_entity(
|
||||
&self,
|
||||
ctx: &Context<'_>,
|
||||
params: &ConstValue,
|
||||
) -> ServerResult<Option<ConstValue>> {
|
||||
match self.0.find_entity(ctx, params).await {
|
||||
Ok(Some(value)) => Ok(Some(value)),
|
||||
Ok(None) => self.1.find_entity(ctx, params).await,
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
|
@ -96,5 +107,5 @@ where
|
|||
|
||||
#[doc(hidden)]
|
||||
#[derive(SimpleObject, Default)]
|
||||
#[graphql(internal)]
|
||||
#[graphql(internal, dummy)]
|
||||
pub struct MergedObjectTail;
|
||||
|
|
|
@ -185,7 +185,11 @@ pub async fn test_merged_subscription() {
|
|||
struct Query;
|
||||
|
||||
#[Object]
|
||||
impl Query {}
|
||||
impl Query {
|
||||
async fn value(&self) -> i32 {
|
||||
10
|
||||
}
|
||||
}
|
||||
|
||||
let schema = Schema::new(Query, EmptyMutation, Subscription::default());
|
||||
|
||||
|
@ -221,3 +225,68 @@ pub async fn test_merged_subscription() {
|
|||
assert!(stream.next().await.is_none());
|
||||
}
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
pub async fn test_merged_entity() {
|
||||
#[derive(SimpleObject)]
|
||||
struct Fruit {
|
||||
id: ID,
|
||||
name: String,
|
||||
}
|
||||
|
||||
#[derive(SimpleObject)]
|
||||
struct Vegetable {
|
||||
id: ID,
|
||||
name: String,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct FruitQuery;
|
||||
|
||||
#[Object]
|
||||
impl FruitQuery {
|
||||
#[graphql(entity)]
|
||||
async fn get_fruit(&self, id: ID) -> Fruit {
|
||||
Fruit {
|
||||
id,
|
||||
name: "Apple".into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct VegetableQuery;
|
||||
|
||||
#[Object]
|
||||
impl VegetableQuery {
|
||||
#[graphql(entity)]
|
||||
async fn get_vegetable(&self, id: ID) -> Vegetable {
|
||||
Vegetable {
|
||||
id,
|
||||
name: "Carrot".into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(MergedObject, Default)]
|
||||
struct Query(FruitQuery, VegetableQuery);
|
||||
|
||||
let schema = Schema::new(Query::default(), EmptyMutation, EmptySubscription);
|
||||
let query = r#"{
|
||||
_entities(representations: [{__typename: "Fruit", id: "1"}]) {
|
||||
__typename
|
||||
... on Fruit {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
}"#;
|
||||
assert_eq!(
|
||||
schema.execute(query).await.into_result().unwrap().data,
|
||||
value!({
|
||||
"_entities": [
|
||||
{"__typename": "Fruit", "id": "1", "name": "Apple"},
|
||||
]
|
||||
})
|
||||
);
|
||||
}
|
||||
|
|
|
@ -7,9 +7,15 @@ use std::time::Duration;
|
|||
pub async fn test_mutation_execution_order() {
|
||||
type List = Arc<Mutex<Vec<i32>>>;
|
||||
|
||||
#[derive(SimpleObject)]
|
||||
struct QueryRoot;
|
||||
|
||||
#[Object]
|
||||
impl QueryRoot {
|
||||
async fn value(&self) -> i32 {
|
||||
10
|
||||
}
|
||||
}
|
||||
|
||||
struct MutationRoot;
|
||||
|
||||
#[Object]
|
||||
|
@ -38,9 +44,15 @@ pub async fn test_mutation_execution_order() {
|
|||
|
||||
#[async_std::test]
|
||||
pub async fn test_mutation_fragment() {
|
||||
#[derive(SimpleObject)]
|
||||
struct QueryRoot;
|
||||
|
||||
#[Object]
|
||||
impl QueryRoot {
|
||||
async fn value(&self) -> i32 {
|
||||
10
|
||||
}
|
||||
}
|
||||
|
||||
struct MutationRoot;
|
||||
|
||||
#[Object]
|
||||
|
|
|
@ -105,9 +105,15 @@ pub async fn test_input_object() {
|
|||
|
||||
#[async_std::test]
|
||||
pub async fn test_subscription() {
|
||||
#[derive(SimpleObject)]
|
||||
struct Query;
|
||||
|
||||
#[Object]
|
||||
impl Query {
|
||||
async fn value(&self) -> i32 {
|
||||
10
|
||||
}
|
||||
}
|
||||
|
||||
struct Subscription;
|
||||
|
||||
#[Subscription(rename_fields = "SCREAMING_SNAKE_CASE", rename_args = "lowercase")]
|
||||
|
|
|
@ -2,10 +2,17 @@ use async_graphql::*;
|
|||
|
||||
#[async_std::test]
|
||||
pub async fn test_schema_default() {
|
||||
#[derive(SimpleObject, Default)]
|
||||
struct Query;
|
||||
#[derive(Default)]
|
||||
struct QueryRoot;
|
||||
|
||||
type MySchema = Schema<Query, EmptyMutation, EmptySubscription>;
|
||||
#[Object]
|
||||
impl QueryRoot {
|
||||
async fn value(&self) -> i32 {
|
||||
10
|
||||
}
|
||||
}
|
||||
|
||||
type MySchema = Schema<QueryRoot, EmptyMutation, EmptySubscription>;
|
||||
|
||||
let _schema = MySchema::default();
|
||||
}
|
||||
|
|
|
@ -1,19 +1,23 @@
|
|||
use async_graphql::*;
|
||||
use futures_util::stream::{Stream, StreamExt, TryStreamExt};
|
||||
|
||||
struct QueryRoot;
|
||||
|
||||
#[Object]
|
||||
impl QueryRoot {
|
||||
async fn value(&self) -> i32 {
|
||||
10
|
||||
}
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
pub async fn test_subscription() {
|
||||
struct QueryRoot;
|
||||
|
||||
#[derive(SimpleObject)]
|
||||
struct Event {
|
||||
a: i32,
|
||||
b: i32,
|
||||
}
|
||||
|
||||
#[Object]
|
||||
impl QueryRoot {}
|
||||
|
||||
struct SubscriptionRoot;
|
||||
|
||||
#[Subscription]
|
||||
|
@ -60,7 +64,11 @@ pub async fn test_subscription_with_ctx_data() {
|
|||
struct QueryRoot;
|
||||
|
||||
#[Object]
|
||||
impl QueryRoot {}
|
||||
impl QueryRoot {
|
||||
async fn value(&self) -> i32 {
|
||||
10
|
||||
}
|
||||
}
|
||||
|
||||
struct MyObject;
|
||||
|
||||
|
@ -106,7 +114,11 @@ pub async fn test_subscription_with_token() {
|
|||
struct QueryRoot;
|
||||
|
||||
#[Object]
|
||||
impl QueryRoot {}
|
||||
impl QueryRoot {
|
||||
async fn value(&self) -> i32 {
|
||||
10
|
||||
}
|
||||
}
|
||||
|
||||
struct SubscriptionRoot;
|
||||
|
||||
|
@ -150,16 +162,20 @@ pub async fn test_subscription_with_token() {
|
|||
|
||||
#[async_std::test]
|
||||
pub async fn test_subscription_inline_fragment() {
|
||||
struct QueryRoot;
|
||||
|
||||
#[derive(SimpleObject)]
|
||||
struct Event {
|
||||
a: i32,
|
||||
b: i32,
|
||||
}
|
||||
|
||||
struct QueryRoot;
|
||||
|
||||
#[Object]
|
||||
impl QueryRoot {}
|
||||
impl QueryRoot {
|
||||
async fn value(&self) -> i32 {
|
||||
10
|
||||
}
|
||||
}
|
||||
|
||||
struct SubscriptionRoot;
|
||||
|
||||
|
@ -197,8 +213,6 @@ pub async fn test_subscription_inline_fragment() {
|
|||
|
||||
#[async_std::test]
|
||||
pub async fn test_subscription_fragment() {
|
||||
struct QueryRoot;
|
||||
|
||||
#[derive(SimpleObject)]
|
||||
struct Event {
|
||||
a: i32,
|
||||
|
@ -211,9 +225,6 @@ pub async fn test_subscription_fragment() {
|
|||
Event(Event),
|
||||
}
|
||||
|
||||
#[Object]
|
||||
impl QueryRoot {}
|
||||
|
||||
struct SubscriptionRoot;
|
||||
|
||||
#[Subscription]
|
||||
|
@ -252,8 +263,6 @@ pub async fn test_subscription_fragment() {
|
|||
|
||||
#[async_std::test]
|
||||
pub async fn test_subscription_fragment2() {
|
||||
struct QueryRoot;
|
||||
|
||||
#[derive(SimpleObject)]
|
||||
struct Event {
|
||||
a: i32,
|
||||
|
@ -266,9 +275,6 @@ pub async fn test_subscription_fragment2() {
|
|||
Event(Event),
|
||||
}
|
||||
|
||||
#[Object]
|
||||
impl QueryRoot {}
|
||||
|
||||
struct SubscriptionRoot;
|
||||
|
||||
#[Subscription]
|
||||
|
@ -308,8 +314,6 @@ pub async fn test_subscription_fragment2() {
|
|||
|
||||
#[async_std::test]
|
||||
pub async fn test_subscription_error() {
|
||||
struct QueryRoot;
|
||||
|
||||
struct Event {
|
||||
value: i32,
|
||||
}
|
||||
|
@ -325,9 +329,6 @@ pub async fn test_subscription_error() {
|
|||
}
|
||||
}
|
||||
|
||||
#[Object]
|
||||
impl QueryRoot {}
|
||||
|
||||
struct SubscriptionRoot;
|
||||
|
||||
#[Subscription]
|
||||
|
@ -370,11 +371,6 @@ pub async fn test_subscription_error() {
|
|||
|
||||
#[async_std::test]
|
||||
pub async fn test_subscription_fieldresult() {
|
||||
struct QueryRoot;
|
||||
|
||||
#[Object]
|
||||
impl QueryRoot {}
|
||||
|
||||
struct SubscriptionRoot;
|
||||
|
||||
#[Subscription]
|
||||
|
|
|
@ -6,7 +6,11 @@ pub async fn test_subscription_ws_transport() {
|
|||
struct QueryRoot;
|
||||
|
||||
#[Object]
|
||||
impl QueryRoot {}
|
||||
impl QueryRoot {
|
||||
async fn value(&self) -> i32 {
|
||||
10
|
||||
}
|
||||
}
|
||||
|
||||
struct SubscriptionRoot;
|
||||
|
||||
|
@ -77,7 +81,11 @@ pub async fn test_subscription_ws_transport_with_token() {
|
|||
struct QueryRoot;
|
||||
|
||||
#[Object]
|
||||
impl QueryRoot {}
|
||||
impl QueryRoot {
|
||||
async fn value(&self) -> i32 {
|
||||
10
|
||||
}
|
||||
}
|
||||
|
||||
struct SubscriptionRoot;
|
||||
|
||||
|
@ -161,8 +169,6 @@ pub async fn test_subscription_ws_transport_with_token() {
|
|||
|
||||
#[async_std::test]
|
||||
pub async fn test_subscription_ws_transport_error() {
|
||||
struct QueryRoot;
|
||||
|
||||
struct Event {
|
||||
value: i32,
|
||||
}
|
||||
|
@ -178,8 +184,14 @@ pub async fn test_subscription_ws_transport_error() {
|
|||
}
|
||||
}
|
||||
|
||||
struct QueryRoot;
|
||||
|
||||
#[Object]
|
||||
impl QueryRoot {}
|
||||
impl QueryRoot {
|
||||
async fn value(&self) -> i32 {
|
||||
10
|
||||
}
|
||||
}
|
||||
|
||||
struct SubscriptionRoot;
|
||||
|
||||
|
|
|
@ -327,6 +327,10 @@ pub async fn test_union_flatten() {
|
|||
async fn value2(&self) -> MyUnion {
|
||||
InnerUnion2::B(MyObj2 { value2: 88 }).into()
|
||||
}
|
||||
|
||||
async fn value3(&self) -> InnerUnion1 {
|
||||
InnerUnion1::A(MyObj1 { value1: 77 })
|
||||
}
|
||||
}
|
||||
|
||||
let schema = Schema::new(Query, EmptyMutation, EmptySubscription);
|
||||
|
@ -342,6 +346,11 @@ pub async fn test_union_flatten() {
|
|||
value2
|
||||
}
|
||||
}
|
||||
value3 {
|
||||
... on MyObj1 {
|
||||
value1
|
||||
}
|
||||
}
|
||||
}"#;
|
||||
assert_eq!(
|
||||
schema.execute(query).await.into_result().unwrap().data,
|
||||
|
@ -351,6 +360,9 @@ pub async fn test_union_flatten() {
|
|||
},
|
||||
"value2": {
|
||||
"value2": 88,
|
||||
},
|
||||
"value3": {
|
||||
"value1": 77,
|
||||
}
|
||||
})
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue
Block a user