feat: restore zhihu browser skills
Reconnect the recovered Zhihu skill flows to the live browser runtime and resolve their resources relative to the executable so they work outside the repo root. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
661
tests/zhihu_navigation_skill_test.rs
Normal file
661
tests/zhihu_navigation_skill_test.rs
Normal file
@@ -0,0 +1,661 @@
|
||||
mod common;
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use common::MockTransport;
|
||||
use sgclaw::pipe::{Action, AgentMessage, BrowserMessage, BrowserPipeTool, Timing};
|
||||
use sgclaw::security::MacPolicy;
|
||||
use sgclaw::skill::zhihu_navigation::{execute, load_catalog, ZhihuNavigateRequest};
|
||||
|
||||
fn test_policy() -> MacPolicy {
|
||||
MacPolicy::from_json_str(
|
||||
r#"{
|
||||
"version": "1.0",
|
||||
"domains": { "allowed": ["www.zhihu.com", "zhuanlan.zhihu.com"] },
|
||||
"pipe_actions": {
|
||||
"allowed": ["click", "navigate", "getText", "waitForSelector"],
|
||||
"blocked": []
|
||||
}
|
||||
}"#,
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn response(seq: u64, data: serde_json::Value) -> BrowserMessage {
|
||||
BrowserMessage::Response {
|
||||
seq,
|
||||
success: true,
|
||||
data,
|
||||
aom_snapshot: vec![],
|
||||
timing: Timing {
|
||||
queue_ms: 1,
|
||||
exec_ms: 10,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn load_catalog_preserves_confirmed_content_analysis_route() {
|
||||
let catalog = load_catalog().unwrap();
|
||||
|
||||
assert_eq!(catalog.domains["creator"], "www.zhihu.com");
|
||||
assert_eq!(
|
||||
catalog.routes["content_analysis"].url,
|
||||
"https://www.zhihu.com/creator/analytics/work/all"
|
||||
);
|
||||
assert_eq!(
|
||||
catalog.targets["content_analysis"].route_ref.as_deref(),
|
||||
Some("content_analysis")
|
||||
);
|
||||
assert!(catalog.routes["content_analysis"]
|
||||
.aliases
|
||||
.iter()
|
||||
.any(|alias| alias == "知乎内容分析页面"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn load_catalog_includes_top_level_navigation_targets() {
|
||||
let catalog = load_catalog().unwrap();
|
||||
|
||||
assert_eq!(catalog.routes["home"].url, "https://www.zhihu.com/");
|
||||
assert_eq!(catalog.routes["hot_list"].url, "https://www.zhihu.com/hot");
|
||||
assert_eq!(
|
||||
catalog.routes["column_home"].url,
|
||||
"https://zhuanlan.zhihu.com/"
|
||||
);
|
||||
assert_eq!(
|
||||
catalog.routes["messages_page"].url,
|
||||
"https://www.zhihu.com/messages"
|
||||
);
|
||||
assert_eq!(
|
||||
catalog.routes["notifications_page"].url,
|
||||
"https://www.zhihu.com/notifications"
|
||||
);
|
||||
assert_eq!(
|
||||
catalog.targets["messages_unread_tab"]
|
||||
.component_ref
|
||||
.as_deref(),
|
||||
Some("messages_tab_unread")
|
||||
);
|
||||
assert_eq!(
|
||||
catalog.targets["notifications_replies_tab"]
|
||||
.component_ref
|
||||
.as_deref(),
|
||||
Some("notifications_tab_replies")
|
||||
);
|
||||
assert_eq!(
|
||||
catalog.targets["notifications_settings_menu"]
|
||||
.component_ref
|
||||
.as_deref(),
|
||||
Some("notifications_settings_menu")
|
||||
);
|
||||
assert_eq!(
|
||||
catalog.targets["profile_page"].flow_ref.as_deref(),
|
||||
Some("open_profile_from_avatar_menu")
|
||||
);
|
||||
assert_eq!(
|
||||
catalog.targets["notifications_menu"].flow_ref.as_deref(),
|
||||
Some("open_notifications_menu")
|
||||
);
|
||||
assert_eq!(
|
||||
catalog.targets["search_box"].component_ref.as_deref(),
|
||||
Some("top_nav_search")
|
||||
);
|
||||
assert_eq!(
|
||||
catalog.components["creator_write_button"]
|
||||
.result_domain_ref
|
||||
.as_deref(),
|
||||
Some("editor")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn load_catalog_includes_expanded_profile_and_settings_flows() {
|
||||
let catalog = load_catalog().unwrap();
|
||||
|
||||
assert_eq!(
|
||||
catalog.targets["profile_answers_tab"].flow_ref.as_deref(),
|
||||
Some("open_profile_answers_tab")
|
||||
);
|
||||
assert_eq!(
|
||||
catalog.targets["profile_followers_tab"].flow_ref.as_deref(),
|
||||
Some("open_profile_followers_tab")
|
||||
);
|
||||
assert_eq!(
|
||||
catalog.targets["settings_account_menu"].flow_ref.as_deref(),
|
||||
Some("open_account_settings_from_avatar_menu")
|
||||
);
|
||||
assert_eq!(
|
||||
catalog.targets["settings_privacy_menu"].flow_ref.as_deref(),
|
||||
Some("open_privacy_settings_from_avatar_menu")
|
||||
);
|
||||
assert_eq!(
|
||||
catalog.targets["settings_security_menu"]
|
||||
.flow_ref
|
||||
.as_deref(),
|
||||
Some("open_security_settings_from_avatar_menu")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn zhihu_navigation_skill_opens_content_analysis_page() {
|
||||
let transport = Arc::new(MockTransport::new(vec![response(
|
||||
1,
|
||||
serde_json::json!({ "url": "https://www.zhihu.com/creator/analytics/work/all" }),
|
||||
)]));
|
||||
let browser_tool = BrowserPipeTool::new(
|
||||
transport.clone(),
|
||||
test_policy(),
|
||||
vec![1, 2, 3, 4, 5, 6, 7, 8],
|
||||
)
|
||||
.with_response_timeout(Duration::from_secs(1));
|
||||
|
||||
let result = execute(
|
||||
transport.as_ref(),
|
||||
&browser_tool,
|
||||
ZhihuNavigateRequest {
|
||||
page: "content_analysis".to_string(),
|
||||
ensure_loaded: true,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let sent = transport.sent_messages();
|
||||
|
||||
assert_eq!(
|
||||
result.summary,
|
||||
"知乎页面已打开:内容分析 (https://www.zhihu.com/creator/analytics/work/all)"
|
||||
);
|
||||
assert_eq!(result.page, "content_analysis");
|
||||
assert_eq!(
|
||||
result.final_url,
|
||||
"https://www.zhihu.com/creator/analytics/work/all"
|
||||
);
|
||||
assert_eq!(sent.len(), 2);
|
||||
assert!(matches!(
|
||||
&sent[0],
|
||||
AgentMessage::LogEntry { level, message }
|
||||
if level == "info"
|
||||
&& message == "navigate https://www.zhihu.com/creator/analytics/work/all"
|
||||
));
|
||||
assert!(matches!(
|
||||
&sent[1],
|
||||
AgentMessage::Command { seq, action, .. }
|
||||
if *seq == 1 && action == &Action::Navigate
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn zhihu_navigation_skill_clicks_creator_write_button() {
|
||||
let transport = Arc::new(MockTransport::new(vec![
|
||||
response(
|
||||
1,
|
||||
serde_json::json!({ "url": "https://www.zhihu.com/creator" }),
|
||||
),
|
||||
response(
|
||||
2,
|
||||
serde_json::json!({ "clicked": true, "url": "https://zhuanlan.zhihu.com/write" }),
|
||||
),
|
||||
response(
|
||||
3,
|
||||
serde_json::json!({ "ready": true, "url": "https://zhuanlan.zhihu.com/write" }),
|
||||
),
|
||||
]));
|
||||
let browser_tool = BrowserPipeTool::new(
|
||||
transport.clone(),
|
||||
test_policy(),
|
||||
vec![1, 2, 3, 4, 5, 6, 7, 8],
|
||||
)
|
||||
.with_response_timeout(Duration::from_secs(1));
|
||||
|
||||
let result = execute(
|
||||
transport.as_ref(),
|
||||
&browser_tool,
|
||||
ZhihuNavigateRequest {
|
||||
page: "creator_write_button".to_string(),
|
||||
ensure_loaded: true,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let sent = transport.sent_messages();
|
||||
|
||||
assert_eq!(
|
||||
result.summary,
|
||||
"知乎入口已打开:写文章入口按钮 (https://zhuanlan.zhihu.com/write)"
|
||||
);
|
||||
assert_eq!(result.page, "creator_write_button");
|
||||
assert_eq!(result.final_url, "https://zhuanlan.zhihu.com/write");
|
||||
assert_eq!(sent.len(), 6);
|
||||
assert!(matches!(
|
||||
&sent[0],
|
||||
AgentMessage::LogEntry { level, message }
|
||||
if level == "info" && message == "navigate https://www.zhihu.com/creator"
|
||||
));
|
||||
assert!(matches!(
|
||||
&sent[1],
|
||||
AgentMessage::Command { seq, action, .. }
|
||||
if *seq == 1 && action == &Action::Navigate
|
||||
));
|
||||
assert!(matches!(
|
||||
&sent[2],
|
||||
AgentMessage::LogEntry { level, message }
|
||||
if level == "info" && message == "click 写文章入口按钮"
|
||||
));
|
||||
assert!(matches!(
|
||||
&sent[3],
|
||||
AgentMessage::Command { seq, action, security, .. }
|
||||
if *seq == 2 && action == &Action::Click && security.expected_domain == "www.zhihu.com"
|
||||
));
|
||||
assert!(matches!(
|
||||
&sent[4],
|
||||
AgentMessage::LogEntry { level, message }
|
||||
if level == "info" && message.contains("wait for textarea")
|
||||
));
|
||||
assert!(matches!(
|
||||
&sent[5],
|
||||
AgentMessage::Command { seq, action, security, .. }
|
||||
if *seq == 3 && action == &Action::WaitForSelector && security.expected_domain == "zhuanlan.zhihu.com"
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn zhihu_navigation_skill_opens_notifications_menu_flow() {
|
||||
let transport = Arc::new(MockTransport::new(vec![
|
||||
response(1, serde_json::json!({ "url": "https://www.zhihu.com/" })),
|
||||
response(2, serde_json::json!({ "clicked": true })),
|
||||
]));
|
||||
let browser_tool = BrowserPipeTool::new(
|
||||
transport.clone(),
|
||||
test_policy(),
|
||||
vec![1, 2, 3, 4, 5, 6, 7, 8],
|
||||
)
|
||||
.with_response_timeout(Duration::from_secs(1));
|
||||
|
||||
let result = execute(
|
||||
transport.as_ref(),
|
||||
&browser_tool,
|
||||
ZhihuNavigateRequest {
|
||||
page: "notifications_menu".to_string(),
|
||||
ensure_loaded: true,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let sent = transport.sent_messages();
|
||||
|
||||
assert_eq!(result.summary, "知乎菜单已打开:通知菜单");
|
||||
assert_eq!(result.page, "notifications_menu");
|
||||
assert_eq!(result.final_url, "https://www.zhihu.com/");
|
||||
assert_eq!(sent.len(), 4);
|
||||
assert!(matches!(
|
||||
&sent[0],
|
||||
AgentMessage::LogEntry { level, message }
|
||||
if level == "info" && message == "navigate https://www.zhihu.com/"
|
||||
));
|
||||
assert!(matches!(
|
||||
&sent[1],
|
||||
AgentMessage::Command { seq, action, .. }
|
||||
if *seq == 1 && action == &Action::Navigate
|
||||
));
|
||||
assert!(matches!(
|
||||
&sent[2],
|
||||
AgentMessage::LogEntry { level, message }
|
||||
if level == "info" && message == "click 通知菜单"
|
||||
));
|
||||
assert!(matches!(
|
||||
&sent[3],
|
||||
AgentMessage::Command { seq, action, security, .. }
|
||||
if *seq == 2 && action == &Action::Click && security.expected_domain == "www.zhihu.com"
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn zhihu_navigation_skill_opens_profile_page_from_avatar_menu() {
|
||||
let transport = Arc::new(MockTransport::new(vec![
|
||||
response(1, serde_json::json!({ "url": "https://www.zhihu.com/" })),
|
||||
response(2, serde_json::json!({ "clicked": true })),
|
||||
response(
|
||||
3,
|
||||
serde_json::json!({ "clicked": true, "url": "https://www.zhihu.com/people/test-user" }),
|
||||
),
|
||||
]));
|
||||
let browser_tool = BrowserPipeTool::new(
|
||||
transport.clone(),
|
||||
test_policy(),
|
||||
vec![1, 2, 3, 4, 5, 6, 7, 8],
|
||||
)
|
||||
.with_response_timeout(Duration::from_secs(1));
|
||||
|
||||
let result = execute(
|
||||
transport.as_ref(),
|
||||
&browser_tool,
|
||||
ZhihuNavigateRequest {
|
||||
page: "profile_page".to_string(),
|
||||
ensure_loaded: true,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let sent = transport.sent_messages();
|
||||
|
||||
assert_eq!(
|
||||
result.summary,
|
||||
"知乎导航已完成:个人主页 (https://www.zhihu.com/people/test-user)"
|
||||
);
|
||||
assert_eq!(result.page, "profile_page");
|
||||
assert_eq!(result.final_url, "https://www.zhihu.com/people/test-user");
|
||||
assert_eq!(sent.len(), 6);
|
||||
assert!(matches!(
|
||||
&sent[0],
|
||||
AgentMessage::LogEntry { level, message }
|
||||
if level == "info" && message == "navigate https://www.zhihu.com/"
|
||||
));
|
||||
assert!(matches!(
|
||||
&sent[1],
|
||||
AgentMessage::Command { seq, action, .. }
|
||||
if *seq == 1 && action == &Action::Navigate
|
||||
));
|
||||
assert!(matches!(
|
||||
&sent[2],
|
||||
AgentMessage::LogEntry { level, message }
|
||||
if level == "info" && message == "click 头像菜单"
|
||||
));
|
||||
assert!(matches!(
|
||||
&sent[3],
|
||||
AgentMessage::Command { seq, action, .. }
|
||||
if *seq == 2 && action == &Action::Click
|
||||
));
|
||||
assert!(matches!(
|
||||
&sent[4],
|
||||
AgentMessage::LogEntry { level, message }
|
||||
if level == "info" && message == "click 个人主页入口"
|
||||
));
|
||||
assert!(matches!(
|
||||
&sent[5],
|
||||
AgentMessage::Command { seq, action, security, .. }
|
||||
if *seq == 3 && action == &Action::Click && security.expected_domain == "www.zhihu.com"
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn zhihu_navigation_skill_opens_profile_answers_tab_from_avatar_menu() {
|
||||
let transport = Arc::new(MockTransport::new(vec![
|
||||
response(1, serde_json::json!({ "url": "https://www.zhihu.com/" })),
|
||||
response(2, serde_json::json!({ "clicked": true })),
|
||||
response(
|
||||
3,
|
||||
serde_json::json!({ "clicked": true, "url": "https://www.zhihu.com/people/test-user" }),
|
||||
),
|
||||
response(
|
||||
4,
|
||||
serde_json::json!({ "clicked": true, "url": "https://www.zhihu.com/people/test-user/answers" }),
|
||||
),
|
||||
]));
|
||||
let browser_tool = BrowserPipeTool::new(
|
||||
transport.clone(),
|
||||
test_policy(),
|
||||
vec![1, 2, 3, 4, 5, 6, 7, 8],
|
||||
)
|
||||
.with_response_timeout(Duration::from_secs(1));
|
||||
|
||||
let result = execute(
|
||||
transport.as_ref(),
|
||||
&browser_tool,
|
||||
ZhihuNavigateRequest {
|
||||
page: "profile_answers_tab".to_string(),
|
||||
ensure_loaded: true,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let sent = transport.sent_messages();
|
||||
|
||||
assert_eq!(
|
||||
result.summary,
|
||||
"知乎导航已完成:回答分栏 (https://www.zhihu.com/people/test-user/answers)"
|
||||
);
|
||||
assert_eq!(result.page, "profile_answers_tab");
|
||||
assert_eq!(
|
||||
result.final_url,
|
||||
"https://www.zhihu.com/people/test-user/answers"
|
||||
);
|
||||
assert_eq!(sent.len(), 8);
|
||||
assert!(matches!(
|
||||
&sent[0],
|
||||
AgentMessage::LogEntry { level, message }
|
||||
if level == "info" && message == "navigate https://www.zhihu.com/"
|
||||
));
|
||||
assert!(matches!(
|
||||
&sent[1],
|
||||
AgentMessage::Command { seq, action, .. }
|
||||
if *seq == 1 && action == &Action::Navigate
|
||||
));
|
||||
assert!(matches!(
|
||||
&sent[2],
|
||||
AgentMessage::LogEntry { level, message }
|
||||
if level == "info" && message == "click 头像菜单"
|
||||
));
|
||||
assert!(matches!(
|
||||
&sent[3],
|
||||
AgentMessage::Command { seq, action, .. }
|
||||
if *seq == 2 && action == &Action::Click
|
||||
));
|
||||
assert!(matches!(
|
||||
&sent[4],
|
||||
AgentMessage::LogEntry { level, message }
|
||||
if level == "info" && message == "click 个人主页入口"
|
||||
));
|
||||
assert!(matches!(
|
||||
&sent[5],
|
||||
AgentMessage::Command { seq, action, .. }
|
||||
if *seq == 3 && action == &Action::Click
|
||||
));
|
||||
assert!(matches!(
|
||||
&sent[6],
|
||||
AgentMessage::LogEntry { level, message }
|
||||
if level == "info" && message == "click 回答分栏"
|
||||
));
|
||||
assert!(matches!(
|
||||
&sent[7],
|
||||
AgentMessage::Command { seq, action, security, .. }
|
||||
if *seq == 4 && action == &Action::Click && security.expected_domain == "www.zhihu.com"
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn zhihu_navigation_skill_opens_account_settings_from_avatar_menu() {
|
||||
let transport = Arc::new(MockTransport::new(vec![
|
||||
response(1, serde_json::json!({ "url": "https://www.zhihu.com/" })),
|
||||
response(2, serde_json::json!({ "clicked": true })),
|
||||
response(
|
||||
3,
|
||||
serde_json::json!({ "clicked": true, "url": "https://www.zhihu.com/settings/account" }),
|
||||
),
|
||||
]));
|
||||
let browser_tool = BrowserPipeTool::new(
|
||||
transport.clone(),
|
||||
test_policy(),
|
||||
vec![1, 2, 3, 4, 5, 6, 7, 8],
|
||||
)
|
||||
.with_response_timeout(Duration::from_secs(1));
|
||||
|
||||
let result = execute(
|
||||
transport.as_ref(),
|
||||
&browser_tool,
|
||||
ZhihuNavigateRequest {
|
||||
page: "settings_account_menu".to_string(),
|
||||
ensure_loaded: true,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let sent = transport.sent_messages();
|
||||
|
||||
assert_eq!(
|
||||
result.summary,
|
||||
"知乎导航已完成:账号设置菜单 (https://www.zhihu.com/settings/account)"
|
||||
);
|
||||
assert_eq!(result.page, "settings_account_menu");
|
||||
assert_eq!(result.final_url, "https://www.zhihu.com/settings/account");
|
||||
assert_eq!(sent.len(), 6);
|
||||
assert!(matches!(
|
||||
&sent[0],
|
||||
AgentMessage::LogEntry { level, message }
|
||||
if level == "info" && message == "navigate https://www.zhihu.com/"
|
||||
));
|
||||
assert!(matches!(
|
||||
&sent[1],
|
||||
AgentMessage::Command { seq, action, .. }
|
||||
if *seq == 1 && action == &Action::Navigate
|
||||
));
|
||||
assert!(matches!(
|
||||
&sent[2],
|
||||
AgentMessage::LogEntry { level, message }
|
||||
if level == "info" && message == "click 头像菜单"
|
||||
));
|
||||
assert!(matches!(
|
||||
&sent[3],
|
||||
AgentMessage::Command { seq, action, .. }
|
||||
if *seq == 2 && action == &Action::Click
|
||||
));
|
||||
assert!(matches!(
|
||||
&sent[4],
|
||||
AgentMessage::LogEntry { level, message }
|
||||
if level == "info" && message == "click 账号设置菜单"
|
||||
));
|
||||
assert!(matches!(
|
||||
&sent[5],
|
||||
AgentMessage::Command { seq, action, security, .. }
|
||||
if *seq == 3 && action == &Action::Click && security.expected_domain == "www.zhihu.com"
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn zhihu_navigation_skill_opens_notifications_replies_tab() {
|
||||
let transport = Arc::new(MockTransport::new(vec![
|
||||
response(
|
||||
1,
|
||||
serde_json::json!({ "url": "https://www.zhihu.com/notifications" }),
|
||||
),
|
||||
response(
|
||||
2,
|
||||
serde_json::json!({ "clicked": true, "url": "https://www.zhihu.com/notifications/replies" }),
|
||||
),
|
||||
]));
|
||||
let browser_tool = BrowserPipeTool::new(
|
||||
transport.clone(),
|
||||
test_policy(),
|
||||
vec![1, 2, 3, 4, 5, 6, 7, 8],
|
||||
)
|
||||
.with_response_timeout(Duration::from_secs(1));
|
||||
|
||||
let result = execute(
|
||||
transport.as_ref(),
|
||||
&browser_tool,
|
||||
ZhihuNavigateRequest {
|
||||
page: "notifications_replies_tab".to_string(),
|
||||
ensure_loaded: true,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let sent = transport.sent_messages();
|
||||
|
||||
assert_eq!(
|
||||
result.summary,
|
||||
"知乎入口已打开:回复我的 (https://www.zhihu.com/notifications/replies)"
|
||||
);
|
||||
assert_eq!(sent.len(), 4);
|
||||
assert!(matches!(
|
||||
&sent[0],
|
||||
AgentMessage::LogEntry { level, message }
|
||||
if level == "info" && message == "navigate https://www.zhihu.com/notifications"
|
||||
));
|
||||
assert!(matches!(
|
||||
&sent[1],
|
||||
AgentMessage::Command { seq, action, .. }
|
||||
if *seq == 1 && action == &Action::Navigate
|
||||
));
|
||||
assert!(matches!(
|
||||
&sent[2],
|
||||
AgentMessage::LogEntry { level, message }
|
||||
if level == "info" && message == "click 回复我的"
|
||||
));
|
||||
assert!(matches!(
|
||||
&sent[3],
|
||||
AgentMessage::Command { seq, action, security, .. }
|
||||
if *seq == 2 && action == &Action::Click && security.expected_domain == "www.zhihu.com"
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn zhihu_navigation_skill_opens_messages_settings_menu() {
|
||||
let transport = Arc::new(MockTransport::new(vec![
|
||||
response(
|
||||
1,
|
||||
serde_json::json!({ "url": "https://www.zhihu.com/messages" }),
|
||||
),
|
||||
response(2, serde_json::json!({ "clicked": true })),
|
||||
]));
|
||||
let browser_tool = BrowserPipeTool::new(
|
||||
transport.clone(),
|
||||
test_policy(),
|
||||
vec![1, 2, 3, 4, 5, 6, 7, 8],
|
||||
)
|
||||
.with_response_timeout(Duration::from_secs(1));
|
||||
|
||||
let result = execute(
|
||||
transport.as_ref(),
|
||||
&browser_tool,
|
||||
ZhihuNavigateRequest {
|
||||
page: "messages_settings_menu".to_string(),
|
||||
ensure_loaded: true,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let sent = transport.sent_messages();
|
||||
|
||||
assert_eq!(result.summary, "知乎菜单已打开:消息设置菜单");
|
||||
assert_eq!(result.final_url, "https://www.zhihu.com/messages");
|
||||
assert_eq!(sent.len(), 4);
|
||||
assert!(matches!(
|
||||
&sent[0],
|
||||
AgentMessage::LogEntry { level, message }
|
||||
if level == "info" && message == "navigate https://www.zhihu.com/messages"
|
||||
));
|
||||
assert!(matches!(
|
||||
&sent[1],
|
||||
AgentMessage::Command { seq, action, .. }
|
||||
if *seq == 1 && action == &Action::Navigate
|
||||
));
|
||||
assert!(matches!(
|
||||
&sent[2],
|
||||
AgentMessage::LogEntry { level, message }
|
||||
if level == "info" && message == "click 消息设置菜单"
|
||||
));
|
||||
assert!(matches!(
|
||||
&sent[3],
|
||||
AgentMessage::Command { seq, action, security, .. }
|
||||
if *seq == 2 && action == &Action::Click && security.expected_domain == "www.zhihu.com"
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn zhihu_navigation_skill_rejects_unknown_target() {
|
||||
let transport = Arc::new(MockTransport::new(vec![]));
|
||||
let browser_tool = BrowserPipeTool::new(
|
||||
transport.clone(),
|
||||
test_policy(),
|
||||
vec![1, 2, 3, 4, 5, 6, 7, 8],
|
||||
)
|
||||
.with_response_timeout(Duration::from_secs(1));
|
||||
|
||||
let err = execute(
|
||||
transport.as_ref(),
|
||||
&browser_tool,
|
||||
ZhihuNavigateRequest {
|
||||
page: "unknown_target".to_string(),
|
||||
ensure_loaded: true,
|
||||
},
|
||||
)
|
||||
.unwrap_err();
|
||||
|
||||
assert!(err
|
||||
.to_string()
|
||||
.contains("unknown zhihu target: unknown_target"));
|
||||
}
|
||||
Reference in New Issue
Block a user