|
11 | 11 | from infrahub_sdk.constants import InfrahubClientMode |
12 | 12 | from infrahub_sdk.exceptions import BranchNotFoundError, URLNotFoundError |
13 | 13 | from infrahub_sdk.node import InfrahubNode |
| 14 | +from infrahub_sdk.node.metadata import NodeMetadata, RelationshipMetadata |
14 | 15 | from infrahub_sdk.playback import JSONPlayback |
15 | 16 | from infrahub_sdk.recorder import JSONRecorder |
16 | 17 | from infrahub_sdk.schema import GenericSchema, NodeSchema, ProfileSchemaAPI |
@@ -328,6 +329,83 @@ async def create_person_with_tags(clt: InfrahubClient, nbr_tags: int) -> None: |
328 | 329 | ) |
329 | 330 | assert len(group.members.peers) == 2 |
330 | 331 |
|
| 332 | + async def test_node_metadata_not_fetched_by_default( |
| 333 | + self, client: InfrahubClient, base_dataset: None, cat_luna: InfrahubNode |
| 334 | + ) -> None: |
| 335 | + node = await client.get(kind=TESTING_CAT, id=cat_luna.id) |
| 336 | + assert node.get_node_metadata() is None |
| 337 | + |
| 338 | + async def test_node_metadata_with_get( |
| 339 | + self, client: InfrahubClient, base_dataset: None, cat_luna: InfrahubNode |
| 340 | + ) -> None: |
| 341 | + node = await client.get(kind=TESTING_CAT, id=cat_luna.id, include_metadata=True) |
| 342 | + |
| 343 | + metadata = node.get_node_metadata() |
| 344 | + assert isinstance(metadata, NodeMetadata) |
| 345 | + assert metadata.created_at is not None |
| 346 | + assert metadata.updated_at is not None |
| 347 | + assert metadata.created_by is not None |
| 348 | + assert metadata.created_by.display_label is not None |
| 349 | + assert metadata.updated_by is not None |
| 350 | + assert metadata.updated_by.display_label is not None |
| 351 | + |
| 352 | + async def test_node_metadata_with_all(self, client: InfrahubClient, base_dataset: None) -> None: |
| 353 | + nodes = await client.all(kind=TESTING_CAT, include_metadata=True) |
| 354 | + assert nodes |
| 355 | + |
| 356 | + for node in nodes: |
| 357 | + metadata = node.get_node_metadata() |
| 358 | + assert isinstance(metadata, NodeMetadata) |
| 359 | + assert metadata.created_at is not None |
| 360 | + assert metadata.updated_at is not None |
| 361 | + assert metadata.created_by is not None |
| 362 | + assert metadata.updated_by is not None |
| 363 | + |
| 364 | + async def test_attribute_metadata(self, client: InfrahubClient, base_dataset: None, cat_luna: InfrahubNode) -> None: |
| 365 | + node = await client.get(kind=TESTING_CAT, id=cat_luna.id, include_metadata=True) |
| 366 | + |
| 367 | + assert node.name.updated_at is not None |
| 368 | + assert node.name.updated_by is not None |
| 369 | + assert node.name.updated_by.display_label is not None |
| 370 | + assert node.breed.updated_at is not None |
| 371 | + assert node.breed.updated_by is not None |
| 372 | + |
| 373 | + async def test_relationship_metadata_cardinality_one( |
| 374 | + self, client: InfrahubClient, base_dataset: None, cat_luna: InfrahubNode |
| 375 | + ) -> None: |
| 376 | + node = await client.get(kind=TESTING_CAT, id=cat_luna.id, include_metadata=True) |
| 377 | + |
| 378 | + rel_metadata = node.owner.get_relationship_metadata() |
| 379 | + assert isinstance(rel_metadata, RelationshipMetadata) |
| 380 | + assert rel_metadata.updated_at is not None |
| 381 | + assert rel_metadata.updated_by is not None |
| 382 | + assert rel_metadata.updated_by.display_label is not None |
| 383 | + |
| 384 | + async def test_relationship_metadata_cardinality_many( |
| 385 | + self, client: InfrahubClient, base_dataset: None, person_ethan: InfrahubNode |
| 386 | + ) -> None: |
| 387 | + # Use include=["animals"] rather than prefetch_relationships=True. |
| 388 | + # prefetch_relationships=True recursively fetches each animal's peer relationships, |
| 389 | + # which in turn include person_ethan's null favorite_animal cardinality-one relationship. |
| 390 | + # The server GraphQL schema marks NestedEdgedTestingAnimal.node_metadata as non-nullable, |
| 391 | + # so requesting include_metadata=True on that null edge causes the server to silently |
| 392 | + # return empty edges. include=["animals"] fetches only the animals relationship shallowly. |
| 393 | + # Also exclude favorite_animal (null cardinality-one inbound) for the same reason. |
| 394 | + node = await client.get( |
| 395 | + kind=TESTING_PERSON, |
| 396 | + id=person_ethan.id, |
| 397 | + include_metadata=True, |
| 398 | + include=["animals"], |
| 399 | + exclude=["favorite_animal"], |
| 400 | + ) |
| 401 | + |
| 402 | + assert node.animals.peers |
| 403 | + for peer in node.animals.peers: |
| 404 | + rel_metadata = peer.get_relationship_metadata() |
| 405 | + assert isinstance(rel_metadata, RelationshipMetadata) |
| 406 | + assert rel_metadata.updated_at is not None |
| 407 | + assert rel_metadata.updated_by is not None |
| 408 | + |
331 | 409 | @pytest.mark.xfail(reason="https://github.com/opsmill/infrahub-sdk-python/issues/733") |
332 | 410 | async def test_recorder_with_playback_rewrite_host( |
333 | 411 | self, base_dataset: None, tmp_path: Path, infrahub_port: int |
|
0 commit comments