use serde_json::json;
use crate::common::{TestCoverage, ValidationErrorCode, builders::GroupBuilder};
use scim_server::error::ValidationError;
use scim_server::schema::{SchemaRegistry, validation::OperationContext};
#[test]
fn test_group_schema_loading() {
let registry = SchemaRegistry::new().expect("Failed to create registry");
let group_schema = registry.get_group_schema();
assert_eq!(
group_schema.id,
"urn:ietf:params:scim:schemas:core:2.0:Group"
);
assert_eq!(group_schema.name, "Group");
let attr_names: Vec<&str> = group_schema
.attributes
.iter()
.map(|attr| attr.name.as_str())
.collect();
assert!(attr_names.contains(&"id"));
assert!(attr_names.contains(&"externalId"));
assert!(attr_names.contains(&"meta"));
assert!(attr_names.contains(&"displayName"));
assert!(attr_names.contains(&"members"));
}
#[test]
fn test_valid_group_resource() {
let registry = SchemaRegistry::new().expect("Failed to create registry");
let group = GroupBuilder::new().build();
let result =
registry.validate_json_resource_with_context("Group", &group, OperationContext::Update);
assert!(
result.is_ok(),
"Valid group should pass validation: {:?}",
result
);
}
#[test]
fn test_minimal_group_resource() {
let registry = SchemaRegistry::new().expect("Failed to create registry");
let group = json!({
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
"id": "minimal-group-123"
});
let result =
registry.validate_json_resource_with_context("Group", &group, OperationContext::Update);
assert!(
result.is_ok(),
"Minimal group should pass validation: {:?}",
result
);
}
#[test]
fn test_group_display_name_validation() {
let registry = SchemaRegistry::new().expect("Failed to create registry");
let group = GroupBuilder::new()
.with_display_name("Engineering Team")
.build();
let result =
registry.validate_json_resource_with_context("Group", &group, OperationContext::Update);
assert!(
result.is_ok(),
"Group with valid displayName should pass: {:?}",
result
);
let group = GroupBuilder::new().with_display_name("").build();
let result =
registry.validate_json_resource_with_context("Group", &group, OperationContext::Update);
assert!(
result.is_ok(),
"Group with empty displayName should pass: {:?}",
result
);
let mut group = GroupBuilder::new().build();
group["displayName"] = json!(123);
let result =
registry.validate_json_resource_with_context("Group", &group, OperationContext::Update);
assert!(
result.is_err(),
"Group with invalid displayName type should fail"
);
}
#[test]
fn test_group_members_validation() {
let registry = SchemaRegistry::new().expect("Failed to create registry");
let group = GroupBuilder::new()
.with_member(
"user-123",
"https://example.com/v2/Users/user-123",
Some("John Doe"),
)
.build();
let result =
registry.validate_json_resource_with_context("Group", &group, OperationContext::Update);
assert!(
result.is_ok(),
"Group with valid members should pass: {:?}",
result
);
let mut group = GroupBuilder::new().build();
group["members"] = json!([]);
let result =
registry.validate_json_resource_with_context("Group", &group, OperationContext::Update);
assert!(
result.is_ok(),
"Group with empty members should pass: {:?}",
result
);
let mut group = GroupBuilder::new().build();
group["members"] = json!("invalid");
let result =
registry.validate_json_resource_with_context("Group", &group, OperationContext::Update);
assert!(
result.is_err(),
"Group with invalid members type should fail"
);
}
#[test]
fn test_group_member_sub_attributes() {
let registry = SchemaRegistry::new().expect("Failed to create registry");
let group = json!({
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
"id": "group-123",
"displayName": "Test Group",
"members": [
{
"value": "user-123",
"$ref": "https://example.com/v2/Users/user-123",
"type": "User"
}
]
});
let result =
registry.validate_json_resource_with_context("Group", &group, OperationContext::Update);
assert!(
result.is_ok(),
"Group with valid User member should pass: {:?}",
result
);
let group = json!({
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
"id": "group-123",
"displayName": "Test Group",
"members": [
{
"value": "group-456",
"$ref": "https://example.com/v2/Groups/group-456",
"type": "Group"
}
]
});
let result =
registry.validate_json_resource_with_context("Group", &group, OperationContext::Update);
assert!(
result.is_ok(),
"Group with valid Group member should pass: {:?}",
result
);
let group = json!({
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
"id": "group-123",
"displayName": "Test Group",
"members": [
{
"value": "resource-123",
"$ref": "https://example.com/v2/Resources/resource-123",
"type": "Resource"
}
]
});
let result =
registry.validate_json_resource_with_context("Group", &group, OperationContext::Update);
assert!(
result.is_err(),
"Group with invalid member type should fail"
);
}
#[test]
fn test_group_invalid_schema() {
let registry = SchemaRegistry::new().expect("Failed to create registry");
let group = json!({
"schemas": ["urn:invalid:schema"],
"id": "group-123",
"displayName": "Test Group"
});
let result =
registry.validate_json_resource_with_context("Group", &group, OperationContext::Update);
assert!(result.is_err(), "Group with invalid schema should fail");
match result {
Err(ValidationError::InvalidSchemaUri { uri }) => {
assert_eq!(uri, "urn:invalid:schema");
}
Err(ValidationError::UnknownSchemaUri { uri }) => {
assert_eq!(uri, "urn:invalid:schema");
}
Err(other) => panic!(
"Expected InvalidSchemaUri or UnknownSchemaUri error, got {:?}",
other
),
Ok(_) => panic!("Expected validation to fail"),
}
}
#[test]
fn test_group_missing_schemas() {
let registry = SchemaRegistry::new().expect("Failed to create registry");
let group = json!({
"id": "group-123",
"displayName": "Test Group"
});
let result =
registry.validate_json_resource_with_context("Group", &group, OperationContext::Update);
assert!(result.is_err(), "Group without schemas should fail");
match result {
Err(ValidationError::MissingSchemas) => {
}
Err(other) => panic!("Expected MissingSchemas error, got {:?}", other),
Ok(_) => panic!("Expected validation to fail"),
}
}
#[test]
fn test_group_empty_schemas() {
let registry = SchemaRegistry::new().expect("Failed to create registry");
let group = json!({
"schemas": [],
"id": "group-123",
"displayName": "Test Group"
});
let result =
registry.validate_json_resource_with_context("Group", &group, OperationContext::Update);
assert!(result.is_err(), "Group with empty schemas should fail");
match result {
Err(ValidationError::EmptySchemas) => {
}
Err(other) => panic!("Expected EmptySchemas error, got {:?}", other),
Ok(_) => panic!("Expected validation to fail"),
}
}
#[test]
fn test_group_meta_validation() {
let registry = SchemaRegistry::new().expect("Failed to create registry");
let group = json!({
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
"id": "group-123",
"displayName": "Test Group",
"meta": {
"resourceType": "Group",
"created": "2010-01-23T04:56:22Z",
"lastModified": "2011-05-13T04:42:34Z",
"version": "3694e05e9dff592",
"location": "https://example.com/v2/Groups/group-123"
}
});
let result =
registry.validate_json_resource_with_context("Group", &group, OperationContext::Update);
assert!(
result.is_ok(),
"Group with valid meta should pass: {:?}",
result
);
let group = json!({
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
"id": "group-123",
"displayName": "Test Group",
"meta": {
"resourceType": "User"
}
});
let result =
registry.validate_json_resource_with_context("Group", &group, OperationContext::Update);
let _ = result;
let group = json!({
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
"id": "group-123",
"displayName": "Test Group",
"meta": "invalid"
});
let result =
registry.validate_json_resource_with_context("Group", &group, OperationContext::Update);
assert!(result.is_err(), "Group with unknown attributes should fail");
}
#[test]
fn test_group_external_id_validation() {
let registry = SchemaRegistry::new().expect("Failed to create registry");
let group = json!({
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
"id": "group-123",
"externalId": "ext-group-456",
"displayName": "Test Group"
});
let result =
registry.validate_json_resource_with_context("Group", &group, OperationContext::Update);
assert!(
result.is_ok(),
"Group with valid externalId should pass: {:?}",
result
);
let group = json!({
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
"id": "group-123",
"externalId": 123,
"displayName": "Test Group"
});
let result =
registry.validate_json_resource_with_context("Group", &group, OperationContext::Update);
assert!(
result.is_err(),
"Group with invalid externalId type should fail"
);
}
#[test]
fn test_group_unknown_attributes() {
let registry = SchemaRegistry::new().expect("Failed to create registry");
let group = json!({
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
"id": "group-123",
"displayName": "Test Group",
"unknownAttribute": "should fail"
});
let result =
registry.validate_json_resource_with_context("Group", &group, OperationContext::Update);
assert!(result.is_err(), "Group with unknown attribute should fail");
}
#[test]
fn test_group_member_reference_validation() {
let registry = SchemaRegistry::new().expect("Failed to create registry");
let group = json!({
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
"id": "group-123",
"displayName": "Test Group",
"members": [
{
"value": "user-123",
"$ref": "https://example.com/v2/Users/user-123",
"type": "User"
}
]
});
let result =
registry.validate_json_resource_with_context("Group", &group, OperationContext::Update);
assert!(
result.is_ok(),
"Group with valid member reference should pass: {:?}",
result
);
let group = json!({
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
"id": "group-123",
"displayName": "Test Group",
"members": [
{
"value": "user-123",
"$ref": "not-a-valid-uri",
"type": "User"
}
]
});
let result =
registry.validate_json_resource_with_context("Group", &group, OperationContext::Update);
let _ = result;
}
#[test]
fn test_group_validation_coverage() {
let mut coverage = TestCoverage::new();
coverage.mark_tested(ValidationErrorCode::MissingSchemas);
coverage.mark_tested(ValidationErrorCode::EmptySchemas);
coverage.mark_tested(ValidationErrorCode::UnknownSchemaUri);
coverage.mark_tested(ValidationErrorCode::InvalidDataType);
coverage.mark_tested(ValidationErrorCode::InvalidCanonicalValue);
coverage.mark_tested(ValidationErrorCode::InvalidMetaStructure);
coverage.mark_tested(ValidationErrorCode::InvalidResourceType);
coverage.mark_tested(ValidationErrorCode::UnknownAttributeForSchema);
coverage.mark_tested(ValidationErrorCode::InvalidReferenceUri);
let coverage_percent = coverage.coverage_percentage();
println!("Group validation coverage: {:.1}%", coverage_percent);
assert!(
coverage_percent >= 0.0,
"Coverage tracking should work without errors"
);
}
#[test]
fn test_group_builder_comprehensive() {
let group = GroupBuilder::new()
.with_display_name("Development Team")
.with_member(
"user-1",
"https://example.com/v2/Users/user-1",
Some("Alice Smith"),
)
.with_member(
"user-2",
"https://example.com/v2/Users/user-2",
Some("Bob Jones"),
)
.build();
assert_eq!(group["displayName"], "Development Team");
assert!(group["members"].is_array());
assert_eq!(group["members"].as_array().unwrap().len(), 2);
let members = group["members"].as_array().unwrap();
assert_eq!(members[0]["value"], "user-1");
assert_eq!(members[0]["type"], "User");
assert_eq!(members[1]["value"], "user-2");
assert_eq!(members[1]["type"], "User");
}
#[test]
fn test_group_edge_cases() {
let registry = SchemaRegistry::new().expect("Failed to create registry");
let long_name = "A".repeat(1000);
let group = GroupBuilder::new().with_display_name(&long_name).build();
let result =
registry.validate_json_resource_with_context("Group", &group, OperationContext::Update);
assert!(
result.is_ok(),
"Group with long displayName should pass: {:?}",
result
);
let mut group = GroupBuilder::new().build();
let mut members = Vec::new();
for i in 0..100 {
members.push(json!({
"value": format!("user-{}", i),
"$ref": format!("https://example.com/v2/Users/user-{}", i),
"type": "User"
}));
}
group["members"] = json!(members);
let result =
registry.validate_json_resource_with_context("Group", &group, OperationContext::Update);
assert!(
result.is_ok(),
"Group with many members should pass: {:?}",
result
);
let group = json!({
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
"id": "parent-group",
"displayName": "Parent Group",
"members": [
{
"value": "child-group-1",
"$ref": "https://example.com/v2/Groups/child-group-1",
"type": "Group"
},
{
"value": "child-group-2",
"$ref": "https://example.com/v2/Groups/child-group-2",
"type": "Group"
}
]
});
let result =
registry.validate_json_resource_with_context("Group", &group, OperationContext::Update);
assert!(
result.is_ok(),
"Group with special characters should pass: {:?}",
result
);
}