use flarer::{Account, Flarer, JsonOptions, Output, ResponseFormat, Tool};
use reqwest::Url;
use serde_json::json;
use wiremock::matchers::{header, method, path};
use wiremock::{Mock, MockServer, ResponseTemplate};
const ACCOUNT: &str = "test-account";
async fn make_flarer(server: &MockServer) -> Flarer {
let base = Url::parse(&server.uri()).unwrap();
Flarer::builder()
.account(Account::new(ACCOUNT, "test-token"))
.base_url(base)
.build()
.unwrap()
}
#[tokio::test]
async fn verify_succeeds_on_2xx() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path(format!("/accounts/{ACCOUNT}/tokens/verify")))
.and(header("authorization", "Bearer test-token"))
.respond_with(ResponseTemplate::new(200).set_body_json(json!({"success": true})))
.mount(&server)
.await;
let flarer = make_flarer(&server).await;
flarer.verify().await.expect("verify should succeed");
}
#[tokio::test]
async fn verify_fails_on_401() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path(format!("/accounts/{ACCOUNT}/tokens/verify")))
.respond_with(ResponseTemplate::new(401).set_body_string("nope"))
.mount(&server)
.await;
let flarer = make_flarer(&server).await;
let err = flarer.verify().await.unwrap_err();
assert!(matches!(err, flarer::FlarerError::Auth(_)));
}
#[tokio::test]
async fn markdown_returns_json() {
let server = MockServer::start().await;
let body = json!({"success": true, "result": "# hello"});
Mock::given(method("POST"))
.and(path(format!(
"/accounts/{ACCOUNT}/browser-rendering/markdown"
)))
.respond_with(ResponseTemplate::new(200).set_body_json(body.clone()))
.mount(&server)
.await;
let flarer = make_flarer(&server).await;
let out = flarer
.run(Tool::Markdown, "https://example.com")
.await
.unwrap();
match out {
Output::Json(v) => assert_eq!(v, body),
other => panic!("unexpected: {other:?}"),
}
}
#[tokio::test]
async fn screenshot_writes_file() {
let server = MockServer::start().await;
let png = vec![0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a];
Mock::given(method("POST"))
.and(path(format!(
"/accounts/{ACCOUNT}/browser-rendering/screenshot"
)))
.respond_with(
ResponseTemplate::new(200)
.insert_header("content-type", "image/png")
.set_body_bytes(png.clone()),
)
.mount(&server)
.await;
let tmp = tempdir();
let flarer = Flarer::builder()
.account(Account::new(ACCOUNT, "test-token"))
.base_url(Url::parse(&server.uri()).unwrap())
.output_dir(&tmp)
.build()
.unwrap();
let out = flarer
.run(Tool::Screenshot, "https://example.com")
.await
.unwrap();
let path = match out {
Output::File(p) => p,
other => panic!("unexpected: {other:?}"),
};
let bytes = std::fs::read(&path).unwrap();
assert_eq!(bytes, png);
let _ = std::fs::remove_dir_all(&tmp);
}
#[tokio::test]
async fn json_tool_serializes_response_format_with_type_key() {
let server = MockServer::start().await;
Mock::given(method("POST"))
.and(path(format!("/accounts/{ACCOUNT}/browser-rendering/json")))
.respond_with(ResponseTemplate::new(200).set_body_json(json!({"success": true})))
.mount(&server)
.await;
let flarer = make_flarer(&server).await;
let opts = JsonOptions::new()
.with_prompt("hi")
.with_response_format(ResponseFormat::json_schema(json!({"type": "object"})));
let _ = flarer.json("https://example.com", opts).await.unwrap();
let received = server.received_requests().await.unwrap();
let last = received.last().unwrap();
let body: serde_json::Value = serde_json::from_slice(&last.body).unwrap();
assert_eq!(body["url"], "https://example.com/");
assert_eq!(body["prompt"], "hi");
assert_eq!(body["response_format"]["type"], "json_schema");
assert_eq!(body["response_format"]["schema"]["type"], "object");
}
#[tokio::test]
async fn api_error_propagates_status_and_body() {
let server = MockServer::start().await;
Mock::given(method("POST"))
.and(path(format!(
"/accounts/{ACCOUNT}/browser-rendering/content"
)))
.respond_with(ResponseTemplate::new(500).set_body_string("boom"))
.mount(&server)
.await;
let flarer = make_flarer(&server).await;
let err = flarer
.text(Tool::Content, "https://example.com")
.await
.unwrap_err();
match err {
flarer::FlarerError::Api { status, body } => {
assert_eq!(status, 500);
assert_eq!(body, "boom");
}
other => panic!("unexpected error: {other:?}"),
}
}
fn tempdir() -> std::path::PathBuf {
let mut p = std::env::temp_dir();
p.push(format!("flarer-test-{}", std::process::id()));
let _ = std::fs::create_dir_all(&p);
p
}