5c8ff9d3a6
If an interface is added manually (as it is not directly referenced by any type) it was not showing up in the introspection. Now it will be exposed if it is visible and references already accessible types
204 lines
4.2 KiB
Rust
204 lines
4.2 KiB
Rust
use async_graphql::*;
|
|
use serde::Deserialize;
|
|
|
|
#[derive(SimpleObject)]
|
|
struct ObjectA {
|
|
id: i32,
|
|
title: String,
|
|
}
|
|
|
|
#[derive(SimpleObject)]
|
|
struct ObjectB {
|
|
id: i32,
|
|
title: String,
|
|
}
|
|
|
|
#[derive(Interface)]
|
|
#[graphql(field(name = "id", type = "&i32"))]
|
|
enum ImplicitInterface {
|
|
ObjectA(ObjectA),
|
|
ObjectB(ObjectB),
|
|
}
|
|
|
|
#[derive(Interface)]
|
|
#[graphql(field(name = "title", type = "String"))]
|
|
enum ExplicitInterface {
|
|
ObjectA(ObjectA),
|
|
ObjectB(ObjectB),
|
|
}
|
|
|
|
#[derive(Interface)]
|
|
#[graphql(visible = false)]
|
|
#[graphql(field(name = "title", type = "String"))]
|
|
enum InvisibleInterface {
|
|
ObjectA(ObjectA),
|
|
ObjectB(ObjectB),
|
|
}
|
|
|
|
#[derive(SimpleObject)]
|
|
struct ObjectC {
|
|
id: i32,
|
|
title: String,
|
|
}
|
|
|
|
#[derive(Interface)]
|
|
#[graphql(field(name = "id", type = "&i32"))]
|
|
enum UnreferencedInterface {
|
|
ObjectC(ObjectC),
|
|
}
|
|
|
|
|
|
#[derive(Union)]
|
|
enum ObjectUnion {
|
|
ObjectA(ObjectA),
|
|
ObjectB(ObjectB),
|
|
}
|
|
|
|
struct Query;
|
|
|
|
#[Object]
|
|
impl Query {
|
|
async fn implicit(&self) -> ObjectUnion {
|
|
ObjectA {
|
|
id: 33,
|
|
title: "haha".to_string(),
|
|
}.into()
|
|
}
|
|
|
|
async fn explicit(&self) -> ExplicitInterface {
|
|
ObjectA {
|
|
id: 40,
|
|
title: "explicit".to_string(),
|
|
}.into()
|
|
}
|
|
}
|
|
|
|
fn build_schema() -> Schema<Query, EmptyMutation, EmptySubscription> {
|
|
Schema::build(Query, EmptyMutation, EmptySubscription)
|
|
.register_output_type::<ImplicitInterface>()
|
|
.register_output_type::<InvisibleInterface>()
|
|
.register_output_type::<UnreferencedInterface>()
|
|
.finish()
|
|
}
|
|
|
|
#[tokio::test]
|
|
pub async fn test_interface_exports_interfaces_on_object_type() {
|
|
#[derive(Deserialize)]
|
|
struct QueryResponse {
|
|
#[serde(rename = "__type")]
|
|
ty: TypeResponse,
|
|
}
|
|
|
|
#[derive(Deserialize)]
|
|
struct TypeResponse {
|
|
name: String,
|
|
kind: String,
|
|
interfaces: Vec<InterfaceResponse>,
|
|
}
|
|
|
|
#[derive(Deserialize)]
|
|
struct InterfaceResponse {
|
|
name: String,
|
|
}
|
|
|
|
let schema = build_schema();
|
|
|
|
let resp: QueryResponse = from_value(
|
|
schema
|
|
.execute(r#"{ __type(name: "ObjectA") { name kind interfaces { name }} }"#)
|
|
.await
|
|
.into_result()
|
|
.unwrap()
|
|
.data,
|
|
)
|
|
.unwrap();
|
|
|
|
assert_eq!(resp.ty.name, "ObjectA");
|
|
assert_eq!(resp.ty.kind, "OBJECT");
|
|
assert!(resp.ty.interfaces.iter().any(|i| i.name == "ExplicitInterface"));
|
|
assert!(resp.ty.interfaces.iter().any(|i| i.name == "ImplicitInterface"));
|
|
assert!(!resp.ty.interfaces.iter().any(|i| i.name == "InvisibleInterface"));
|
|
}
|
|
|
|
#[tokio::test]
|
|
pub async fn test_interface_exports_explicit_interface_type() {
|
|
let schema = build_schema();
|
|
|
|
let data = schema
|
|
.execute(r#"{ __type(name: "ExplicitInterface") { name kind } }"#)
|
|
.await
|
|
.into_result()
|
|
.unwrap()
|
|
.data;
|
|
|
|
assert_eq!(
|
|
data,
|
|
value!({
|
|
"__type": {
|
|
"name": "ExplicitInterface",
|
|
"kind": "INTERFACE",
|
|
}
|
|
})
|
|
);
|
|
}
|
|
|
|
#[tokio::test]
|
|
pub async fn test_interface_exports_implicit_interface_type() {
|
|
let schema = build_schema();
|
|
|
|
let data = schema
|
|
.execute(r#"{ __type(name: "ImplicitInterface") { name kind } }"#)
|
|
.await
|
|
.into_result()
|
|
.unwrap()
|
|
.data;
|
|
|
|
assert_eq!(
|
|
data,
|
|
value!({
|
|
"__type": {
|
|
"name": "ImplicitInterface",
|
|
"kind": "INTERFACE",
|
|
}
|
|
})
|
|
);
|
|
}
|
|
|
|
#[tokio::test]
|
|
pub async fn test_interface_no_export_invisible_interface_type() {
|
|
let schema = build_schema();
|
|
|
|
let data = schema
|
|
.execute(r#"{ __type(name: "InvisibleInterface") { name } }"#)
|
|
.await
|
|
.into_result()
|
|
.unwrap()
|
|
.data;
|
|
|
|
assert_eq!(
|
|
data,
|
|
value!({
|
|
"__type": null,
|
|
})
|
|
);
|
|
}
|
|
|
|
#[tokio::test]
|
|
pub async fn test_interface_no_export_unreferenced_interface_type() {
|
|
let schema = build_schema();
|
|
|
|
let data = schema
|
|
.execute(r#"{ __type(name: "UnreferencedInterface") { name } }"#)
|
|
.await
|
|
.into_result()
|
|
.unwrap()
|
|
.data;
|
|
|
|
assert_eq!(
|
|
data,
|
|
value!({
|
|
"__type": null,
|
|
})
|
|
);
|
|
}
|