fix(cdp): return descriptive error for Page.printToPDF instead of generic Unknown Page method (#53) (#112)

Playwright's `page.pdf()` issues a `Page.printToPDF` CDP request which
Obscura was not handling, so the dispatcher fell through to the generic
catch-all and clients saw:

    Page.pdf: Protocol error (Page.printToPDF): Unknown Page method: printToPDF

This reads like an oversight rather than a deliberate limitation.
Obscura intentionally has no layout engine — option (2) from the issue —
so make the limitation explicit by handling the method and returning a
clear error that names the method, says why it isn't supported, and
points users at a working alternative (extract HTML via
Runtime.evaluate, then render to PDF in their client).

The behavior change is small but meaningful for DX: the JSON-RPC error
code stays -32601 (the dispatcher's mapping for `Err(_)`), but the
human-readable message becomes actionable instead of looking like a
forgotten method.

Adds a unit test that pins the regression: printToPDF must NOT fall
through to the "Unknown Page method" catch-all and must mention both
"not supported" and a workaround.

Generated by Ora Studio
Vibe coded by ousamabenyounes

Co-authored-by: Ora Studio <[email protected]>
This commit is contained in:
Ben YounesandOra Studio authored and GitHub committed 2026-05-09 17:36:11 +02:00
1 parent 7dfc2a9c01
commit 023caf9ce5
1 file changed
+39
+39
View File
@@ -273,6 +273,20 @@ pub async fn handle(
}]
}))
}
"printToPDF" => {
// Obscura has no layout/rendering engine, so PDF generation is
// intentionally not implemented. Returning a distinct, descriptive
// error (rather than the generic "Unknown Page method" fallback)
// tells Playwright/Puppeteer/headless_chrome clients exactly why
// the call failed and what to do instead.
Err(
"Page.printToPDF is not supported by Obscura: no layout engine. \
Use Runtime.evaluate (e.g. page.evaluate) to extract the rendered \
HTML, then render to PDF in your client (wkhtmltopdf, weasyprint, \
a separate headless Chromium pipeline, etc.)."
.to_string(),
)
}
_ => Err(format!("Unknown Page method: {}", method)),
}
}
@@ -333,4 +347,29 @@ mod tests {
.expect_err("unknown methods must surface as errors");
assert!(err.contains("Unknown Page method"));
}
#[tokio::test]
async fn print_to_pdf_returns_descriptive_unsupported_error() {
// Regression for #53: Page.printToPDF must be handled explicitly so
// Playwright clients receive a descriptive error rather than the
// generic "Unknown Page method" fallback.
let mut ctx = CdpContext::new();
let err = handle("printToPDF", &json!({}), &mut ctx, &None)
.await
.expect_err("printToPDF must error until a real renderer exists");
assert!(
!err.contains("Unknown Page method"),
"printToPDF must NOT fall through to the catch-all: {err}"
);
assert!(
err.contains("not supported by Obscura"),
"error must clearly state PDF is unsupported: {err}"
);
// Direct user to a workaround so the message is actionable.
assert!(
err.to_lowercase().contains("evaluate")
|| err.to_lowercase().contains("html"),
"error must point to a workaround: {err}"
);
}
}