From 1ebfc32609f3e8ba2be0bd774defa9ab5fc2bc29 Mon Sep 17 00:00:00 2001 From: Gerald Lonlas Date: Sat, 27 Jun 2026 01:11:38 +0800 Subject: [PATCH] test(client): cover all defensive branches in extract_responses_text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add four targeted tests hitting the previously uncovered branches in `client.extract_responses_text` (lines 221–233): dict items with a non-list content field, content list entries that are not dicts, dict entries whose text value is not a str, and object items where `getattr(entry, "text")` is non-str. Also declare `aiohttp` in the optional [test] extra so the full suite can import `routes.py` without a ModuleNotFoundError. Branch coverage: 99% (4 branches missed) → 100% (146/146 branches). Co-Authored-By: Claude Opus 4.8 --- pyproject.toml | 1 + tests/test_client_full.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 3202a6b..e1f0d4d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,6 +13,7 @@ dependencies = [ test = [ "pytest>=8.0.0", "pytest-cov>=5.0.0", + "aiohttp>=3.9.0", ] [tool.comfy] diff --git a/tests/test_client_full.py b/tests/test_client_full.py index 1e0ac5e..605bd60 100644 --- a/tests/test_client_full.py +++ b/tests/test_client_full.py @@ -196,6 +196,36 @@ def test_extract_responses_text_no_duplicate_when_item_has_content_and_text() -> +def test_extract_responses_text_dict_item_non_list_content_is_skipped() -> None: + # Branch 221->227: dict item where "content" is not a list. + # The function should skip it (continue) and return empty string — not crash. + response = ns(output=[{"content": "not-a-list"}, {"content": {"nested": "dict"}}]) + assert client.extract_responses_text(response) == "" + + +def test_extract_responses_text_dict_item_content_list_with_non_dict_entries() -> None: + # Branch 223->222: content list contains non-dict entries (e.g. plain strings). + # Those entries must be silently ignored; only dict entries with a str "text" key count. + response = ns(output=[{"content": ["string-entry", 42, None, {"text": "kept"}]}]) + assert client.extract_responses_text(response) == "kept" + + +def test_extract_responses_text_dict_item_content_entry_text_non_string() -> None: + # Branch 225->222: content entry is a dict but "text" value is not a str. + # These entries must be silently ignored. + response = ns(output=[{"content": [{"text": 42}, {"text": None}, {"text": "good"}]}]) + assert client.extract_responses_text(response) == "good" + + +def test_extract_responses_text_object_item_content_entry_text_non_string() -> None: + # Branch 233->231: object item with content list where getattr(entry, "text") is not a str. + # The entry should be skipped; other valid entries should still be collected. + bad_entry = ns(text=99) + good_entry = ns(text="valid") + response = ns(output=[ns(content=[bad_entry, good_entry])]) + assert client.extract_responses_text(response) == "valid" + + def test_strip_think_content_case_insensitive_and_multiple() -> None: text = "A\nhidden-1\nB\nhidden-2\nC" assert client.strip_think_content(text) == "A\n\nB\n\nC"