mirror of
https://github.com/actionbook/actionbook.git
synced 2026-09-19 03:28:06 +08:00
266 lines
6.6 KiB
Rust
266 lines
6.6 KiB
Rust
//! E2E tests for `browser pdf`.
|
|
|
|
use crate::harness::{
|
|
SessionGuard, assert_failure, assert_success, headless, headless_json, parse_json, skip,
|
|
stdout_str,
|
|
};
|
|
|
|
fn start_session() -> (String, String) {
|
|
let out = headless_json(
|
|
&[
|
|
"browser",
|
|
"start",
|
|
"--mode",
|
|
"local",
|
|
"--headless",
|
|
"--open-url",
|
|
"about:blank",
|
|
],
|
|
30,
|
|
);
|
|
assert_success(&out, "start session");
|
|
let v = parse_json(&out);
|
|
let sid = v["data"]["session"]["session_id"]
|
|
.as_str()
|
|
.unwrap()
|
|
.to_string();
|
|
let tid = v["data"]["tab"]["tab_id"].as_str().unwrap().to_string();
|
|
|
|
let goto_out = headless_json(
|
|
&[
|
|
"browser",
|
|
"goto",
|
|
"about:blank",
|
|
"--session",
|
|
&sid,
|
|
"--tab",
|
|
&tid,
|
|
],
|
|
30,
|
|
);
|
|
assert_success(&goto_out, "goto about:blank");
|
|
|
|
(sid, tid)
|
|
}
|
|
|
|
fn inject_fixture(sid: &str, tid: &str) {
|
|
let js = r#"document.body.innerHTML = `
|
|
<main>
|
|
<h1>PDF Contract Fixture</h1>
|
|
<p>Export this page to PDF.</p>
|
|
</main>
|
|
`;
|
|
document.title = 'PDF Fixture';
|
|
void(0)"#;
|
|
let out = headless_json(&["browser", "eval", js, "--session", sid, "--tab", tid], 10);
|
|
assert_success(&out, "inject fixture");
|
|
}
|
|
|
|
fn assert_meta(v: &serde_json::Value) {
|
|
assert!(v["meta"]["duration_ms"].is_number());
|
|
assert!(v["meta"]["warnings"].is_array());
|
|
assert!(v["meta"]["pagination"].is_null());
|
|
assert!(v["meta"]["truncated"].is_boolean());
|
|
}
|
|
|
|
fn assert_error_envelope(v: &serde_json::Value, expected_code: &str) {
|
|
assert_eq!(v["ok"], false);
|
|
assert!(v["data"].is_null());
|
|
assert_eq!(v["error"]["code"], expected_code);
|
|
assert!(v["error"]["message"].is_string());
|
|
assert!(v["error"]["retryable"].is_boolean());
|
|
assert!(v["error"]["details"].is_object() || v["error"]["details"].is_null());
|
|
assert_meta(v);
|
|
}
|
|
|
|
#[test]
|
|
fn pdf_json_happy_path() {
|
|
if skip() {
|
|
return;
|
|
}
|
|
|
|
let (sid, tid) = start_session();
|
|
let _guard = SessionGuard::new(&sid);
|
|
inject_fixture(&sid, &tid);
|
|
|
|
let tmp = tempfile::tempdir().expect("create temp dir");
|
|
let path = tmp.path().join("fixture.pdf");
|
|
let path_str = path.to_string_lossy().to_string();
|
|
|
|
let out = headless_json(
|
|
&[
|
|
"browser",
|
|
"pdf",
|
|
&path_str,
|
|
"--session",
|
|
&sid,
|
|
"--tab",
|
|
&tid,
|
|
],
|
|
30,
|
|
);
|
|
assert_success(&out, "pdf json");
|
|
let v = parse_json(&out);
|
|
let metadata = std::fs::metadata(&path).expect("pdf file should exist");
|
|
|
|
assert_eq!(v["command"], "browser.pdf");
|
|
assert_eq!(v["ok"], true);
|
|
assert!(v["error"].is_null());
|
|
assert_meta(&v);
|
|
assert_eq!(v["context"]["session_id"], sid);
|
|
assert_eq!(v["context"]["tab_id"], tid);
|
|
assert_eq!(v["context"]["title"], "PDF Fixture");
|
|
assert_eq!(v["data"]["artifact"]["path"], path_str);
|
|
assert_eq!(v["data"]["artifact"]["mime_type"], "application/pdf");
|
|
assert_eq!(v["data"]["artifact"]["bytes"], metadata.len());
|
|
assert!(
|
|
metadata.len() > 0,
|
|
"pdf file should be non-empty: {}",
|
|
path.display()
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn pdf_text_output() {
|
|
if skip() {
|
|
return;
|
|
}
|
|
|
|
let (sid, tid) = start_session();
|
|
let _guard = SessionGuard::new(&sid);
|
|
inject_fixture(&sid, &tid);
|
|
|
|
let tmp = tempfile::tempdir().expect("create temp dir");
|
|
let path = tmp.path().join("fixture.pdf");
|
|
let path_str = path.to_string_lossy().to_string();
|
|
|
|
let out = headless(
|
|
&[
|
|
"browser",
|
|
"pdf",
|
|
&path_str,
|
|
"--session",
|
|
&sid,
|
|
"--tab",
|
|
&tid,
|
|
],
|
|
30,
|
|
);
|
|
assert_success(&out, "pdf text");
|
|
let text = stdout_str(&out);
|
|
let lines: Vec<&str> = text.lines().collect();
|
|
|
|
assert!(
|
|
lines
|
|
.first()
|
|
.unwrap_or(&"")
|
|
.starts_with(&format!("[{sid} {tid}]")),
|
|
"header must start with [session_id tab_id]: {text}"
|
|
);
|
|
assert!(
|
|
lines.first().unwrap_or(&"").contains("about:blank"),
|
|
"header must contain current URL: {text}"
|
|
);
|
|
assert_eq!(lines.get(1), Some(&"ok browser.pdf"));
|
|
assert_eq!(lines.get(2), Some(&format!("path: {path_str}").as_str()));
|
|
}
|
|
|
|
#[test]
|
|
fn pdf_artifact_write_failed_json() {
|
|
if skip() {
|
|
return;
|
|
}
|
|
|
|
let (sid, tid) = start_session();
|
|
let _guard = SessionGuard::new(&sid);
|
|
inject_fixture(&sid, &tid);
|
|
|
|
let tmp = tempfile::tempdir().expect("create temp dir");
|
|
let bad_path = tmp.path().to_string_lossy().to_string();
|
|
|
|
let out = headless_json(
|
|
&[
|
|
"browser",
|
|
"pdf",
|
|
&bad_path,
|
|
"--session",
|
|
&sid,
|
|
"--tab",
|
|
&tid,
|
|
],
|
|
30,
|
|
);
|
|
assert_failure(&out, "pdf bad path");
|
|
let v = parse_json(&out);
|
|
|
|
assert_eq!(v["command"], "browser.pdf");
|
|
assert_eq!(v["context"]["session_id"], sid);
|
|
assert_eq!(v["context"]["tab_id"], tid);
|
|
assert_error_envelope(&v, "ARTIFACT_WRITE_FAILED");
|
|
}
|
|
|
|
#[test]
|
|
fn pdf_session_not_found_json() {
|
|
if skip() {
|
|
return;
|
|
}
|
|
|
|
let tmp = tempfile::tempdir().expect("create temp dir");
|
|
let path = tmp.path().join("missing-session.pdf");
|
|
let path_str = path.to_string_lossy().to_string();
|
|
|
|
let out = headless_json(
|
|
&[
|
|
"browser",
|
|
"pdf",
|
|
&path_str,
|
|
"--session",
|
|
"missing-session",
|
|
"--tab",
|
|
"any-tab",
|
|
],
|
|
10,
|
|
);
|
|
assert_failure(&out, "pdf missing session");
|
|
let v = parse_json(&out);
|
|
|
|
assert_eq!(v["command"], "browser.pdf");
|
|
assert!(v["context"].is_null());
|
|
assert_error_envelope(&v, "SESSION_NOT_FOUND");
|
|
}
|
|
|
|
#[test]
|
|
fn pdf_tab_not_found_json() {
|
|
if skip() {
|
|
return;
|
|
}
|
|
|
|
let (sid, _tid) = start_session();
|
|
let _guard = SessionGuard::new(&sid);
|
|
|
|
let tmp = tempfile::tempdir().expect("create temp dir");
|
|
let path = tmp.path().join("missing-tab.pdf");
|
|
let path_str = path.to_string_lossy().to_string();
|
|
|
|
let out = headless_json(
|
|
&[
|
|
"browser",
|
|
"pdf",
|
|
&path_str,
|
|
"--session",
|
|
&sid,
|
|
"--tab",
|
|
"missing-tab",
|
|
],
|
|
10,
|
|
);
|
|
assert_failure(&out, "pdf missing tab");
|
|
let v = parse_json(&out);
|
|
|
|
assert_eq!(v["command"], "browser.pdf");
|
|
assert!(v["context"].is_object());
|
|
assert_eq!(v["context"]["session_id"], sid);
|
|
assert!(v["context"]["tab_id"].is_null());
|
|
assert_error_envelope(&v, "TAB_NOT_FOUND");
|
|
}
|