11import pytest
22
3- from backend .channels .doubao_research_channel import DoubaoResearchChannel , _citations
3+ from backend .channels .doubao_research_channel import (
4+ DoubaoResearchChannel ,
5+ _citations ,
6+ _conversation_url ,
7+ )
48from backend .schemas .source import DataSourceCreate
59
610
@@ -13,6 +17,29 @@ def test_citations_preserve_order_and_strip_punctuation():
1317 ]
1418
1519
20+ def test_conversation_url_extracts_chat_id ():
21+ status = (
22+ '[{"Status": "Connected", "Url": '
23+ '"https://www.doubao.com/chat/38436240748612354", "Title": "x"}]'
24+ )
25+ assert (
26+ _conversation_url (status )
27+ == "https://www.doubao.com/chat/38436240748612354"
28+ )
29+
30+
31+ def test_conversation_url_ignores_root_chat ():
32+ # A freshly opened /chat page has no conversation id yet — must not be picked up.
33+ status = (
34+ '[{"Status": "Connected", "Url": "https://www.doubao.com/chat", "Title": "x"}]'
35+ )
36+ assert _conversation_url (status ) == ""
37+
38+
39+ def test_conversation_url_tolerates_garbage ():
40+ assert _conversation_url ("not json at all" ) == ""
41+
42+
1643@pytest .mark .asyncio
1744async def test_collect_stores_answer_and_citations (monkeypatch ):
1845 async def fake_run (command ):
@@ -48,8 +75,76 @@ async def fake_run(command):
4875 assert result .items [0 ]["citations" ] == [{"url" : "https://example.com/" }]
4976
5077
78+ @pytest .mark .asyncio
79+ async def test_collect_captures_conversation_url (monkeypatch ):
80+ calls = []
81+
82+ async def fake_run (command ):
83+ calls .append (command )
84+ if command [2 ] == "ask" :
85+ return 0 , '[{"Role":"assistant","Text":"回答"}]' , ""
86+ if command [2 ] == "status" :
87+ return 0 , (
88+ '[{"Status": "Connected", "Url": '
89+ '"https://www.doubao.com/chat/12345", "Title": "t"}]'
90+ ), ""
91+ return 0 , "" , ""
92+
93+ monkeypatch .setattr ("backend.channels.doubao_research_channel._run_doubao_command" , fake_run )
94+ result = await DoubaoResearchChannel ().collect ({"question" : "测试" }, {})
95+
96+ assert result .success
97+ assert result .items [0 ]["conversation_url" ] == "https://www.doubao.com/chat/12345"
98+ # ask + status both hit the adapter
99+ assert [c [2 ] for c in calls ] == ["ask" , "status" ]
100+
101+
102+ @pytest .mark .asyncio
103+ async def test_collect_tolerates_status_failure (monkeypatch ):
104+ async def fake_run (command ):
105+ if command [2 ] == "ask" :
106+ return 0 , '[{"Role":"assistant","Text":"回答"}]' , ""
107+ return 1 , "" , "status exploded"
108+
109+ monkeypatch .setattr ("backend.channels.doubao_research_channel._run_doubao_command" , fake_run )
110+ result = await DoubaoResearchChannel ().collect ({"question" : "测试" }, {})
111+
112+ # A failed status must NOT fail the collect — answer is already in hand.
113+ assert result .success
114+ assert result .items [0 ]["conversation_url" ] == ""
115+
116+
117+ @pytest .mark .asyncio
118+ async def test_collect_classifies_captcha_block (monkeypatch ):
119+ async def fake_run (command ):
120+ return 1 , "" , (
121+ "ok: false\n error:\n code: COMMAND_EXEC\n "
122+ " message: Doubao blocked the request with a verification challenge\n "
123+ " help: 'Detected challenge signal: iframe[src*=\" captcha\" ]'"
124+ )
125+
126+ monkeypatch .setattr ("backend.channels.doubao_research_channel._run_doubao_command" , fake_run )
127+ result = await DoubaoResearchChannel ().collect ({"question" : "测试" }, {})
128+
129+ assert not result .success
130+ assert result .error_type == "captcha_challenge"
131+
132+
133+ @pytest .mark .asyncio
134+ async def test_collect_does_not_classify_generic_error (monkeypatch ):
135+ async def fake_run (command ):
136+ return 1 , "" , "some unrelated error"
137+
138+ monkeypatch .setattr ("backend.channels.doubao_research_channel._run_doubao_command" , fake_run )
139+ result = await DoubaoResearchChannel ().collect ({"question" : "测试" }, {})
140+
141+ assert not result .success
142+ assert result .error_type is None
143+
144+
51145def test_source_schema_accepts_doubao_research_channel ():
52146 source = DataSourceCreate (
53147 name = "Doubao research" , channel_type = "doubao_research" , channel_config = {"question" : "test" }
54148 )
55149 assert source .channel_type == "doubao_research"
150+
0 commit comments