From c1fc2ef2c86ceb8fc748eb3ca61fc850dad42a23 Mon Sep 17 00:00:00 2001 From: Damien Garros Date: Sat, 4 Jan 2025 12:13:21 +0100 Subject: [PATCH 1/2] Add some integration tests in test_node and test_infrahub_client --- infrahub_sdk/schema/main.py | 3 +- infrahub_sdk/testing/schemas/animal.py | 181 +++++++++++ infrahub_sdk/testing/schemas/car_person.py | 99 +++++- tests/integration/test_infrahub_client.py | 356 +++++++++------------ tests/integration/test_node.py | 122 ++++--- 5 files changed, 480 insertions(+), 281 deletions(-) create mode 100644 infrahub_sdk/testing/schemas/animal.py diff --git a/infrahub_sdk/schema/main.py b/infrahub_sdk/schema/main.py index 7f6c7d66..069f744f 100644 --- a/infrahub_sdk/schema/main.py +++ b/infrahub_sdk/schema/main.py @@ -259,6 +259,8 @@ class BaseSchema(BaseModel): description: str | None = None include_in_menu: bool | None = None menu_placement: str | None = None + display_labels: list[str] | None = None + human_friendly_id: list[str] | None = None icon: str | None = None uniqueness_constraints: list[list[str]] | None = None documentation: str | None = None @@ -286,7 +288,6 @@ class BaseNodeSchema(BaseSchema): inherit_from: list[str] = Field(default_factory=list) branch: BranchSupportType | None = None default_filter: str | None = None - human_friendly_id: list[str] | None = None generate_profile: bool | None = None parent: str | None = None children: str | None = None diff --git a/infrahub_sdk/testing/schemas/animal.py b/infrahub_sdk/testing/schemas/animal.py new file mode 100644 index 00000000..636588d4 --- /dev/null +++ b/infrahub_sdk/testing/schemas/animal.py @@ -0,0 +1,181 @@ +import pytest + +from infrahub_sdk import InfrahubClient +from infrahub_sdk.exceptions import GraphQLError +from infrahub_sdk.node import InfrahubNode +from infrahub_sdk.schema.main import ( + AttributeKind, + GenericSchema, + NodeSchema, + RelationshipDirection, + RelationshipKind, + SchemaRoot, +) +from infrahub_sdk.schema.main import AttributeSchema as Attr +from infrahub_sdk.schema.main import RelationshipSchema as Rel + +NAMESPACE = "Testing" + +TESTING_ANIMAL = f"{NAMESPACE}Animal" +TESTING_CAT = f"{NAMESPACE}Cat" +TESTING_DOG = f"{NAMESPACE}Dog" +TESTING_PERSON = f"{NAMESPACE}Person" + + +class SchemaAnimal: + @pytest.fixture(scope="class") + def schema_animal(self) -> GenericSchema: + return GenericSchema( + name="Animal", + namespace=NAMESPACE, + include_in_menu=True, + human_friendly_id=["owner__name__value", "name__value"], + uniqueness_constraints=[ + ["owner", "name__value"], + ], + attributes=[ + Attr(name="name", kind=AttributeKind.TEXT), + Attr(name="weight", kind=AttributeKind.NUMBER, optional=True), + ], + relationships=[ + Rel( + name="owner", + kind=RelationshipKind.GENERIC, + optional=False, + peer=TESTING_PERSON, + cardinality="one", + identifier="person__animal", + direction=RelationshipDirection.OUTBOUND, + ), + Rel( + name="best_friend", + kind=RelationshipKind.GENERIC, + optional=True, + peer=TESTING_PERSON, + cardinality="one", + identifier="person__animal_friend", + direction=RelationshipDirection.OUTBOUND, + ), + ], + ) + + @pytest.fixture(scope="class") + def schema_dog(self) -> NodeSchema: + return NodeSchema( + name="Dog", + namespace=NAMESPACE, + include_in_menu=True, + inherit_from=[TESTING_ANIMAL], + display_labels=["name__value", "breed__value"], + attributes=[ + Attr(name="breed", kind=AttributeKind.TEXT, optional=False), + Attr(name="color", kind=AttributeKind.COLOR, default_value="#444444", optional=True), + ], + ) + + @pytest.fixture(scope="class") + def schema_cat(self) -> NodeSchema: + return NodeSchema( + name="Cat", + namespace=NAMESPACE, + include_in_menu=True, + inherit_from=[TESTING_ANIMAL], + display_labels=["name__value", "breed__value", "color__value"], + attributes=[ + Attr(name="breed", kind=AttributeKind.TEXT, optional=False), + Attr(name="color", kind=AttributeKind.COLOR, default_value="#555555", optional=True), + ], + ) + + @pytest.fixture(scope="class") + def schema_person(self) -> NodeSchema: + return NodeSchema( + name="Person", + namespace=NAMESPACE, + include_in_menu=True, + display_labels=["name__value"], + default_filter="name__value", + human_friendly_id=["name__value"], + attributes=[ + Attr(name="name", kind=AttributeKind.TEXT, unique=True), + Attr(name="height", kind=AttributeKind.NUMBER, optional=True), + ], + relationships=[ + Rel( + name="animals", + peer=TESTING_ANIMAL, + identifier="person__animal", + cardinality="many", + direction=RelationshipDirection.INBOUND, + ), + Rel( + name="best_friends", + peer=TESTING_ANIMAL, + identifier="person__animal_friend", + cardinality="many", + direction=RelationshipDirection.INBOUND, + ), + ], + ) + + @pytest.fixture(scope="class") + def schema_base( + self, + schema_animal: GenericSchema, + schema_person: NodeSchema, + schema_cat: NodeSchema, + schema_dog: NodeSchema, + ) -> SchemaRoot: + return SchemaRoot(version="1.0", generics=[schema_animal], nodes=[schema_person, schema_cat, schema_dog]) + + @pytest.fixture(scope="class") + async def load_schema(self, client: InfrahubClient, schema_base: SchemaRoot) -> None: + resp = await client.schema.load(schemas=[schema_base.to_schema_dict()], wait_until_converged=True) + if resp.errors: + raise GraphQLError(errors=[resp.errors]) + + @pytest.fixture(scope="class") + async def person_liam(self, client: InfrahubClient) -> InfrahubNode: + obj = await client.create(kind=TESTING_PERSON, name="Liam Walker", height=178) + await obj.save() + return obj + + @pytest.fixture(scope="class") + async def person_sophia(self, client: InfrahubClient) -> InfrahubNode: + obj = await client.create(kind=TESTING_PERSON, name="Sophia Walker", height=168) + await obj.save() + return obj + + @pytest.fixture(scope="class") + async def person_ethan(self, client: InfrahubClient) -> InfrahubNode: + obj = await client.create(kind=TESTING_PERSON, name="Ethan Carter", height=185) + await obj.save() + return obj + + @pytest.fixture(scope="class") + async def cat_bella(self, client: InfrahubClient, person_ethan: InfrahubNode) -> InfrahubNode: + obj = await client.create(kind=TESTING_CAT, name="Bella", breed="Bengal", color="#123456", owner=person_ethan) + await obj.save() + return obj + + @pytest.fixture(scope="class") + async def cat_luna(self, client: InfrahubClient, person_ethan: InfrahubNode) -> InfrahubNode: + obj = await client.create(kind=TESTING_CAT, name="Luna", breed="Siamese", color="#FFFFFF", owner=person_ethan) + await obj.save() + return obj + + @pytest.fixture(scope="class") + async def dog_daisy(self, client: InfrahubClient, person_ethan: InfrahubNode) -> InfrahubNode: + obj = await client.create( + kind=TESTING_DOG, name="Daisy", breed="French Bulldog", color="#7B7D7D", owner=person_ethan + ) + await obj.save() + return obj + + @pytest.fixture(scope="class") + async def dog_rocky(self, client: InfrahubClient, person_sophia: InfrahubNode) -> InfrahubNode: + obj = await client.create( + kind=TESTING_DOG, name="Rocky", breed="German Shepherd", color="#784212", owner=person_sophia + ) + await obj.save() + return obj diff --git a/infrahub_sdk/testing/schemas/car_person.py b/infrahub_sdk/testing/schemas/car_person.py index 632b7ad9..ce3f2f64 100644 --- a/infrahub_sdk/testing/schemas/car_person.py +++ b/infrahub_sdk/testing/schemas/car_person.py @@ -1,16 +1,43 @@ +from __future__ import annotations + +from dataclasses import asdict, dataclass +from typing import TYPE_CHECKING + import pytest -from infrahub_sdk import InfrahubClient -from infrahub_sdk.node import InfrahubNode from infrahub_sdk.schema.main import AttributeKind, NodeSchema, RelationshipKind, SchemaRoot from infrahub_sdk.schema.main import AttributeSchema as Attr from infrahub_sdk.schema.main import RelationshipSchema as Rel +if TYPE_CHECKING: + from infrahub_sdk import InfrahubClient + from infrahub_sdk.node import InfrahubNode + NAMESPACE = "Testing" TESTING_MANUFACTURER = f"{NAMESPACE}Manufacturer" TESTING_PERSON = f"{NAMESPACE}Person" TESTING_CAR = f"{NAMESPACE}Car" +BUILTIN_TAG = "BuiltinTag" + + +@dataclass +class TestingPersonData: + name: str + kind: str = TESTING_PERSON + + +@dataclass +class TestingManufacturerData: + name: str + kind: str = TESTING_MANUFACTURER + + +@dataclass +class TestingCarData: + name: str + color: str | None = None + kind: str = TESTING_CAR class SchemaCarPerson: @@ -63,6 +90,12 @@ def schema_car_base(self) -> NodeSchema: cardinality="one", identifier="car__manufacturer", ), + Rel( + name="tags", + optional=True, + peer=BUILTIN_TAG, + cardinality="many", + ), ], ) @@ -107,6 +140,68 @@ def schema_base( ) -> SchemaRoot: return SchemaRoot(version="1.0", nodes=[schema_car_base, schema_person_base, schema_manufacturer_base]) + @pytest.fixture(scope="class") + async def person_joe_data(self) -> TestingPersonData: + return TestingPersonData(name="Joe Doe") + + @pytest.fixture(scope="class") + async def person_jane_data(self) -> TestingPersonData: + return TestingPersonData(name="Jane Doe") + + @pytest.fixture(scope="class") + async def manufacturer_vw_data(self) -> TestingManufacturerData: + return TestingManufacturerData(name="Volkswagen") + + @pytest.fixture(scope="class") + async def manufacturer_renault_data(self) -> TestingManufacturerData: + return TestingManufacturerData(name="Renault") + + @pytest.fixture(scope="class") + async def manufacturer_mercedes_data(self) -> TestingManufacturerData: + return TestingManufacturerData(name="Mercedes") + + @pytest.fixture(scope="class") + async def car_golf_data(self) -> TestingCarData: + return TestingCarData(name="Golf", color="Black") + + @pytest.fixture(scope="class") + async def person_joe(self, client: InfrahubClient, person_joe_data: TestingPersonData) -> InfrahubNode: + obj = await client.create(**asdict(person_joe_data)) + await obj.save() + return obj + + @pytest.fixture(scope="class") + async def manufacturer_mercedes( + self, client: InfrahubClient, manufacturer_mercedes_data: TestingManufacturerData + ) -> InfrahubNode: + obj = await client.create(**asdict(manufacturer_mercedes_data)) + await obj.save() + return obj + + @pytest.fixture(scope="class") + async def car_golf( + self, + client: InfrahubClient, + car_golf_data: TestingCarData, + manufacturer_mercedes: InfrahubNode, + person_joe: InfrahubNode, + ) -> InfrahubNode: + obj = await client.create(**asdict(car_golf_data), manufacturer=manufacturer_mercedes, owner=person_joe) + await obj.save() + return obj + + @pytest.fixture(scope="class") + async def tag_blue(self, client: InfrahubClient) -> InfrahubNode: + obj = await client.create(kind=BUILTIN_TAG, name="Blue") + await obj.save() + return obj + + @pytest.fixture(scope="class") + async def tag_red(self, client: InfrahubClient) -> InfrahubNode: + obj = await client.create(kind=BUILTIN_TAG, name="Red") + await obj.save() + return obj + async def create_persons(self, client: InfrahubClient, branch: str) -> list[InfrahubNode]: john = await client.create(kind=TESTING_PERSON, name="John Doe", branch=branch) await john.save() diff --git a/tests/integration/test_infrahub_client.py b/tests/integration/test_infrahub_client.py index 0b6f7e4a..5115ffc2 100644 --- a/tests/integration/test_infrahub_client.py +++ b/tests/integration/test_infrahub_client.py @@ -1,186 +1,146 @@ -# from __future__ import annotations -# -# from typing import TYPE_CHECKING -# -# import pytest -# from infrahub.core import registry -# from infrahub.core.initialization import create_branch -# from infrahub.core.node import Node -# from infrahub.server import app -# -# from infrahub_sdk import Config, InfrahubClient -# from infrahub_sdk.branch import BranchData -# from infrahub_sdk.constants import InfrahubClientMode -# from infrahub_sdk.exceptions import BranchNotFoundError -# from infrahub_sdk.node import InfrahubNode -# from infrahub_sdk.playback import JSONPlayback -# from infrahub_sdk.recorder import JSONRecorder -# from infrahub_sdk.schema import ProfileSchema -# -# from .conftest import InfrahubTestClient -# -# if TYPE_CHECKING: -# from pathlib import Path -# -# from infrahub.database import InfrahubDatabase -# -# -# # pylint: disable=unused-argument -# -# -# class TestInfrahubClient: -# @pytest.fixture(scope="class") -# async def test_client(self) -> InfrahubTestClient: -# registry.delete_all() -# -# return InfrahubTestClient(app) -# -# @pytest.fixture -# def client(self, test_client: InfrahubTestClient) -> InfrahubClient: -# config = Config(username="admin", password="infrahub", requester=test_client.async_request) -# return InfrahubClient(config=config) -# -# @pytest.fixture(scope="class") -# async def base_dataset(self, db: InfrahubDatabase, test_client: InfrahubTestClient, builtin_org_schema): -# config = Config(username="admin", password="infrahub", requester=test_client.async_request) -# client = InfrahubClient(config=config) -# response = await client.schema.load(schemas=[builtin_org_schema]) -# assert not response.errors -# -# await create_branch(branch_name="branch01", db=db) -# -# query_string = """ -# query { -# branch { -# id -# name -# } -# } -# """ -# obj1 = await Node.init(schema="CoreGraphQLQuery", db=db) -# await obj1.new(db=db, name="test_query2", description="test query", query=query_string) -# await obj1.save(db=db) -# -# obj2 = await Node.init(schema="CoreRepository", db=db) -# await obj2.new( -# db=db, -# name="repository1", -# description="test repository", -# location="git@github.com:mock/test.git", -# ) -# await obj2.save(db=db) -# -# obj3 = await Node.init(schema="CoreTransformJinja2", db=db) -# await obj3.new( -# db=db, -# name="rfile1", -# description="test rfile", -# template_path="mytemplate.j2", -# repository=obj2, -# query=obj1, -# ) -# await obj3.save(db=db) -# -# obj4 = await Node.init(schema="CoreTransformPython", db=db) -# await obj4.new( -# db=db, -# name="transform01", -# description="test transform01", -# file_path="mytransformation.py", -# class_name="Transform01", -# query=obj1, -# repository=obj2, -# ) -# await obj4.save(db=db) -# -# async def test_query_branches(self, client: InfrahubClient, init_db_base, base_dataset): -# branches = await client.branch.all() -# main = await client.branch.get(branch_name="main") -# -# with pytest.raises(BranchNotFoundError): -# await client.branch.get(branch_name="not-found") -# -# assert main.name == "main" -# assert "main" in branches -# assert "branch01" in branches -# -# async def test_branch_delete(self, client: InfrahubClient, init_db_base, base_dataset, db): -# async_branch = "async-delete-branch" -# await create_branch(branch_name=async_branch, db=db) -# pre_delete = await client.branch.all() -# await client.branch.delete(async_branch) -# post_delete = await client.branch.all() -# assert async_branch in pre_delete.keys() -# assert async_branch not in post_delete.keys() -# -# async def test_get_all(self, client: InfrahubClient, init_db_base, base_dataset): -# obj1 = await client.create(kind="BuiltinLocation", name="jfk1", description="new york", type="site") -# await obj1.save() -# -# obj2 = await client.create(kind="BuiltinLocation", name="sfo1", description="san francisco", type="site") -# await obj2.save() -# -# nodes = await client.all(kind="BuiltinLocation") -# assert len(nodes) == 2 -# assert isinstance(nodes[0], InfrahubNode) -# assert sorted([node.name.value for node in nodes]) == ["jfk1", "sfo1"] # type: ignore[attr-defined] -# -# async def test_get_one(self, client: InfrahubClient, init_db_base, base_dataset): -# obj1 = await client.create(kind="BuiltinLocation", name="jfk2", description="new york", type="site") -# await obj1.save() -# -# obj2 = await client.create(kind="BuiltinLocation", name="sfo2", description="san francisco", type="site") -# await obj2.save() -# -# node1 = await client.get(kind="BuiltinLocation", id=obj1.id) -# assert isinstance(node1, InfrahubNode) -# assert node1.name.value == "jfk2" # type: ignore[attr-defined] -# -# node2 = await client.get(kind="BuiltinLocation", id="jfk2") -# assert isinstance(node2, InfrahubNode) -# assert node2.name.value == "jfk2" # type: ignore[attr-defined] -# -# async def test_filters_partial_match(self, client: InfrahubClient, init_db_base, base_dataset): -# nodes = await client.filters(kind="BuiltinLocation", name__value="jfk") -# assert not nodes -# -# nodes = await client.filters(kind="BuiltinLocation", partial_match=True, name__value="jfk") -# assert len(nodes) == 2 -# assert isinstance(nodes[0], InfrahubNode) -# assert sorted([node.name.value for node in nodes]) == ["jfk1", "jfk2"] # type: ignore[attr-defined] -# -# async def test_get_generic(self, client: InfrahubClient, db: InfrahubDatabase, init_db_base): -# nodes = await client.all(kind="CoreNode") -# assert len(nodes) -# -# async def test_get_generic_fragment(self, client: InfrahubClient, db: InfrahubDatabase, init_db_base): -# nodes = await client.all(kind="CoreGenericAccount", fragment=True, exclude=["type"]) -# assert len(nodes) -# assert nodes[0].typename == "CoreAccount" -# assert nodes[0].name.value is not None # type: ignore[attr-defined] -# -# async def test_get_generic_filter_source(self, client: InfrahubClient, db: InfrahubDatabase, init_db_base): -# admin = await client.get(kind="CoreAccount", name__value="admin") -# -# obj1 = await client.create( -# kind="BuiltinLocation", name={"value": "jfk3", "source": admin.id}, description="new york", type="site" -# ) -# await obj1.save() -# -# nodes = await client.filters(kind="CoreNode", any__source__id=admin.id) -# assert len(nodes) == 1 -# assert nodes[0].typename == "BuiltinLocation" -# assert nodes[0].id == obj1.id -# -# async def test_get_related_nodes(self, client: InfrahubClient, db: InfrahubDatabase, init_db_base): -# nodes = await client.all(kind="CoreRepository") -# assert len(nodes) == 1 -# repo = nodes[0] -# -# assert repo.transformations.peers == [] # type: ignore[attr-defined] -# await repo.transformations.fetch() # type: ignore[attr-defined] -# assert len(repo.transformations.peers) == 2 # type: ignore[attr-defined] -# +from __future__ import annotations + +from typing import TYPE_CHECKING + +import pytest + +from infrahub_sdk.branch import BranchData +from infrahub_sdk.exceptions import BranchNotFoundError +from infrahub_sdk.node import InfrahubNode +from infrahub_sdk.schema import ProfileSchemaAPI +from infrahub_sdk.testing.docker import TestInfrahubDockerClient +from infrahub_sdk.testing.schemas.animal import TESTING_ANIMAL, TESTING_CAT, TESTING_DOG, TESTING_PERSON, SchemaAnimal + +if TYPE_CHECKING: + from infrahub_sdk import InfrahubClient + + +class TestInfrahubNode(TestInfrahubDockerClient, SchemaAnimal): + @pytest.fixture(scope="class") + def infrahub_version(self) -> str: + return "1.0.10" + + @pytest.fixture(scope="class") + async def base_dataset( + self, + client: InfrahubClient, + load_schema, + person_liam, + person_ethan, + person_sophia, + cat_luna, + cat_bella, + dog_daisy, + dog_rocky, + ): + await client.branch.create(branch_name="branch01") + + async def test_query_branches(self, client: InfrahubClient, base_dataset): + branches = await client.branch.all() + main = await client.branch.get(branch_name="main") + + with pytest.raises(BranchNotFoundError): + await client.branch.get(branch_name="not-found") + + assert main.name == "main" + assert "main" in branches + assert "branch01" in branches + + async def test_branch_delete(self, client: InfrahubClient, base_dataset): + async_branch = "async-delete-branch" + await client.branch.create(branch_name=async_branch) + pre_delete = await client.branch.all() + await client.branch.delete(async_branch) + post_delete = await client.branch.all() + assert async_branch in pre_delete.keys() + assert async_branch not in post_delete.keys() + + async def test_get_all(self, client: InfrahubClient, base_dataset): + nodes = await client.all(kind=TESTING_CAT) + assert len(nodes) == 2 + assert isinstance(nodes[0], InfrahubNode) + assert sorted([node.name.value for node in nodes]) == ["Bella", "Luna"] + + async def test_get_one(self, client: InfrahubClient, base_dataset, cat_luna, person_sophia): + node1 = await client.get(kind=TESTING_CAT, id=cat_luna.id) + assert isinstance(node1, InfrahubNode) + assert node1.name.value == "Luna" + + node2 = await client.get(kind=TESTING_PERSON, id=person_sophia.id) + assert isinstance(node2, InfrahubNode) + assert node2.name.value == "Sophia Walker" + + async def test_filters_partial_match(self, client: InfrahubClient, base_dataset): + nodes = await client.filters(kind=TESTING_PERSON, name__value="Walker") + assert not nodes + + nodes = await client.filters(kind=TESTING_PERSON, partial_match=True, name__value="Walker") + assert len(nodes) == 2 + assert isinstance(nodes[0], InfrahubNode) + assert sorted([node.name.value for node in nodes]) == ["Liam Walker", "Sophia Walker"] + + async def test_get_generic(self, client: InfrahubClient, base_dataset): + nodes = await client.all(kind=TESTING_ANIMAL) + assert len(nodes) == 4 + + async def test_get_generic_fragment(self, client: InfrahubClient, base_dataset): + nodes = await client.all(kind=TESTING_ANIMAL, fragment=True) + assert len(nodes) + assert nodes[0].typename in [TESTING_DOG, TESTING_CAT] + assert nodes[0].breed.value is not None + + async def test_get_related_nodes(self, client: InfrahubClient, base_dataset, person_ethan): + ethan = await client.get(kind=TESTING_PERSON, id=person_ethan.id) + assert ethan + + assert ethan.animals.peers == [] + await ethan.animals.fetch() + assert len(ethan.animals.peers) == 3 + + async def test_profile(self, client: InfrahubClient, base_dataset, person_liam): + profile_schema_kind = f"Profile{TESTING_DOG}" + profile_schema = await client.schema.get(kind=profile_schema_kind) + assert isinstance(profile_schema, ProfileSchemaAPI) + + profile1 = await client.create( + kind=profile_schema_kind, + profile_name="profile1", + profile_priority=1000, + color="#111111", + ) + await profile1.save() + + obj = await client.create( + kind=TESTING_DOG, name="Sparky", breed="Border Collie", owner=person_liam, profiles=[profile1] + ) + await obj.save() + + obj1 = await client.get(kind=TESTING_DOG, id=obj.id) + assert obj1.color.value == "#111111" + + async def test_create_branch(self, client: InfrahubClient, base_dataset): + branch = await client.branch.create(branch_name="new-branch-1") + assert isinstance(branch, BranchData) + assert branch.id is not None + + async def test_create_branch_async(self, client: InfrahubClient, base_dataset): + task_id = await client.branch.create(branch_name="new-branch-2", wait_until_completion=False) + assert isinstance(task_id, str) + + # async def test_get_generic_filter_source(self, client: InfrahubClient, base_dataset): + # admin = await client.get(kind="CoreAccount", name__value="admin") + + # obj1 = await client.create( + # kind="BuiltinLocation", name={"value": "jfk3", "source": admin.id}, description="new york", type="site" + # ) + # await obj1.save() + + # nodes = await client.filters(kind="CoreNode", any__source__id=admin.id) + # assert len(nodes) == 1 + # assert nodes[0].typename == "BuiltinLocation" + # assert nodes[0].id == obj1.id + + # async def test_tracking_mode(self, client: InfrahubClient, db: InfrahubDatabase, init_db_base, base_dataset): # tag_names = ["BLUE", "RED", "YELLOW"] # orgname = "Acme" @@ -266,34 +226,8 @@ # assert nodes == recorded_nodes # assert recorded_nodes[0].name.value == "repository1" # -# async def test_profile(self, client: InfrahubClient, db: InfrahubDatabase, init_db_base, base_dataset): -# profile_schema_kind = "ProfileBuiltinStatus" -# profile_schema = await client.schema.get(kind=profile_schema_kind) -# assert isinstance(profile_schema, ProfileSchema) -# -# profile1 = await client.create( -# kind=profile_schema_kind, -# profile_name="profile1", -# profile_priority=1000, -# description="description in profile", -# ) -# await profile1.save() -# -# obj = await client.create(kind="BuiltinStatus", name="planned", profiles=[profile1]) -# await obj.save() -# -# obj1 = await client.get(kind="BuiltinStatus", id=obj.id) -# assert obj1.description.value == "description in profile" -# -# async def test_create_branch(self, client: InfrahubClient, db: InfrahubDatabase, init_db_base, base_dataset): -# branch = await client.branch.create(branch_name="new-branch-1") -# assert isinstance(branch, BranchData) -# assert branch.id is not None -# -# async def test_create_branch_async(self, client: InfrahubClient, db: InfrahubDatabase, init_db_base, base_dataset): -# task_id = await client.branch.create(branch_name="new-branch-2", wait_until_completion=False) -# assert isinstance(task_id, str) -# + + # # See issue #148. # async def test_hierarchical( # self, client: InfrahubClient, db: InfrahubDatabase, init_db_base, base_dataset, hierarchical_schema diff --git a/tests/integration/test_node.py b/tests/integration/test_node.py index 7421cacf..5c50ef69 100644 --- a/tests/integration/test_node.py +++ b/tests/integration/test_node.py @@ -5,7 +5,7 @@ from infrahub_sdk.node import InfrahubNode from infrahub_sdk.schema import NodeSchema, NodeSchemaAPI, SchemaRoot from infrahub_sdk.testing.docker import TestInfrahubDockerClient -from infrahub_sdk.testing.schemas.car_person import TESTING_MANUFACTURER, SchemaCarPerson +from infrahub_sdk.testing.schemas.car_person import TESTING_CAR, TESTING_MANUFACTURER, SchemaCarPerson # pylint: disable=unused-argument @@ -29,56 +29,45 @@ async def test_node_create( ): schema_manufacturer = NodeSchemaAPI(**schema_manufacturer_base.model_dump(exclude_unset=True)) data = { - "name": {"value": "Fiat"}, - "description": {"value": "An italian brand"}, + "name": "Fiat", + "description": "An italian brand", } node = InfrahubNode(client=client, schema=schema_manufacturer, data=data) await node.save() - assert node.id is not None async def test_node_delete( self, - default_branch: str, client: InfrahubClient, initial_schema: None, ): - await self.create_manufacturers(client=client, branch=default_branch) + obj = await client.create(kind=TESTING_MANUFACTURER, name="Dacia") + await obj.save() + + await client.get(kind=TESTING_MANUFACTURER, id=obj.id) - obj: InfrahubNode = client.store.get_by_hfid(key=f"{TESTING_MANUFACTURER}__Volkswagen") await obj.delete() with pytest.raises(NodeNotFoundError): await client.get(kind=TESTING_MANUFACTURER, id=obj.id) - # async def test_node_create_with_relationships( - # self, - # db: InfrahubDatabase, - # client: InfrahubClient, - # init_db_base, - # load_builtin_schema, - # tag_blue: Node, - # tag_red: Node, - # repo01: Node, - # gqlquery01: Node, - # ): - # data = { - # "name": {"value": "rfile01"}, - # "template_path": {"value": "mytemplate.j2"}, - # "query": gqlquery01.id, - # "repository": {"id": repo01.id}, - # "tags": [tag_blue.id, tag_red.id], - # } - - # node = await client.create(kind="CoreTransformJinja2", data=data) - # await node.save() - - # assert node.id is not None + async def test_node_create_with_relationships( + self, + default_branch: str, + client: InfrahubClient, + initial_schema: None, + manufacturer_mercedes, + person_joe, + ): + node = await client.create( + kind=TESTING_CAR, name="Tiguan", color="Black", manufacturer=manufacturer_mercedes.id, owner=person_joe.id + ) + await node.save() + assert node.id is not None - # nodedb = await NodeManager.get_one(id=node.id, db=db, include_owner=True, include_source=True) - # assert nodedb.name.value == node.name.value # type: ignore[attr-defined] - # querydb = await nodedb.query.get_peer(db=db) - # assert node.query.id == querydb.id # type: ignore[attr-defined] + node_after = await client.get(kind=TESTING_CAR, id=node.id, prefetch_relationships=True) + assert node_after.name.value == node.name.value + assert node_after.manufacturer.peer.id == manufacturer_mercedes.id # async def test_node_update_payload_with_relationships( # self, @@ -144,31 +133,30 @@ async def test_node_delete( # assert node.id is not None # nodedb = await NodeManager.get_one(id=node.id, db=db, include_owner=True, include_source=True) - # assert nodedb.name.value == node.name.value # type: ignore[attr-defined] + # assert nodedb.name.value == node.name.value # assert nodedb.name.is_protected is True - # async def test_node_update( - # self, - # db: InfrahubDatabase, - # client: InfrahubClient, - # init_db_base, - # load_builtin_schema, - # tag_blue: Node, - # tag_red: Node, - # repo99: Node, - # ): - # node = await client.get(kind="CoreRepository", name__value="repo99") - # assert node.id is not None - - # node.name.value = "repo95" # type: ignore[attr-defined] - # node.tags.add(tag_blue.id) # type: ignore[attr-defined] - # node.tags.add(tag_red.id) # type: ignore[attr-defined] - # await node.save() + async def test_node_update( + self, + default_branch: str, + client: InfrahubClient, + initial_schema: None, + manufacturer_mercedes, + person_joe, + car_golf, + tag_blue, + tag_red, + ): + car_golf.color.value = "White" + await car_golf.tags.fetch() + car_golf.tags.add(tag_blue.id) + car_golf.tags.add(tag_red.id) + await car_golf.save() - # nodedb = await NodeManager.get_one(id=node.id, db=db, include_owner=True, include_source=True) - # assert nodedb.name.value == "repo95" - # tags = await nodedb.tags.get(db=db) - # assert len(tags) == 2 + node_after = await client.get(kind=TESTING_CAR, id=car_golf.id) + assert node_after.color.value == "White" + await node_after.tags.fetch() + assert len(node_after.tags.peers) == 2 # async def test_node_update_2( # self, @@ -185,10 +173,10 @@ async def test_node_delete( # node = await client.get(kind="CoreGraphQLQuery", name__value="query02") # assert node.id is not None - # node.name.value = "query021" # type: ignore[attr-defined] - # node.repository = repo99.id # type: ignore[attr-defined] - # node.tags.add(tag_green.id) # type: ignore[attr-defined] - # node.tags.remove(tag_red.id) # type: ignore[attr-defined] + # node.name.value = "query021" + # node.repository = repo99.id + # node.tags.add(tag_green.id) + # node.tags.remove(tag_red.id) # await node.save() # nodedb = await NodeManager.get_one(id=node.id, db=db, include_owner=True, include_source=True) @@ -213,21 +201,21 @@ async def test_node_delete( # node = await client.get(kind="CoreGraphQLQuery", name__value="query03") # assert node.id is not None - # updated_query = f"\n\n{node.query.value}" # type: ignore[attr-defined] - # node.name.value = "query031" # type: ignore[attr-defined] - # node.query.value = updated_query # type: ignore[attr-defined] + # updated_query = f"\n\n{node.query.value}" + # node.name.value = "query031" + # node.query.value = updated_query # first_update = node._generate_input_data(exclude_unmodified=True) # await node.save() # nodedb = await NodeManager.get_one(id=node.id, db=db, include_owner=True, include_source=True) # node = await client.get(kind="CoreGraphQLQuery", name__value="query031") - # node.name.value = "query031" # type: ignore[attr-defined] - # node.query.value = updated_query # type: ignore[attr-defined] + # node.name.value = "query031" + # node.query.value = updated_query # second_update = node._generate_input_data(exclude_unmodified=True) - # assert nodedb.query.value == updated_query # type: ignore[attr-defined] + # assert nodedb.query.value == updated_query # assert "query" in first_update["data"]["data"] # assert "value" in first_update["data"]["data"]["query"] # assert first_update["variables"] @@ -247,7 +235,7 @@ async def test_node_delete( # node = InfrahubNode(client=client, schema=location_schema, data=data) # # pylint: disable=no-member - # assert node.name.value == "cdg01" # type: ignore[attr-defined] + # assert node.name.value == "cdg01" # async def test_relationship_manager_errors_without_fetch(self, client: InfrahubClient, load_builtin_schema): # organization = await client.create("TestOrganization", name="organization-1") From bd44e6333422ede73781766c5093c1b55898540d Mon Sep 17 00:00:00 2001 From: Damien Garros Date: Sat, 4 Jan 2025 18:32:02 +0100 Subject: [PATCH 2/2] Run tests on infrahub 1.1, fix issue with branch async --- infrahub_sdk/branch.py | 6 ++++-- tests/integration/test_infrahub_client.py | 2 +- tests/integration/test_node.py | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/infrahub_sdk/branch.py b/infrahub_sdk/branch.py index b4e21d64..9d7de1fb 100644 --- a/infrahub_sdk/branch.py +++ b/infrahub_sdk/branch.py @@ -40,6 +40,7 @@ class BranchData(BaseModel): MUTATION_QUERY_DATA = {"ok": None, "object": BRANCH_DATA} +MUTATION_QUERY_TASK = {"ok": None, "task": {"id": None}} QUERY_ALL_BRANCHES_DATA = {"Branch": BRANCH_DATA} @@ -119,13 +120,14 @@ async def create( }, } - query = Mutation(mutation="BranchCreate", input_data=input_data, query=MUTATION_QUERY_DATA) + mutation_query = MUTATION_QUERY_TASK if background_execution else MUTATION_QUERY_DATA + query = Mutation(mutation="BranchCreate", input_data=input_data, query=mutation_query) response = await self.client.execute_graphql(query=query.render(), tracker="mutation-branch-create") # Make sure server version is recent enough to support background execution, as previously # using background_execution=True had no effect. if background_execution and "task" in response["BranchCreate"]: - return BranchData(**response["BranchCreate"]["task"]["id"]) + return response["BranchCreate"]["task"]["id"] return BranchData(**response["BranchCreate"]["object"]) async def delete(self, branch_name: str) -> bool: diff --git a/tests/integration/test_infrahub_client.py b/tests/integration/test_infrahub_client.py index 5115ffc2..4057d710 100644 --- a/tests/integration/test_infrahub_client.py +++ b/tests/integration/test_infrahub_client.py @@ -18,7 +18,7 @@ class TestInfrahubNode(TestInfrahubDockerClient, SchemaAnimal): @pytest.fixture(scope="class") def infrahub_version(self) -> str: - return "1.0.10" + return "1.1.0" @pytest.fixture(scope="class") async def base_dataset( diff --git a/tests/integration/test_node.py b/tests/integration/test_node.py index 5c50ef69..e8609489 100644 --- a/tests/integration/test_node.py +++ b/tests/integration/test_node.py @@ -13,7 +13,7 @@ class TestInfrahubNode(TestInfrahubDockerClient, SchemaCarPerson): @pytest.fixture(scope="class") def infrahub_version(self) -> str: - return "1.0.10" + return "1.1.0" @pytest.fixture(scope="class") async def initial_schema(self, default_branch: str, client: InfrahubClient, schema_base: SchemaRoot) -> None: