Skip to content

Commit 3331f9d

Browse files
Assert Python workflow list parity
Assert Python workflow list parity
1 parent 41680d8 commit 3331f9d

3 files changed

Lines changed: 98 additions & 2 deletions

File tree

src/durable_workflow/client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
from importlib.metadata import PackageNotFoundError
2626
from importlib.metadata import version as _pkg_version
2727
from typing import Any
28-
from urllib.parse import quote
28+
from urllib.parse import quote, urlencode
2929

3030
import httpx
3131

@@ -992,7 +992,7 @@ async def list_workflows(
992992
if next_page_token is not None:
993993
params["next_page_token"] = next_page_token
994994

995-
qs = "&".join(f"{k}={v}" for k, v in params.items())
995+
qs = urlencode(params)
996996
path = f"/workflows?{qs}" if qs else "/workflows"
997997
data = await self._request("GET", path)
998998
items = data.get("workflows", [])
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
{
2+
"schema": "durable-workflow.polyglot.control-plane-request-fixture",
3+
"version": 1,
4+
"operation": "workflow.list",
5+
"request": {
6+
"method": "GET",
7+
"path": "/workflows"
8+
},
9+
"semantic_body": {
10+
"workflow_type": "orders.process",
11+
"status": "running",
12+
"query": "CustomerId=\"42\"",
13+
"page_size": 25,
14+
"workflow_ids": [
15+
"wf-polyglot-list-1",
16+
"wf-polyglot-list-2"
17+
],
18+
"next_page_token": "next-polyglot-page"
19+
},
20+
"response_body": {
21+
"workflows": [
22+
{
23+
"workflow_id": "wf-polyglot-list-1",
24+
"run_id": "run-polyglot-list-1",
25+
"workflow_type": "orders.process",
26+
"business_key": "order-42",
27+
"status": "running",
28+
"task_queue": "orders",
29+
"started_at": "2026-04-22T05:00:00Z",
30+
"closed_at": null
31+
},
32+
{
33+
"workflow_id": "wf-polyglot-list-2",
34+
"run_id": "run-polyglot-list-2",
35+
"workflow_type": "orders.process",
36+
"business_key": "order-43",
37+
"status": "running",
38+
"task_queue": "orders",
39+
"started_at": "2026-04-22T05:01:00Z",
40+
"closed_at": null
41+
}
42+
],
43+
"next_page_token": "next-polyglot-page"
44+
},
45+
"cli": {
46+
"argv": {
47+
"--type": "orders.process",
48+
"--status": "running",
49+
"--query": "CustomerId=\"42\"",
50+
"--limit": "25",
51+
"--json": true
52+
},
53+
"expected_query": {
54+
"workflow_type": "orders.process",
55+
"status": "running",
56+
"query": "CustomerId=\"42\"",
57+
"page_size": 25
58+
}
59+
},
60+
"sdk_python": {
61+
"method": "list_workflows",
62+
"args": {
63+
"workflow_type": "orders.process",
64+
"status": "running",
65+
"query": "CustomerId=\"42\"",
66+
"page_size": 25
67+
}
68+
}
69+
}

tests/test_client.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import logging
55
from pathlib import Path
66
from unittest.mock import AsyncMock, patch
7+
from urllib.parse import parse_qs, urlsplit
78

89
import httpx
910
import pytest
@@ -686,6 +687,32 @@ async def test_list(self, client: Client) -> None:
686687
assert result.next_page_token == "abc"
687688
assert result.executions[0].workflow_id == "wf-1"
688689

690+
@pytest.mark.asyncio
691+
async def test_list_request_matches_polyglot_fixture(self, client: Client) -> None:
692+
fixture_path = Path(__file__).parent / "fixtures" / "control-plane" / "workflow-list-parity.json"
693+
fixture = json.loads(fixture_path.read_text())
694+
sdk_args = fixture["sdk_python"]["args"]
695+
696+
resp = _mock_response(200, fixture["response_body"])
697+
698+
with patch.object(client._http, "request", new_callable=AsyncMock, return_value=resp) as mock:
699+
result = await client.list_workflows(**sdk_args)
700+
701+
call_args = mock.call_args
702+
assert call_args.args[0] == fixture["request"]["method"]
703+
704+
url = urlsplit(call_args.args[1])
705+
assert url.path == f"/api{fixture['request']['path']}"
706+
assert parse_qs(url.query) == {
707+
"workflow_type": [fixture["semantic_body"]["workflow_type"]],
708+
"status": [fixture["semantic_body"]["status"]],
709+
"query": [fixture["semantic_body"]["query"]],
710+
"page_size": [str(fixture["semantic_body"]["page_size"])],
711+
}
712+
713+
assert [execution.workflow_id for execution in result.executions] == fixture["semantic_body"]["workflow_ids"]
714+
assert result.next_page_token == fixture["semantic_body"]["next_page_token"]
715+
689716

690717
class TestTaskQueues:
691718
@pytest.mark.asyncio

0 commit comments

Comments
 (0)