Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Changelog
Fixed
^^^^^
- Sort results in get_all_available_tags, so it can be used with pytest-xdist.
- `generate_random_value` generate coherent `ref` and `value` values for complex attributes. :pr:`30` :pr:`37`

[0.2.0] - 2025-08-12
--------------------
Expand Down
25 changes: 25 additions & 0 deletions scim2_tester/filling.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from scim2_models import ComplexAttribute
from scim2_models import Extension
from scim2_models import ExternalReference
from scim2_models import MultiValuedComplexAttribute
from scim2_models import Mutability
from scim2_models import Reference
from scim2_models import Resource
Expand Down Expand Up @@ -123,6 +124,9 @@ def generate_random_value(
elif isclass(field_type) and issubclass(field_type, Enum):
value = random.choice(list(field_type))

elif isclass(field_type) and issubclass(field_type, MultiValuedComplexAttribute):
value = fill_mvca_with_random_values(context, field_type()) # type: ignore[arg-type]

elif isclass(field_type) and issubclass(field_type, ComplexAttribute):
value = fill_with_random_values(context, field_type()) # type: ignore[arg-type]

Expand Down Expand Up @@ -172,3 +176,24 @@ def fill_with_random_values(
set_value_by_urn(obj, urn, value)

return obj


def fill_mvca_with_random_values(
context: "CheckContext",
obj: MultiValuedComplexAttribute,
) -> Resource[Any] | None:
"""Fill a MultiValuedComplexAttribute with random values.

For SCIM reference fields, correctly sets the value field to match
the ID extracted from the reference URL.
"""
fill_with_random_values(context, obj)
ref_type = type(obj).get_field_root_type("ref")
if (
get_origin(ref_type) is Reference
and get_args(ref_type)
and get_args(ref_type)[0] not in (URIReference, ExternalReference, Any)
and (ref := getattr(obj, "ref", None))
):
obj.value = ref.rsplit("/", 1)[-1]
return obj
24 changes: 24 additions & 0 deletions tests/test_filling.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,30 @@ def test_model_resolution_from_reference_type(testing_context):
assert result != Group


def test_generate_random_value_for_reference(testing_context, httpserver):
"""Validates random value generation for reference fields."""
group = Group()

# Mock HTTP response for user creation
user_data = {
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"id": "test-user-id",
"userName": "test-user",
"meta": {
"resourceType": "User",
"location": f"http://localhost:{httpserver.port}/Users/test-user-id",
},
}
httpserver.expect_request("/Users", method="POST").respond_with_json(
user_data, status=201
)

result = fill_with_random_values(testing_context, group)

assert len(result.members) == 1
assert result.members[0].value == result.members[0].ref.rsplit("/", 1)[-1]


def test_fill_with_empty_field_list(testing_context):
"""Confirms no fields are modified when empty field list provided."""
user = User(user_name="test")
Expand Down
Loading