From a194c6c7e9bcad42354aad8850dd9133c47c56b3 Mon Sep 17 00:00:00 2001 From: Leonardo Schwarz Date: Wed, 15 Apr 2026 14:25:09 +0200 Subject: [PATCH] Fix SaveLinkSpec registration crash on ResultContainer string indexing (#476) `res['id']` tried string indexing on a ResultContainer, which only supports int/slice indexing. Changed to `res[0]['id']`. --- AGENTS.md | 1 + .../output_registration/register.py | 2 +- .../output_registration/test_save_link.py | 39 +++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 tests/bfabric_app_runner/output_registration/test_save_link.py diff --git a/AGENTS.md b/AGENTS.md index 23128aba..7b887a2e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -91,6 +91,7 @@ Handles dispatch → process → collect workflow for B-Fabric applications. Use - Line length: 120 (ruff and black) - basedpyright uses per-package baseline files at `.basedpyright/baseline.{package}.json` - Integration tests live in a separate repository +- Use TDD: write a failing test first, verify it fails, then fix the code, then verify the test passes ## Branches diff --git a/bfabric_app_runner/src/bfabric_app_runner/output_registration/register.py b/bfabric_app_runner/src/bfabric_app_runner/output_registration/register.py index 94fe3c1f..6a61ffe1 100644 --- a/bfabric_app_runner/src/bfabric_app_runner/output_registration/register.py +++ b/bfabric_app_runner/src/bfabric_app_runner/output_registration/register.py @@ -154,7 +154,7 @@ def _save_link(spec: SaveLinkSpec, client: Bfabric, workunit_definition: Workuni if existing_link_id is not None: link_data["id"] = existing_link_id res = client.save("link", link_data) - logger.info(f"Link {spec.name} saved with id {res['id']} for entity {entity_type} with id {entity_id}") + logger.info(f"Link {spec.name} saved with id {res[0]['id']} for entity {entity_type} with id {entity_id}") def find_default_resource_id(workunit_definition: WorkunitDefinition, client: Bfabric) -> int | None: diff --git a/tests/bfabric_app_runner/output_registration/test_save_link.py b/tests/bfabric_app_runner/output_registration/test_save_link.py new file mode 100644 index 00000000..9e12d6cf --- /dev/null +++ b/tests/bfabric_app_runner/output_registration/test_save_link.py @@ -0,0 +1,39 @@ +from unittest.mock import MagicMock + +import pytest + +from bfabric.results.result_container import ResultContainer +from bfabric_app_runner.output_registration.register import _save_link +from bfabric_app_runner.specs.outputs_spec import SaveLinkSpec + + +@pytest.fixture() +def mock_client(): + return MagicMock() + + +@pytest.fixture() +def mock_workunit_definition(): + mock = MagicMock() + mock.registration.workunit_id = 42 + return mock + + +@pytest.fixture() +def spec(): + return SaveLinkSpec(name="test_link", url="https://example.com", entity_type="Workunit") + + +def test_save_link_no_existing(mock_client, mock_workunit_definition, spec): + """Test that _save_link works when no existing link is found.""" + mock_client.read.return_value = ResultContainer(results=[], total_pages_api=None, errors=[]) + mock_client.save.return_value = ResultContainer(results=[{"id": 123}], total_pages_api=None, errors=[]) + + _save_link(spec, mock_client, mock_workunit_definition) + + mock_client.save.assert_called_once() + saved_data = mock_client.save.call_args[0][1] + assert saved_data["name"] == "test_link" + assert saved_data["url"] == "https://example.com" + assert saved_data["parentid"] == 42 + assert saved_data["parentclassname"] == "Workunit"