Skip to content

Commit 9383e27

Browse files
committed
test for diff with migrated kind peer
1 parent 93e92e2 commit 9383e27

File tree

1 file changed

+156
-0
lines changed

1 file changed

+156
-0
lines changed

backend/tests/unit/core/diff/test_diff_calculator.py

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4296,3 +4296,159 @@ async def test_migrated_kind_with_property_level_changes(
42964296
assert is_protected_prop.action is DiffAction.UPDATED
42974297
assert is_protected_prop.new_value is True
42984298
assert is_protected_prop.previous_value is False
4299+
4300+
4301+
async def test_migrated_kind_on_main_then_relationship_update_on_branch(
4302+
db: InfrahubDatabase,
4303+
default_branch: Branch,
4304+
car_accord_main,
4305+
car_camry_main,
4306+
person_john_main,
4307+
person_jane_main,
4308+
person_alfred_main,
4309+
person_albert_main,
4310+
):
4311+
"""Test that when a schema kind is migrated on the default branch, relationships to instances
4312+
of the migrated node can be updated on a branch before the diff is calculated."""
4313+
# Migrate TestPerson kind on default branch
4314+
schema_branch = registry.schema.get_schema_branch(name=default_branch.name)
4315+
original_person_schema = schema_branch.get_node(name="TestPerson")
4316+
person_schema = schema_branch.get_node(name="TestPerson")
4317+
person_schema.inherit_from = ["GenericThing"]
4318+
registry.schema.set(name="TestPerson", schema=person_schema, branch=default_branch.name)
4319+
migration = NodeKindUpdateMigration(
4320+
previous_node_schema=original_person_schema,
4321+
new_node_schema=person_schema,
4322+
schema_path=SchemaPath(path_type=SchemaPathType.ATTRIBUTE, schema_kind="TestPerson", field_name="inherit_from"),
4323+
)
4324+
execution_result = await migration.execute(db=db, branch=default_branch)
4325+
assert not execution_result.errors
4326+
4327+
# Create a branch after the migration
4328+
branch = await create_branch(db=db, branch_name="branch-with-relationship-updates")
4329+
4330+
# Update relationships on the branch that reference instances of the migrated node
4331+
branch_accord = await NodeManager.get_one(db=db, branch=branch, id=car_accord_main.id)
4332+
await branch_accord.owner.update(db=db, data=person_albert_main.id)
4333+
await branch_accord.save(db=db)
4334+
4335+
branch_camry = await NodeManager.get_one(db=db, branch=branch, id=car_camry_main.id)
4336+
await branch_camry.owner.update(db=db, data={"id": person_jane_main.id, "_relation__is_protected": True})
4337+
await branch_camry.save(db=db)
4338+
4339+
# Calculate the diff
4340+
diff_calculator = DiffCalculator(db=db)
4341+
4342+
calculated_diffs = await diff_calculator.calculate_diff(
4343+
base_branch=default_branch,
4344+
diff_branch=branch,
4345+
from_time=Timestamp(branch.get_branched_from()),
4346+
to_time=Timestamp(),
4347+
previous_node_specifiers=None,
4348+
include_unchanged=True,
4349+
)
4350+
4351+
base_diff = calculated_diffs.base_branch_diff
4352+
assert len(base_diff.nodes) == 0
4353+
4354+
branch_diff = calculated_diffs.diff_branch_diff
4355+
nodes_by_id: dict[str, list[DiffNode]] = defaultdict(list)
4356+
for node in branch_diff.nodes:
4357+
nodes_by_id[node.uuid].append(node)
4358+
4359+
# Verify that the cars and related persons appear in the diff
4360+
expected_ids = {
4361+
car_accord_main.id,
4362+
car_camry_main.id,
4363+
person_john_main.id,
4364+
person_jane_main.id,
4365+
person_albert_main.id,
4366+
}
4367+
assert set(nodes_by_id.keys()) == expected_ids
4368+
assert len(nodes_by_id) == len(expected_ids)
4369+
4370+
# Get the car schema to find the owner relationship identifier
4371+
car_schema = registry.schema.get(name="TestCar", branch=branch.name)
4372+
owner_rel_schema = car_schema.get_relationship(name="owner")
4373+
owner_identifier = owner_rel_schema.get_identifier()
4374+
4375+
# Validate car_accord relationship update
4376+
accord_diffs = nodes_by_id[car_accord_main.id]
4377+
assert len(accord_diffs) == 1
4378+
accord_diff = accord_diffs[0]
4379+
assert accord_diff.action is DiffAction.UPDATED
4380+
assert accord_diff.is_node_kind_migration is False
4381+
rels_by_identifier = {r.identifier: r for r in accord_diff.relationships}
4382+
assert owner_identifier in rels_by_identifier
4383+
owner_rel_diff = rels_by_identifier[owner_identifier]
4384+
assert owner_rel_diff.action is DiffAction.UPDATED
4385+
elements_by_id = {r.peer_id: r for r in owner_rel_diff.relationships}
4386+
assert set(elements_by_id.keys()) == {person_john_main.id, person_albert_main.id}
4387+
# Original owner was person_john_main, so it should be REMOVED
4388+
john_element = elements_by_id[person_john_main.id]
4389+
assert john_element.action is DiffAction.REMOVED
4390+
# Verify the relationship properties for the removed owner
4391+
props_by_type = {p.property_type: p for p in john_element.properties}
4392+
assert set(props_by_type.keys()) == {
4393+
DatabaseEdgeType.IS_RELATED,
4394+
DatabaseEdgeType.IS_VISIBLE,
4395+
DatabaseEdgeType.IS_PROTECTED,
4396+
}
4397+
for prop_type, previous_value in [
4398+
(DatabaseEdgeType.IS_RELATED, person_john_main.id),
4399+
(DatabaseEdgeType.IS_VISIBLE, True),
4400+
(DatabaseEdgeType.IS_PROTECTED, False),
4401+
]:
4402+
prop_diff = props_by_type[prop_type]
4403+
assert prop_diff.action is DiffAction.REMOVED
4404+
assert prop_diff.previous_value == previous_value
4405+
assert prop_diff.new_value is None
4406+
# The owner should have been updated to person_albert_main
4407+
albert_element = elements_by_id[person_albert_main.id]
4408+
assert albert_element.action is DiffAction.ADDED
4409+
# Verify the relationship properties for the new owner
4410+
props_by_type = {p.property_type: p for p in albert_element.properties}
4411+
assert DatabaseEdgeType.IS_RELATED in props_by_type
4412+
is_related_prop = props_by_type[DatabaseEdgeType.IS_RELATED]
4413+
assert is_related_prop.action is DiffAction.ADDED
4414+
assert is_related_prop.new_value == person_albert_main.id
4415+
4416+
# Validate car_camry relationship update
4417+
camry_diffs = nodes_by_id[car_camry_main.id]
4418+
assert len(camry_diffs) == 1
4419+
camry_diff = camry_diffs[0]
4420+
assert camry_diff.action is DiffAction.UPDATED
4421+
assert camry_diff.is_node_kind_migration is False
4422+
rels_by_identifier = {r.identifier: r for r in camry_diff.relationships}
4423+
assert owner_identifier in rels_by_identifier
4424+
owner_rel_diff = rels_by_identifier[owner_identifier]
4425+
assert owner_rel_diff.action is DiffAction.UPDATED
4426+
elements_by_id = {r.peer_id: r for r in owner_rel_diff.relationships}
4427+
# The owner relationship with person_jane_main should have is_protected updated
4428+
assert set(elements_by_id.keys()) == {person_jane_main.id}
4429+
element_diff = elements_by_id[person_jane_main.id]
4430+
assert element_diff.action is DiffAction.UPDATED
4431+
properties_by_type = {p.property_type: p for p in element_diff.properties if p.action != DiffAction.UNCHANGED}
4432+
assert set(properties_by_type.keys()) == {DatabaseEdgeType.IS_PROTECTED}
4433+
is_protected_prop = properties_by_type[DatabaseEdgeType.IS_PROTECTED]
4434+
assert is_protected_prop.action is DiffAction.UPDATED
4435+
assert is_protected_prop.new_value is True
4436+
assert is_protected_prop.previous_value is False
4437+
4438+
# Validate only correct TestPerson nodes are present in the diff
4439+
current_persons_map = await NodeManager.get_many(
4440+
db=db, ids=[person_john_main.id, person_jane_main.id, person_albert_main.id]
4441+
)
4442+
for person_id in [person_john_main.id, person_jane_main.id, person_albert_main.id]:
4443+
person_object = current_persons_map[person_id]
4444+
person_diffs = nodes_by_id[person_id]
4445+
assert len(person_diffs) == 1
4446+
person_diff = person_diffs[0]
4447+
assert person_diff.identifier.db_id == person_object.db_id
4448+
assert person_diff.action is DiffAction.UPDATED
4449+
assert person_diff.is_node_kind_migration is False
4450+
assert person_diff.attributes == []
4451+
assert len(person_diff.relationships) == 1
4452+
rel_diff = person_diff.relationships[0]
4453+
assert rel_diff.name == "cars"
4454+
assert rel_diff.action is DiffAction.UPDATED

0 commit comments

Comments
 (0)