use fraiseql_core::federation::types::{FederatedType, FederationMetadata, KeyDirective};
#[test]
fn test_key_directive_single_field() {
let key = KeyDirective {
fields: vec!["id".to_string()],
resolvable: true,
};
assert_eq!(key.fields.len(), 1);
assert_eq!(key.fields[0], "id");
assert!(key.resolvable);
}
#[test]
fn test_key_directive_composite_key() {
let key = KeyDirective {
fields: vec!["organizationId".to_string(), "id".to_string()],
resolvable: true,
};
assert_eq!(key.fields.len(), 2);
assert_eq!(key.fields[0], "organizationId");
assert_eq!(key.fields[1], "id");
}
#[test]
fn test_key_directive_resolvable_flag() {
let resolvable = KeyDirective {
fields: vec!["id".to_string()],
resolvable: true,
};
let non_resolvable = KeyDirective {
fields: vec!["id".to_string()],
resolvable: false,
};
assert!(resolvable.resolvable);
assert!(!non_resolvable.resolvable);
}
#[test]
fn test_key_directive_multiple_keys() {
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,
},
KeyDirective {
fields: vec!["email".to_string()],
resolvable: true,
},
],
is_extends: false,
external_fields: vec![],
shareable_fields: vec![],
inaccessible_fields: vec![],
field_directives: std::collections::HashMap::new(),
type_shareable: false,
}],
remote_subscription_fields: std::collections::HashMap::new(),
};
let user_type = &metadata.types[0];
assert_eq!(user_type.keys.len(), 2);
assert_eq!(user_type.keys[0].fields[0], "id");
assert_eq!(user_type.keys[1].fields[0], "email");
}
#[test]
fn test_external_field_single() {
let fed_type = FederatedType {
name: "User".to_string(),
keys: vec![KeyDirective {
fields: vec!["id".to_string()],
resolvable: true,
}],
is_extends: true,
external_fields: vec!["email".to_string()],
shareable_fields: vec![],
inaccessible_fields: vec![],
field_directives: std::collections::HashMap::new(),
type_shareable: false,
};
assert!(fed_type.external_fields.contains(&"email".to_string()));
assert_eq!(fed_type.external_fields.len(), 1);
}
#[test]
fn test_external_field_multiple() {
let fed_type = FederatedType {
name: "Order".to_string(),
keys: vec![KeyDirective {
fields: vec!["id".to_string()],
resolvable: true,
}],
is_extends: true,
external_fields: vec!["customerId".to_string(), "customerEmail".to_string()],
shareable_fields: vec![],
inaccessible_fields: vec![],
field_directives: std::collections::HashMap::new(),
type_shareable: false,
};
assert_eq!(fed_type.external_fields.len(), 2);
assert!(fed_type.external_fields.contains(&"customerId".to_string()));
assert!(fed_type.external_fields.contains(&"customerEmail".to_string()));
}
#[test]
fn test_external_field_key_field() {
let fed_type = 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![],
inaccessible_fields: vec![],
field_directives: std::collections::HashMap::new(),
type_shareable: false,
};
assert!(fed_type.external_fields.contains(&"id".to_string()));
}
#[test]
fn test_extends_directive_owned_entity() {
let fed_type = FederatedType {
name: "User".to_string(),
keys: vec![KeyDirective {
fields: vec!["id".to_string()],
resolvable: true,
}],
is_extends: false,
external_fields: vec![],
shareable_fields: vec![],
inaccessible_fields: vec![],
field_directives: std::collections::HashMap::new(),
type_shareable: false,
};
assert!(!fed_type.is_extends, "Local entity should not be extended");
}
#[test]
fn test_extends_directive_extended_entity() {
let fed_type = FederatedType {
name: "User".to_string(),
keys: vec![KeyDirective {
fields: vec!["id".to_string()],
resolvable: true,
}],
is_extends: true,
external_fields: vec!["email".to_string()],
shareable_fields: vec![],
inaccessible_fields: vec![],
field_directives: std::collections::HashMap::new(),
type_shareable: false,
};
assert!(fed_type.is_extends, "Extended entity should have is_extends=true");
}
#[test]
fn test_extends_with_external_fields() {
let fed_type = FederatedType {
name: "Order".to_string(),
keys: vec![KeyDirective {
fields: vec!["id".to_string()],
resolvable: true,
}],
is_extends: true,
external_fields: vec!["customerId".to_string()],
shareable_fields: vec!["total".to_string()],
inaccessible_fields: Vec::new(),
field_directives: std::collections::HashMap::new(),
type_shareable: false,
};
assert!(fed_type.is_extends);
assert!(!fed_type.external_fields.is_empty());
assert_eq!(fed_type.external_fields[0], "customerId");
}
#[test]
fn test_shareable_field_single() {
let fed_type = FederatedType {
name: "User".to_string(),
keys: vec![KeyDirective {
fields: vec!["id".to_string()],
resolvable: true,
}],
is_extends: false,
external_fields: vec![],
shareable_fields: vec!["email".to_string()],
inaccessible_fields: Vec::new(),
field_directives: std::collections::HashMap::new(),
type_shareable: false,
};
assert!(fed_type.shareable_fields.contains(&"email".to_string()));
}
#[test]
fn test_shareable_field_multiple() {
let fed_type = FederatedType {
name: "Product".to_string(),
keys: vec![KeyDirective {
fields: vec!["id".to_string()],
resolvable: true,
}],
is_extends: false,
external_fields: vec![],
shareable_fields: vec!["name".to_string(), "description".to_string()],
inaccessible_fields: Vec::new(),
field_directives: std::collections::HashMap::new(),
type_shareable: false,
};
assert_eq!(fed_type.shareable_fields.len(), 2);
assert!(fed_type.shareable_fields.contains(&"name".to_string()));
assert!(fed_type.shareable_fields.contains(&"description".to_string()));
}
#[test]
fn test_shareable_field_in_extended_type() {
let fed_type = FederatedType {
name: "Order".to_string(),
keys: vec![KeyDirective {
fields: vec!["id".to_string()],
resolvable: true,
}],
is_extends: true,
external_fields: vec!["customerId".to_string()],
shareable_fields: vec!["status".to_string()],
inaccessible_fields: Vec::new(),
field_directives: std::collections::HashMap::new(),
type_shareable: false,
};
assert!(fed_type.is_extends);
assert!(fed_type.shareable_fields.contains(&"status".to_string()));
}
#[test]
fn test_composite_key_multi_tenant() {
let fed_type = FederatedType {
name: "TenantUser".to_string(),
keys: vec![KeyDirective {
fields: vec!["tenantId".to_string(), "id".to_string()],
resolvable: true,
}],
is_extends: false,
external_fields: vec![],
shareable_fields: vec![],
inaccessible_fields: vec![],
field_directives: std::collections::HashMap::new(),
type_shareable: false,
};
assert_eq!(fed_type.keys[0].fields.len(), 2);
assert_eq!(fed_type.keys[0].fields[0], "tenantId");
assert_eq!(fed_type.keys[0].fields[1], "id");
}
#[test]
fn test_composite_key_ordering_matters() {
let key1 = KeyDirective {
fields: vec!["organizationId".to_string(), "userId".to_string()],
resolvable: true,
};
let key2 = KeyDirective {
fields: vec!["userId".to_string(), "organizationId".to_string()],
resolvable: true,
};
assert_ne!(key1.fields, key2.fields, "Key field order matters");
}
#[test]
fn test_composite_key_uniqueness() {
let key = KeyDirective {
fields: vec!["organizationId".to_string(), "id".to_string()],
resolvable: true,
};
assert_eq!(key.fields.len(), 2);
assert_ne!(key.fields[0], key.fields[1], "Key fields must be unique");
}
#[test]
fn test_federation_metadata_version() {
let metadata = FederationMetadata {
enabled: true,
version: "v2".to_string(),
types: vec![],
remote_subscription_fields: std::collections::HashMap::new(),
};
assert_eq!(metadata.version, "v2");
assert!(metadata.enabled);
}
#[test]
fn test_federation_metadata_enabled_flag() {
let enabled = FederationMetadata {
enabled: true,
version: "v2".to_string(),
types: vec![],
remote_subscription_fields: std::collections::HashMap::new(),
};
let disabled = FederationMetadata {
enabled: false,
version: "v2".to_string(),
types: vec![],
remote_subscription_fields: std::collections::HashMap::new(),
};
assert!(enabled.enabled);
assert!(!disabled.enabled);
}
#[test]
fn test_federation_metadata_multiple_types() {
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![],
inaccessible_fields: vec![],
field_directives: std::collections::HashMap::new(),
type_shareable: false,
},
FederatedType {
name: "Order".to_string(),
keys: vec![KeyDirective {
fields: vec!["id".to_string()],
resolvable: true,
}],
is_extends: false,
external_fields: vec![],
shareable_fields: vec![],
inaccessible_fields: vec![],
field_directives: std::collections::HashMap::new(),
type_shareable: false,
},
],
remote_subscription_fields: std::collections::HashMap::new(),
};
assert_eq!(metadata.types.len(), 2);
assert_eq!(metadata.types[0].name, "User");
assert_eq!(metadata.types[1].name, "Order");
}
#[test]
fn test_field_cannot_be_both_external_and_key() {
let fed_type = 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![],
inaccessible_fields: vec![],
field_directives: std::collections::HashMap::new(),
type_shareable: false,
};
assert!(fed_type.external_fields.contains(&"id".to_string()));
}
#[test]
fn test_owned_type_cannot_have_external_fields() {
let fed_type = FederatedType {
name: "User".to_string(),
keys: vec![KeyDirective {
fields: vec!["id".to_string()],
resolvable: true,
}],
is_extends: false,
external_fields: vec![], shareable_fields: vec![],
inaccessible_fields: vec![],
field_directives: std::collections::HashMap::new(),
type_shareable: false,
};
assert!(!fed_type.is_extends);
assert!(fed_type.external_fields.is_empty());
}
#[test]
fn test_key_directive_requires_fields() {
let key = KeyDirective {
fields: vec!["id".to_string()],
resolvable: true,
};
assert!(!key.fields.is_empty(), "Key directive must have fields");
}
#[test]
fn test_resolvable_key_vs_non_resolvable() {
let resolvable = KeyDirective {
fields: vec!["id".to_string()],
resolvable: true,
};
let non_resolvable = KeyDirective {
fields: vec!["id".to_string()],
resolvable: false,
};
assert!(resolvable.resolvable);
assert!(!non_resolvable.resolvable);
}
#[test]
fn test_extended_type_must_have_key() {
let fed_type = FederatedType {
name: "Order".to_string(),
keys: vec![KeyDirective {
fields: vec!["id".to_string()],
resolvable: true,
}],
is_extends: true,
external_fields: vec!["customerId".to_string()],
shareable_fields: vec![],
inaccessible_fields: vec![],
field_directives: std::collections::HashMap::new(),
type_shareable: false,
};
assert!(fed_type.is_extends);
assert!(!fed_type.keys.is_empty(), "Extended types must have at least one key");
}