2020-05-01 23:57:34 +00:00
|
|
|
#![allow(unreachable_code)]
|
|
|
|
|
2022-04-19 04:25:11 +00:00
|
|
|
use std::{collections::HashMap, convert::Infallible};
|
2021-03-06 00:21:44 +00:00
|
|
|
|
2022-04-19 04:25:11 +00:00
|
|
|
use async_graphql::{
|
|
|
|
dataloader::{DataLoader, Loader},
|
|
|
|
*,
|
|
|
|
};
|
2020-04-09 14:03:09 +00:00
|
|
|
|
2021-03-12 04:47:24 +00:00
|
|
|
#[tokio::test]
|
2021-02-21 13:29:03 +00:00
|
|
|
pub async fn test_nested_key() {
|
|
|
|
#[derive(InputObject)]
|
|
|
|
struct MyInputA {
|
|
|
|
a: i32,
|
|
|
|
b: i32,
|
|
|
|
c: MyInputB,
|
2020-04-09 14:03:09 +00:00
|
|
|
}
|
|
|
|
|
2021-02-21 13:29:03 +00:00
|
|
|
#[derive(InputObject)]
|
|
|
|
struct MyInputB {
|
|
|
|
v: i32,
|
2020-04-09 14:03:09 +00:00
|
|
|
}
|
|
|
|
|
2021-02-21 13:29:03 +00:00
|
|
|
assert_eq!(MyInputB::federation_fields().as_deref(), Some("{ v }"));
|
|
|
|
assert_eq!(
|
|
|
|
MyInputA::federation_fields().as_deref(),
|
|
|
|
Some("{ a b c { v } }")
|
|
|
|
);
|
2020-04-09 14:03:09 +00:00
|
|
|
|
2021-11-20 03:16:48 +00:00
|
|
|
struct Query;
|
2020-04-09 14:03:09 +00:00
|
|
|
|
2021-02-21 13:29:03 +00:00
|
|
|
#[derive(SimpleObject)]
|
|
|
|
struct MyObj {
|
|
|
|
a: i32,
|
|
|
|
b: i32,
|
|
|
|
c: i32,
|
2020-04-09 14:03:09 +00:00
|
|
|
}
|
|
|
|
|
2021-02-21 13:29:03 +00:00
|
|
|
#[Object]
|
2021-11-20 03:16:48 +00:00
|
|
|
impl Query {
|
2021-02-21 13:29:03 +00:00
|
|
|
#[graphql(entity)]
|
|
|
|
async fn find_obj(&self, input: MyInputA) -> MyObj {
|
|
|
|
MyObj {
|
|
|
|
a: input.a,
|
|
|
|
b: input.b,
|
|
|
|
c: input.c.v,
|
|
|
|
}
|
|
|
|
}
|
2020-04-09 14:03:09 +00:00
|
|
|
}
|
|
|
|
|
2021-11-20 03:16:48 +00:00
|
|
|
let schema = Schema::new(Query, EmptyMutation, EmptySubscription);
|
2021-02-21 13:29:03 +00:00
|
|
|
let query = r#"{
|
|
|
|
_entities(representations: [{__typename: "MyObj", input: {a: 1, b: 2, c: { v: 3 }}}]) {
|
|
|
|
__typename
|
|
|
|
... on MyObj {
|
|
|
|
a b c
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}"#;
|
|
|
|
assert_eq!(
|
|
|
|
schema.execute(query).await.into_result().unwrap().data,
|
|
|
|
value!({
|
|
|
|
"_entities": [
|
|
|
|
{"__typename": "MyObj", "a": 1, "b": 2, "c": 3},
|
|
|
|
]
|
|
|
|
})
|
|
|
|
);
|
2020-04-09 14:03:09 +00:00
|
|
|
}
|
|
|
|
|
2021-03-12 04:47:24 +00:00
|
|
|
#[tokio::test]
|
2021-02-21 13:29:03 +00:00
|
|
|
pub async fn test_federation() {
|
|
|
|
struct User {
|
|
|
|
id: ID,
|
2020-04-09 14:03:09 +00:00
|
|
|
}
|
|
|
|
|
2021-02-21 13:29:03 +00:00
|
|
|
#[Object(extends)]
|
|
|
|
impl User {
|
|
|
|
#[graphql(external)]
|
|
|
|
async fn id(&self) -> &ID {
|
|
|
|
&self.id
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn reviews(&self) -> Vec<Review> {
|
|
|
|
todo!()
|
|
|
|
}
|
2020-04-09 14:03:09 +00:00
|
|
|
}
|
|
|
|
|
2021-02-21 13:29:03 +00:00
|
|
|
struct Review;
|
|
|
|
|
|
|
|
#[Object]
|
|
|
|
impl Review {
|
|
|
|
async fn body(&self) -> String {
|
|
|
|
todo!()
|
|
|
|
}
|
2020-04-09 14:03:09 +00:00
|
|
|
|
2021-02-21 13:29:03 +00:00
|
|
|
async fn author(&self) -> User {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn product(&self) -> Product {
|
|
|
|
todo!()
|
|
|
|
}
|
2020-04-09 14:03:09 +00:00
|
|
|
}
|
|
|
|
|
2021-02-21 13:29:03 +00:00
|
|
|
struct Product {
|
|
|
|
upc: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[Object(extends)]
|
|
|
|
impl Product {
|
|
|
|
#[graphql(external)]
|
|
|
|
async fn upc(&self) -> &str {
|
|
|
|
&self.upc
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn reviews(&self) -> Vec<Review> {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-20 03:16:48 +00:00
|
|
|
struct Query;
|
2021-02-21 13:29:03 +00:00
|
|
|
|
|
|
|
#[Object]
|
2021-11-20 03:16:48 +00:00
|
|
|
impl Query {
|
2021-02-21 13:29:03 +00:00
|
|
|
#[graphql(entity)]
|
|
|
|
async fn find_user_by_id(&self, id: ID) -> User {
|
|
|
|
User { id }
|
|
|
|
}
|
|
|
|
|
|
|
|
#[graphql(entity)]
|
|
|
|
async fn find_product_by_upc(&self, upc: String) -> Product {
|
|
|
|
Product { upc }
|
|
|
|
}
|
2020-04-09 14:03:09 +00:00
|
|
|
}
|
|
|
|
|
2021-11-20 03:16:48 +00:00
|
|
|
let schema = Schema::new(Query, EmptyMutation, EmptySubscription);
|
2020-05-01 23:57:34 +00:00
|
|
|
let query = r#"{
|
|
|
|
_entities(representations: [{__typename: "Product", upc: "B00005N5PF"}]) {
|
2020-04-09 14:03:09 +00:00
|
|
|
__typename
|
2020-05-01 23:57:34 +00:00
|
|
|
... on Product {
|
2020-04-09 14:03:09 +00:00
|
|
|
upc
|
2020-05-01 23:57:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}"#;
|
2020-04-09 14:03:09 +00:00
|
|
|
assert_eq!(
|
2020-09-12 09:29:52 +00:00
|
|
|
schema.execute(query).await.into_result().unwrap().data,
|
2020-10-12 02:17:05 +00:00
|
|
|
value!({
|
2020-04-09 14:03:09 +00:00
|
|
|
"_entities": [
|
|
|
|
{"__typename": "Product", "upc": "B00005N5PF"},
|
|
|
|
]
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
2021-03-06 00:21:44 +00:00
|
|
|
|
2021-03-12 04:47:24 +00:00
|
|
|
#[tokio::test]
|
2021-03-06 00:21:44 +00:00
|
|
|
pub async fn test_find_entity_with_context() {
|
|
|
|
struct MyLoader;
|
|
|
|
|
|
|
|
#[async_trait::async_trait]
|
|
|
|
impl Loader<ID> for MyLoader {
|
|
|
|
type Value = MyObj;
|
|
|
|
type Error = Infallible;
|
|
|
|
|
|
|
|
async fn load(&self, keys: &[ID]) -> Result<HashMap<ID, Self::Value>, Self::Error> {
|
|
|
|
Ok(keys
|
|
|
|
.iter()
|
|
|
|
.filter(|id| id.as_str() != "999")
|
|
|
|
.map(|id| {
|
|
|
|
(
|
|
|
|
id.clone(),
|
|
|
|
MyObj {
|
|
|
|
id: id.clone(),
|
|
|
|
value: 999,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
})
|
|
|
|
.collect())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, SimpleObject)]
|
|
|
|
struct MyObj {
|
|
|
|
id: ID,
|
|
|
|
value: i32,
|
|
|
|
}
|
|
|
|
|
2021-11-20 03:16:48 +00:00
|
|
|
struct Query;
|
2021-03-06 00:21:44 +00:00
|
|
|
|
|
|
|
#[Object]
|
2021-11-20 03:16:48 +00:00
|
|
|
impl Query {
|
2021-03-06 00:21:44 +00:00
|
|
|
#[graphql(entity)]
|
|
|
|
async fn find_user_by_id(&self, ctx: &Context<'_>, id: ID) -> FieldResult<MyObj> {
|
|
|
|
let loader = ctx.data_unchecked::<DataLoader<MyLoader>>();
|
|
|
|
loader
|
|
|
|
.load_one(id)
|
|
|
|
.await
|
|
|
|
.unwrap()
|
|
|
|
.ok_or_else(|| "Not found".into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-20 03:16:48 +00:00
|
|
|
let schema = Schema::build(Query, EmptyMutation, EmptySubscription)
|
2021-12-04 06:33:47 +00:00
|
|
|
.data(DataLoader::new(MyLoader, tokio::spawn))
|
2021-03-06 00:21:44 +00:00
|
|
|
.finish();
|
|
|
|
let query = r#"{
|
|
|
|
_entities(representations: [
|
|
|
|
{__typename: "MyObj", id: "1"},
|
|
|
|
{__typename: "MyObj", id: "2"},
|
|
|
|
{__typename: "MyObj", id: "3"},
|
|
|
|
{__typename: "MyObj", id: "4"}
|
|
|
|
]) {
|
|
|
|
__typename
|
|
|
|
... on MyObj {
|
|
|
|
id
|
|
|
|
value
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}"#;
|
|
|
|
assert_eq!(
|
|
|
|
schema.execute(query).await.into_result().unwrap().data,
|
|
|
|
value!({
|
|
|
|
"_entities": [
|
|
|
|
{"__typename": "MyObj", "id": "1", "value": 999 },
|
|
|
|
{"__typename": "MyObj", "id": "2", "value": 999 },
|
|
|
|
{"__typename": "MyObj", "id": "3", "value": 999 },
|
|
|
|
{"__typename": "MyObj", "id": "4", "value": 999 },
|
|
|
|
]
|
|
|
|
})
|
|
|
|
);
|
|
|
|
|
|
|
|
let query = r#"{
|
|
|
|
_entities(representations: [
|
|
|
|
{__typename: "MyObj", id: "999"}
|
|
|
|
]) {
|
|
|
|
__typename
|
|
|
|
... on MyObj {
|
|
|
|
id
|
|
|
|
value
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}"#;
|
|
|
|
assert_eq!(
|
|
|
|
schema.execute(query).await.into_result().unwrap_err(),
|
|
|
|
vec![ServerError {
|
|
|
|
message: "Not found".to_string(),
|
2021-11-07 11:11:17 +00:00
|
|
|
source: None,
|
2021-03-06 00:21:44 +00:00
|
|
|
locations: vec![Pos {
|
|
|
|
line: 2,
|
|
|
|
column: 13
|
|
|
|
}],
|
|
|
|
path: vec![PathSegment::Field("_entities".to_owned())],
|
|
|
|
extensions: None,
|
|
|
|
}]
|
|
|
|
);
|
|
|
|
}
|
2021-11-13 01:05:29 +00:00
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
pub async fn test_entity_union() {
|
|
|
|
#[derive(SimpleObject)]
|
|
|
|
struct MyObj {
|
|
|
|
a: i32,
|
|
|
|
}
|
|
|
|
|
|
|
|
struct Query;
|
|
|
|
|
|
|
|
#[Object]
|
|
|
|
impl Query {
|
|
|
|
#[graphql(entity)]
|
2021-11-13 01:08:55 +00:00
|
|
|
async fn find_obj(&self, _id: i32) -> MyObj {
|
2021-11-13 01:05:29 +00:00
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let schema = Schema::new(Query, EmptyMutation, EmptySubscription);
|
|
|
|
let query = r#"{
|
|
|
|
__type(name: "_Entity") { possibleTypes { name } }
|
|
|
|
}"#;
|
|
|
|
assert_eq!(
|
|
|
|
schema.execute(query).await.into_result().unwrap().data,
|
|
|
|
value!({
|
|
|
|
"__type": {
|
|
|
|
"possibleTypes": [
|
|
|
|
{"name": "MyObj"},
|
|
|
|
]
|
|
|
|
}
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
2022-08-17 01:50:37 +00:00
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
pub async fn test_entity_shareable() {
|
|
|
|
#[derive(SimpleObject)]
|
2022-08-17 02:36:00 +00:00
|
|
|
struct MyObjFieldShareable {
|
2022-08-17 01:50:37 +00:00
|
|
|
#[graphql(shareable)]
|
2022-08-17 02:36:00 +00:00
|
|
|
field_shareable_a: i32,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(SimpleObject)]
|
|
|
|
#[graphql(shareable)]
|
|
|
|
struct MyObjShareable {
|
2022-08-17 01:50:37 +00:00
|
|
|
a: i32,
|
|
|
|
}
|
|
|
|
|
|
|
|
struct Query;
|
|
|
|
|
|
|
|
#[Object(extends)]
|
|
|
|
impl Query {
|
|
|
|
#[graphql(entity)]
|
2022-08-17 02:36:00 +00:00
|
|
|
async fn find_obj_field_shareable(&self, _id: i32) -> MyObjFieldShareable {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
#[graphql(entity)]
|
|
|
|
async fn find_obj_shareable(&self, _id: i32) -> MyObjShareable {
|
2022-08-17 01:50:37 +00:00
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-17 01:51:23 +00:00
|
|
|
let schema_sdl = Schema::new(Query, EmptyMutation, EmptySubscription)
|
|
|
|
.sdl_with_options(SDLExportOptions::new().federation());
|
2022-08-17 01:50:37 +00:00
|
|
|
assert_eq!(
|
2022-08-17 02:36:00 +00:00
|
|
|
schema_sdl.contains("fieldShareableA: Int! @shareable"),
|
|
|
|
true
|
|
|
|
);
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
schema_sdl.contains(r#"MyObjShareable @key(fields: "id") @shareable"#),
|
2022-08-17 01:50:37 +00:00
|
|
|
true
|
|
|
|
);
|
|
|
|
}
|
2022-08-18 09:40:04 +00:00
|
|
|
|
2022-08-19 21:47:56 +00:00
|
|
|
#[tokio::test]
|
|
|
|
pub async fn test_field_override_directive() {
|
|
|
|
#[derive(SimpleObject)]
|
|
|
|
struct MyObjFieldOverride {
|
|
|
|
#[graphql(override_from = "AnotherSubgraph")]
|
|
|
|
field_override_a: i32,
|
|
|
|
}
|
|
|
|
|
|
|
|
struct Query;
|
|
|
|
|
|
|
|
#[Object(extends)]
|
|
|
|
impl Query {
|
|
|
|
#[graphql(entity)]
|
|
|
|
async fn find_obj_field_override(&self, _id: i32) -> MyObjFieldOverride {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let schema_sdl = Schema::new(Query, EmptyMutation, EmptySubscription)
|
|
|
|
.sdl_with_options(SDLExportOptions::new().federation());
|
|
|
|
assert_eq!(
|
|
|
|
schema_sdl.contains("fieldOverrideA: Int! @override(from: \"AnotherSubgraph\")"),
|
|
|
|
true
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-08-18 09:40:04 +00:00
|
|
|
#[tokio::test]
|
|
|
|
pub async fn test_entity_inaccessible() {
|
2022-08-18 12:31:27 +00:00
|
|
|
struct MyCustomObjInaccessible;
|
|
|
|
|
|
|
|
#[Object(inaccessible)]
|
|
|
|
impl MyCustomObjInaccessible {
|
|
|
|
async fn a(&self) -> i32 {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[graphql(inaccessible)]
|
|
|
|
async fn custom_object_inaccessible(&self) -> i32 {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-18 09:40:04 +00:00
|
|
|
#[derive(SimpleObject)]
|
|
|
|
struct MyObjFieldInaccessible {
|
|
|
|
#[graphql(inaccessible)]
|
|
|
|
obj_field_inaccessible_a: i32,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(SimpleObject)]
|
|
|
|
#[graphql(inaccessible)]
|
|
|
|
struct MyObjInaccessible {
|
|
|
|
a: i32,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(InputObject)]
|
|
|
|
struct MyInputObjFieldInaccessible {
|
|
|
|
#[graphql(inaccessible)]
|
|
|
|
input_field_inaccessible_a: i32,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(InputObject)]
|
|
|
|
#[graphql(inaccessible)]
|
|
|
|
struct MyInputObjInaccessible {
|
|
|
|
a: i32,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Enum, PartialEq, Eq, Copy, Clone)]
|
|
|
|
enum MyEnumVariantInaccessible {
|
|
|
|
#[graphql(inaccessible)]
|
|
|
|
OptionAInaccessible,
|
|
|
|
OptionB,
|
|
|
|
OptionC,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Enum, PartialEq, Eq, Copy, Clone)]
|
|
|
|
#[graphql(inaccessible)]
|
|
|
|
enum MyEnumInaccessible {
|
|
|
|
OptionA,
|
|
|
|
OptionB,
|
|
|
|
OptionC,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(SimpleObject)]
|
|
|
|
struct MyInterfaceObjA {
|
|
|
|
inaccessible_interface_value: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(SimpleObject)]
|
|
|
|
#[graphql(inaccessible)]
|
|
|
|
struct MyInterfaceObjB {
|
|
|
|
inaccessible_interface_value: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Interface)]
|
|
|
|
#[graphql(field(name = "inaccessible_interface_value", type = "String", inaccessible))]
|
|
|
|
#[graphql(inaccessible)]
|
|
|
|
enum MyInterfaceInaccessible {
|
|
|
|
MyInterfaceObjA(MyInterfaceObjA),
|
|
|
|
MyInterfaceObjB(MyInterfaceObjB),
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Union)]
|
|
|
|
#[graphql(inaccessible)]
|
|
|
|
enum MyUnionInaccessible {
|
|
|
|
MyInterfaceObjA(MyInterfaceObjA),
|
|
|
|
MyInterfaceObjB(MyInterfaceObjB),
|
|
|
|
}
|
|
|
|
|
|
|
|
struct MyNumberInaccessible(i32);
|
|
|
|
|
|
|
|
#[Scalar(inaccessible)]
|
|
|
|
impl ScalarType for MyNumberInaccessible {
|
|
|
|
fn parse(_value: Value) -> InputValueResult<Self> {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn to_value(&self) -> Value {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct Query;
|
|
|
|
|
|
|
|
#[Object(extends)]
|
|
|
|
impl Query {
|
|
|
|
#[graphql(entity)]
|
|
|
|
async fn find_obj_field_inaccessible(&self, _id: i32) -> MyObjFieldInaccessible {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[graphql(entity)]
|
|
|
|
async fn find_obj_inaccessible(&self, _id: i32) -> MyObjInaccessible {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn enum_variant_inaccessible(&self, _id: i32) -> MyEnumVariantInaccessible {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn enum_inaccessible(&self, _id: i32) -> MyEnumInaccessible {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[graphql(inaccessible)]
|
|
|
|
async fn inaccessible_field(&self, _id: i32) -> i32 {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn inaccessible_argument(&self, #[graphql(inaccessible)] _id: i32) -> i32 {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn inaccessible_interface(&self) -> MyInterfaceInaccessible {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn inaccessible_union(&self) -> MyUnionInaccessible {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn inaccessible_scalar(&self) -> MyNumberInaccessible {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn inaccessible_input_field(&self, _value: MyInputObjFieldInaccessible) -> i32 {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn inaccessible_input(&self, _value: MyInputObjInaccessible) -> i32 {
|
|
|
|
todo!()
|
|
|
|
}
|
2022-08-18 12:31:27 +00:00
|
|
|
|
|
|
|
async fn inaccessible_custom_object(&self) -> MyCustomObjInaccessible {
|
|
|
|
todo!()
|
|
|
|
}
|
2022-08-18 09:40:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
let schema_sdl = Schema::new(Query, EmptyMutation, EmptySubscription)
|
|
|
|
.sdl_with_options(SDLExportOptions::new().federation());
|
|
|
|
|
|
|
|
// FIELD_DEFINITION
|
|
|
|
assert!(schema_sdl.contains("inaccessibleField(id: Int!): Int! @inaccessible"));
|
|
|
|
assert!(schema_sdl.contains("objFieldInaccessibleA: Int! @inaccessible"));
|
|
|
|
assert!(schema_sdl.contains("inaccessibleInterfaceValue: String! @inaccessible"));
|
2022-08-18 12:31:27 +00:00
|
|
|
assert!(schema_sdl.contains("customObjectInaccessible: Int! @inaccessible"));
|
2022-08-18 09:40:04 +00:00
|
|
|
// INTERFACE
|
|
|
|
assert!(schema_sdl.contains("interface MyInterfaceInaccessible @inaccessible"));
|
|
|
|
// OBJECT
|
2022-08-18 12:31:27 +00:00
|
|
|
assert!(schema_sdl.contains("type MyCustomObjInaccessible @inaccessible"));
|
2022-08-18 09:40:04 +00:00
|
|
|
assert!(schema_sdl.contains(r#"type MyObjInaccessible @key(fields: "id") @inaccessible"#));
|
|
|
|
assert!(schema_sdl
|
|
|
|
.contains("type MyInterfaceObjB implements MyInterfaceInaccessible @inaccessible"));
|
|
|
|
// UNION
|
|
|
|
assert!(schema_sdl.contains("union MyUnionInaccessible @inaccessible ="));
|
|
|
|
// ARGUMENT_DEFINITION
|
|
|
|
assert!(schema_sdl.contains("inaccessibleArgument(id: Int! @inaccessible): Int!"));
|
|
|
|
// SCALAR
|
|
|
|
assert!(schema_sdl.contains("scalar MyNumberInaccessible @inaccessible"));
|
|
|
|
// ENUM
|
|
|
|
assert!(schema_sdl.contains("enum MyEnumInaccessible @inaccessible"));
|
|
|
|
// ENUM_VALUE
|
|
|
|
assert!(schema_sdl.contains("OPTION_A_INACCESSIBLE @inaccessible"));
|
|
|
|
// INPUT_OBJECT
|
|
|
|
assert!(schema_sdl.contains("input MyInputObjInaccessible @inaccessible"));
|
|
|
|
// INPUT_FIELD_DEFINITION
|
|
|
|
assert!(schema_sdl.contains("inputFieldInaccessibleA: Int! @inaccessible"));
|
|
|
|
}
|
2022-08-22 09:44:02 +00:00
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
pub async fn test_entity_tag() {
|
|
|
|
struct MyCustomObjTagged;
|
|
|
|
|
|
|
|
#[Object(
|
|
|
|
tag = "tagged",
|
|
|
|
tag = "object",
|
|
|
|
tag = "with",
|
|
|
|
tag = "multiple",
|
|
|
|
tag = "tags"
|
|
|
|
)]
|
|
|
|
impl MyCustomObjTagged {
|
|
|
|
async fn a(&self) -> i32 {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[graphql(tag = "tagged_custom_object_field")]
|
|
|
|
async fn custom_object_tagged(&self) -> i32 {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(SimpleObject)]
|
|
|
|
struct MyObjFieldTagged {
|
|
|
|
#[graphql(tag = "tagged_field")]
|
|
|
|
obj_field_tagged_a: i32,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(SimpleObject)]
|
|
|
|
#[graphql(tag = "tagged_simple_object")]
|
|
|
|
struct MyObjTagged {
|
|
|
|
a: i32,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(InputObject)]
|
|
|
|
struct MyInputObjFieldTagged {
|
|
|
|
#[graphql(tag = "tagged_input_object_field")]
|
|
|
|
input_field_tagged_a: i32,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(InputObject)]
|
|
|
|
#[graphql(tag = "input_object_tag")]
|
|
|
|
struct MyInputObjTagged {
|
|
|
|
a: i32,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Enum, PartialEq, Eq, Copy, Clone)]
|
|
|
|
enum MyEnumVariantTagged {
|
|
|
|
#[graphql(tag = "tagged_enum_option")]
|
|
|
|
OptionATagged,
|
|
|
|
OptionB,
|
|
|
|
OptionC,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Enum, PartialEq, Eq, Copy, Clone)]
|
|
|
|
#[graphql(tag = "tagged_num")]
|
|
|
|
enum MyEnumTagged {
|
|
|
|
OptionA,
|
|
|
|
OptionB,
|
|
|
|
OptionC,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(SimpleObject)]
|
|
|
|
struct MyInterfaceObjA {
|
|
|
|
tagged_interface_value: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(SimpleObject)]
|
|
|
|
#[graphql(tag = "interface_object")]
|
|
|
|
struct MyInterfaceObjB {
|
|
|
|
tagged_interface_value: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Interface)]
|
|
|
|
#[graphql(field(
|
|
|
|
name = "tagged_interface_value",
|
|
|
|
type = "String",
|
|
|
|
tag = "tagged_interface_field"
|
|
|
|
))]
|
|
|
|
#[graphql(tag = "tagged_interface")]
|
|
|
|
enum MyInterfaceTagged {
|
|
|
|
MyInterfaceObjA(MyInterfaceObjA),
|
|
|
|
MyInterfaceObjB(MyInterfaceObjB),
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Union)]
|
|
|
|
#[graphql(tag = "tagged_union")]
|
|
|
|
enum MyUnionTagged {
|
|
|
|
MyInterfaceObjA(MyInterfaceObjA),
|
|
|
|
MyInterfaceObjB(MyInterfaceObjB),
|
|
|
|
}
|
|
|
|
|
|
|
|
struct MyNumberTagged(i32);
|
|
|
|
|
|
|
|
#[Scalar(tag = "tagged_scalar")]
|
|
|
|
impl ScalarType for MyNumberTagged {
|
|
|
|
fn parse(_value: Value) -> InputValueResult<Self> {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn to_value(&self) -> Value {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct Query;
|
|
|
|
|
|
|
|
#[Object(extends)]
|
|
|
|
impl Query {
|
|
|
|
#[graphql(entity)]
|
|
|
|
async fn find_obj_field_tagged(&self, _id: i32) -> MyObjFieldTagged {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[graphql(entity)]
|
|
|
|
async fn find_obj_tagged(&self, _id: i32) -> MyObjTagged {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn enum_variant_tagged(&self, _id: i32) -> MyEnumVariantTagged {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn enum_tagged(&self, _id: i32) -> MyEnumTagged {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[graphql(tag = "tagged_\"field\"")]
|
|
|
|
async fn tagged_field(&self, _id: i32) -> i32 {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn tagged_argument(&self, #[graphql(tag = "tagged_argument")] _id: i32) -> i32 {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn tagged_interface(&self) -> MyInterfaceTagged {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn tagged_union(&self) -> MyUnionTagged {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn tagged_scalar(&self) -> MyNumberTagged {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn tagged_input_field(&self, _value: MyInputObjFieldTagged) -> i32 {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn tagged_input(&self, _value: MyInputObjTagged) -> i32 {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn tagged_custom_object(&self) -> MyCustomObjTagged {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let schema_sdl = Schema::new(Query, EmptyMutation, EmptySubscription)
|
|
|
|
.sdl_with_options(SDLExportOptions::new().federation());
|
|
|
|
|
|
|
|
// FIELD_DEFINITION
|
|
|
|
assert!(schema_sdl.contains(r#"taggedField(id: Int!): Int! @tag(name: "tagged_\"field\"")"#));
|
|
|
|
assert!(schema_sdl.contains(r#"objFieldTaggedA: Int! @tag(name: "tagged_field")"#));
|
|
|
|
assert!(schema_sdl
|
|
|
|
.contains(r#"taggedInterfaceValue: String! @tag(name: "tagged_interface_field")"#));
|
|
|
|
assert!(
|
|
|
|
schema_sdl.contains(r#"customObjectTagged: Int! @tag(name: "tagged_custom_object_field")"#)
|
|
|
|
);
|
|
|
|
// INTERFACE
|
|
|
|
assert!(schema_sdl.contains(r#"interface MyInterfaceTagged @tag(name: "tagged_interface")"#));
|
|
|
|
// OBJECT
|
|
|
|
assert!(schema_sdl.contains(r#"type MyCustomObjTagged @tag(name: "tagged") @tag(name: "object") @tag(name: "with") @tag(name: "multiple") @tag(name: "tags") {"#));
|
|
|
|
assert!(schema_sdl
|
|
|
|
.contains(r#"type MyObjTagged @key(fields: "id") @tag(name: "tagged_simple_object") {"#));
|
|
|
|
assert!(schema_sdl.contains(
|
|
|
|
r#"type MyInterfaceObjB implements MyInterfaceTagged @tag(name: "interface_object")"#
|
|
|
|
));
|
|
|
|
// UNION
|
|
|
|
assert!(schema_sdl.contains(r#"union MyUnionTagged @tag(name: "tagged_union") ="#));
|
|
|
|
// ARGUMENT_DEFINITION
|
|
|
|
assert!(schema_sdl.contains(r#"taggedArgument(id: Int! @tag(name: "tagged_argument")): Int!"#));
|
|
|
|
// SCALAR
|
|
|
|
assert!(schema_sdl.contains(r#"scalar MyNumberTagged @tag(name: "tagged_scalar")"#));
|
|
|
|
// ENUM
|
|
|
|
assert!(schema_sdl.contains(r#"enum MyEnumTagged @tag(name: "tagged_num")"#));
|
|
|
|
// ENUM_VALUE
|
|
|
|
assert!(schema_sdl.contains(r#"OPTION_A_TAGGED @tag(name: "tagged_enum_option")"#));
|
|
|
|
// INPUT_OBJECT
|
|
|
|
assert!(schema_sdl.contains(r#"input MyInputObjTagged @tag(name: "input_object_tag")"#));
|
|
|
|
// INPUT_FIELD_DEFINITION
|
|
|
|
assert!(
|
|
|
|
schema_sdl.contains(r#"inputFieldTaggedA: Int! @tag(name: "tagged_input_object_field")"#)
|
|
|
|
);
|
|
|
|
}
|