This is an automated email from the ASF dual-hosted git repository.
pierrejeambrun pushed a commit to branch v3-0-test
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/v3-0-test by this push:
new f61d41472de [v3-0-test] Bring back mapped task extra links test
(#51297) (#51477)
f61d41472de is described below
commit f61d41472de13a097e12e921dc6574ca0e030349
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Wed Jul 2 11:00:01 2025 +0200
[v3-0-test] Bring back mapped task extra links test (#51297) (#51477)
* Bring back mapped task extra links test
* rebase and fixing test
(cherry picked from commit 17a5038)
Co-authored-by: Amogh Desai <[email protected]>
---
.../core_api/routes/public/test_extra_links.py | 59 +++++++++++++---------
.../src/tests_common/test_utils/mock_operators.py | 7 +++
2 files changed, 42 insertions(+), 24 deletions(-)
diff --git
a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_extra_links.py
b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_extra_links.py
index 1ff1d06d961..4d84485d48a 100644
---
a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_extra_links.py
+++
b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_extra_links.py
@@ -120,6 +120,9 @@ class TestGetExtraLinks:
CustomOperator(
task_id=self.task_multiple_links,
bash_command=["TEST_LINK_VALUE_1", "TEST_LINK_VALUE_2"]
)
+ _ = CustomOperator.partial(task_id=self.task_mapped).expand(
+ bash_command=["TEST_LINK_VALUE_1", "TEST_LINK_VALUE_2"]
+ )
return dag
@pytest.mark.parametrize(
@@ -261,29 +264,37 @@ class TestGetExtraLinks:
).model_dump()
)
- @pytest.mark.xfail(reason="TODO: TaskSDK need to fix this, Extra links
should work for mapped operator")
- def test_should_respond_200_mapped_task_instance(self, test_client):
- map_index = 0
- XCom.set(
- key="search_query",
- value="TEST_LINK_VALUE_1",
- task_id=self.task_mapped,
- dag_id=self.dag.dag_id,
- run_id=self.dag_run_id,
- map_index=map_index,
- )
- response = test_client.get(
-
f"/dags/{self.dag_id}/dagRuns/{self.dag_run_id}/taskInstances/{self.task_mapped}/links",
- params={"map_index": map_index},
- )
- assert response.status_code == 200
- assert (
- response.json()
- == ExtraLinkCollectionResponse(
- extra_links={"Google Custom":
"http://google.com/custom_base_link?search=TEST_LINK_VALUE_1"},
- total_entries=1,
- ).model_dump()
- )
+ def test_should_respond_200_mapped_task_instance(self, test_client,
session):
+ for map_index, value in enumerate(["TEST_LINK_VALUE_1",
"TEST_LINK_VALUE_2"]):
+ XCom.set(
+ key="search_query",
+ value=value,
+ task_id=self.task_mapped,
+ dag_id=self.dag_id,
+ run_id=self.dag_run_id,
+ map_index=map_index,
+ )
+ XCom.set(
+ key="_link_CustomOpLink",
+ value=f"http://google.com/custom_base_link?search={value}",
+ task_id=self.task_mapped,
+ dag_id=self.dag_id,
+ run_id=self.dag_run_id,
+ map_index=map_index,
+ )
+ session.commit()
+ response = test_client.get(
+
f"/dags/{self.dag_id}/dagRuns/{self.dag_run_id}/taskInstances/{self.task_mapped}/links",
+ params={"map_index": map_index},
+ )
+ assert response.status_code == 200
+ assert (
+ response.json()
+ == ExtraLinkCollectionResponse(
+ extra_links={"Google Custom":
f"http://google.com/custom_base_link?search={value}"},
+ total_entries=1,
+ ).model_dump()
+ )
def test_should_respond_401_unauthenticated(self,
unauthenticated_test_client):
response = unauthenticated_test_client.get(
@@ -305,4 +316,4 @@ class TestGetExtraLinks:
params={"map_index": 4},
)
assert response.status_code == 404
- assert response.json() == {"detail": "Task with ID = TEST_MAPPED_TASK
not found"}
+ assert response.json() == {"detail": "TaskInstance not found"}
diff --git a/devel-common/src/tests_common/test_utils/mock_operators.py
b/devel-common/src/tests_common/test_utils/mock_operators.py
index 123968e936d..d4fd43421f6 100644
--- a/devel-common/src/tests_common/test_utils/mock_operators.py
+++ b/devel-common/src/tests_common/test_utils/mock_operators.py
@@ -151,8 +151,15 @@ class CustomOperator(BaseOperator):
@property
def operator_extra_links(self):
"""Return operator extra links."""
+ # For mapped operators
+ if not hasattr(self, "bash_command"):
+ # For mapped operators, we return CustomOpLink since each mapped
instance
+ # will get its own link during runtime
+ return (CustomOpLink(),)
+ # For non-mapped operators
if isinstance(self.bash_command, str) or self.bash_command is None:
return (CustomOpLink(),)
+ # For operators with multiple commands
return (CustomBaseIndexOpLink(i) for i, _ in
enumerate(self.bash_command))
def __init__(self, bash_command=None, **kwargs):