#![allow(clippy::unwrap_used)]
#![allow(clippy::doc_markdown)] #![allow(clippy::needless_collect)] #![allow(clippy::iter_with_drain)]
#[test]
fn test_entities_query_recognized() {
use fraiseql_core::federation;
assert!(federation::is_federation_query("_entities"));
assert!(federation::is_federation_query("_service"));
assert!(!federation::is_federation_query("query"));
assert!(!federation::is_federation_query("mutation"));
}
#[test]
fn test_entities_representations_parsed() {
use serde_json::json;
let entity_json = json!({
"__typename": "User",
"id": "123",
"name": "Alice"
});
assert_eq!(entity_json["__typename"], "User");
assert_eq!(entity_json["id"], "123");
assert_eq!(entity_json["name"], "Alice");
}
#[test]
fn test_entities_response_format() {
use serde_json::json;
let response = json!({
"data": {
"_entities": [
{"__typename": "User", "id": "1", "name": "Alice"},
{"__typename": "User", "id": "2", "name": "Bob"},
]
}
});
let entities = response["data"]["_entities"].as_array().unwrap();
assert_eq!(entities.len(), 2);
assert_eq!(entities[0]["name"], "Alice");
assert_eq!(entities[1]["name"], "Bob");
}
#[test]
fn test_entities_null_handling() {
use serde_json::json;
let response = json!({
"data": {
"_entities": [
{"__typename": "User", "id": "1", "name": "Alice"},
null, {"__typename": "User", "id": "3", "name": "Charlie"},
]
}
});
let entities = response["data"]["_entities"].as_array().unwrap();
assert_eq!(entities.len(), 3);
assert!(entities[0].is_object());
assert!(entities[1].is_null());
assert!(entities[2].is_object());
}
#[test]
fn test_entities_batch_100() {
use serde_json::json;
let mut entities = Vec::new();
for i in 0..100 {
entities.push(json!({
"__typename": "User",
"id": i.to_string(),
"name": format!("User{}", i)
}));
}
assert_eq!(entities.len(), 100);
assert_eq!(entities[0]["id"], "0");
assert_eq!(entities[99]["id"], "99");
}
#[test]
fn test_service_query_recognized() {
use fraiseql_core::federation;
assert!(federation::is_federation_query("_service"));
}
#[test]
fn test_service_query_required_fields() {
use serde_json::json;
let response = json!({
"_service": {
"sdl": "type User @key(fields: \"id\") { id: ID! }"
}
});
assert!(response["_service"]["sdl"].is_string());
let sdl = response["_service"]["sdl"].as_str().unwrap();
assert!(!sdl.is_empty());
}
#[test]
fn test_sdl_includes_federation_directives() {
let sdl = r#"
type User @key(fields: "id") {
id: ID!
name: String!
}
"#;
assert!(sdl.contains("@key"));
assert!(sdl.contains("fields: \"id\""));
}
#[test]
fn test_sdl_includes_entity_union() {
let entity_union_sdl = "union _Entity = User | Order | Product";
assert!(entity_union_sdl.contains("_Entity"));
assert!(entity_union_sdl.contains("User"));
}
#[test]
fn test_sdl_includes_any_scalar() {
let scalar_def = "scalar _Any";
assert!(scalar_def.contains("_Any"));
}
#[test]
fn test_sdl_valid_graphql() {
let sdl = r#"
scalar _Any
union _Entity = User
type User @key(fields: "id") {
id: ID!
}
type _Service {
sdl: String!
}
extend type Query {
_entities(representations: [_Any!]!): [_Entity]!
_service: _Service!
}
"#;
assert!(sdl.contains("scalar _Any"));
assert!(sdl.contains("union _Entity"));
assert!(sdl.contains("_entities"));
assert!(sdl.contains("_service"));
}
#[test]
fn test_entity_representation_parse_typename() {
use serde_json::json;
let rep = json!({
"__typename": "User",
"id": "123"
});
assert_eq!(rep["__typename"], "User");
}
#[test]
fn test_entity_representation_key_fields() {
use serde_json::json;
let rep = json!({
"__typename": "User",
"id": "123",
"email": "user@example.com"
});
assert_eq!(rep["id"], "123");
assert_eq!(rep["email"], "user@example.com");
}
#[test]
fn test_entity_representation_null_values() {
use serde_json::json;
let rep = json!({
"__typename": "User",
"id": "123",
"bio": null });
assert_eq!(rep["id"], "123");
assert!(rep["bio"].is_null());
}
#[test]
fn test_entity_representation_composite_keys() {
use serde_json::json;
let rep = json!({
"__typename": "OrgUser",
"organizationId": "org-456",
"id": "user-789",
"name": "Alice"
});
assert_eq!(rep["organizationId"], "org-456");
assert_eq!(rep["id"], "user-789");
}
#[test]
fn test_any_scalar_required() {
let scalar_definition = "scalar _Any";
assert!(scalar_definition.contains("_Any"));
}
#[test]
fn test_strategy_local_for_owned_entity() {
use fraiseql_core::federation::types::{FederatedType, FederationMetadata, KeyDirective};
let metadata = FederationMetadata {
enabled: true,
version: "v2".to_string(),
types: vec![FederatedType {
name: "User".to_string(),
keys: vec![KeyDirective {
fields: vec!["id".to_string()],
resolvable: true,
}],
is_extends: false, external_fields: vec![],
shareable_fields: vec![],
field_directives: std::collections::HashMap::new(),
}],
};
let fed_type = metadata.types.iter().find(|t| t.name == "User").unwrap();
assert!(!fed_type.is_extends, "User should be locally owned (not extended)");
}
#[test]
fn test_strategy_direct_db_when_available() {
use fraiseql_core::federation::types::{FederatedType, FederationMetadata, KeyDirective};
let metadata = FederationMetadata {
enabled: true,
version: "v2".to_string(),
types: vec![FederatedType {
name: "Order".to_string(),
keys: vec![KeyDirective {
fields: vec!["id".to_string()],
resolvable: true,
}],
is_extends: true, external_fields: vec!["id".to_string()],
shareable_fields: vec![],
field_directives: std::collections::HashMap::new(),
}],
};
let fed_type = metadata.types.iter().find(|t| t.name == "Order").unwrap();
assert!(fed_type.is_extends, "Order should be extended (not locally owned)");
}
#[test]
fn test_strategy_http_fallback() {
use fraiseql_core::federation::types::{FederatedType, FederationMetadata, KeyDirective};
let metadata = FederationMetadata {
enabled: true,
version: "v2".to_string(),
types: vec![
FederatedType {
name: "User".to_string(),
keys: vec![KeyDirective {
fields: vec!["id".to_string()],
resolvable: true,
}],
is_extends: false,
external_fields: vec![],
shareable_fields: vec![],
field_directives: std::collections::HashMap::new(),
},
FederatedType {
name: "Product".to_string(),
keys: vec![KeyDirective {
fields: vec!["id".to_string()],
resolvable: true,
}],
is_extends: true,
external_fields: vec!["id".to_string()],
shareable_fields: vec![],
field_directives: std::collections::HashMap::new(),
},
],
};
for fed_type in &metadata.types {
let key_directive = fed_type.keys.first().unwrap();
assert!(
key_directive.resolvable,
"Type {} should have resolvable key for HTTP fallback",
fed_type.name
);
}
}
#[test]
fn test_strategy_caching() {
use std::collections::HashMap;
let mut strategy_cache: HashMap<String, String> = HashMap::new();
if !strategy_cache.contains_key("User") {
let strategy = "local".to_string();
strategy_cache.insert("User".to_string(), strategy);
}
assert_eq!(
strategy_cache.get("User").unwrap(),
"local",
"Strategy should be cached for User type"
);
assert_eq!(strategy_cache.len(), 1, "Cache should have one entry");
assert!(strategy_cache.contains_key("User"), "User strategy should be cached");
}
#[test]
fn test_batch_latency_single_entity() {
use std::time::Instant;
use serde_json::json;
let start = Instant::now();
let _entity = json!({
"__typename": "User",
"id": "1",
"name": "Alice"
});
let elapsed = start.elapsed();
assert!(elapsed.as_millis() < 10);
}
#[test]
fn test_batch_latency_hundred_entities() {
use std::time::Instant;
use serde_json::json;
let start = Instant::now();
let mut entities = Vec::with_capacity(100);
for i in 0..100 {
entities.push(json!({
"__typename": "User",
"id": i.to_string(),
"name": format!("User{}", i)
}));
}
let elapsed = start.elapsed();
assert_eq!(entities.len(), 100);
assert!(elapsed.as_millis() < 100);
}
#[test]
fn test_batch_order_preservation() {
use serde_json::json;
let reps = vec!["1", "2", "3", "4", "5"];
let mut results = Vec::new();
for id in &reps {
results.push(json!({
"__typename": "User",
"id": (*id).to_string()
}));
}
for (idx, id) in reps.iter().enumerate() {
assert_eq!(results[idx]["id"].as_str().unwrap(), *id);
}
}
#[test]
fn test_batch_deduplication() {
use std::collections::HashSet;
let mut keys = vec!["id1", "id2", "id1", "id3", "id2"];
let unique_keys: HashSet<_> = keys.drain(..).collect();
assert_eq!(unique_keys.len(), 3);
assert!(unique_keys.contains("id1"));
assert!(unique_keys.contains("id2"));
assert!(unique_keys.contains("id3"));
}
#[test]
fn test_federation_spec_version_2() {
use fraiseql_core::federation::types::FederationMetadata;
let metadata = FederationMetadata {
enabled: true,
version: "v2".to_string(),
types: vec![],
};
assert!(metadata.enabled);
assert_eq!(metadata.version, "v2");
}
#[test]
fn test_entity_union_required() {
let schema = r#"
union _Entity = User | Order | Product
type User @key(fields: "id") {
id: ID!
}
"#;
assert!(schema.contains("_Entity"));
assert!(schema.contains("union"));
}
#[test]
fn test_federation_directive_fields() {
use fraiseql_core::federation::types::{FederatedType, FederationMetadata, KeyDirective};
let metadata = FederationMetadata {
enabled: true,
version: "v2".to_string(),
types: vec![FederatedType {
name: "User".to_string(),
keys: vec![KeyDirective {
fields: vec!["id".to_string()],
resolvable: true,
}],
is_extends: false,
external_fields: vec![],
shareable_fields: vec![],
field_directives: std::collections::HashMap::new(),
}],
};
let user_type = &metadata.types[0];
assert_eq!(user_type.keys.len(), 1);
assert_eq!(user_type.keys[0].fields, vec!["id".to_string()]);
assert!(user_type.keys[0].resolvable);
}
#[test]
fn test_federation_query_single_entity_postgres() {
use serde_json::json;
let _request = json!({
"query": "query($representations: [_Any!]!) { _entities(representations: $representations) { __typename ... on User { id name } } }",
"variables": {
"representations": [
{
"__typename": "User",
"id": "1"
}
]
}
});
let response = json!({
"data": {
"_entities": [
{
"__typename": "User",
"id": "1",
"name": "Alice"
}
]
}
});
assert_eq!(response["data"]["_entities"].as_array().unwrap().len(), 1);
}
#[test]
fn test_federation_query_batch_entities() {
use serde_json::json;
let request = json!({
"variables": {
"representations": [
{"__typename": "User", "id": "1"},
{"__typename": "User", "id": "2"},
{"__typename": "User", "id": "3"},
]
}
});
let response = json!({
"data": {
"_entities": [
{"__typename": "User", "id": "1", "name": "Alice"},
{"__typename": "User", "id": "2", "name": "Bob"},
{"__typename": "User", "id": "3", "name": "Charlie"},
]
}
});
let representations = request["variables"]["representations"].as_array().unwrap();
let entities = response["data"]["_entities"].as_array().unwrap();
assert_eq!(entities.len(), representations.len());
assert_eq!(entities.len(), 3);
}
#[test]
fn test_federation_partial_failure() {
use serde_json::json;
let response = json!({
"data": {
"_entities": [
{"__typename": "User", "id": "1", "name": "Alice"},
null, {"__typename": "User", "id": "3", "name": "Charlie"},
]
}
});
let entities = response["data"]["_entities"].as_array().unwrap();
assert_eq!(entities.len(), 3);
assert!(entities[0].is_object());
assert!(entities[1].is_null());
assert!(entities[2].is_object());
}