Skip to content

Commit 7ccf9a6

Browse files
feat(client): implement printing pages as PDF (#285)
1 parent 1e4d29b commit 7ccf9a6

File tree

6 files changed

+530
-6
lines changed

6 files changed

+530
-6
lines changed

src/client.rs

+22-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ use crate::error;
66
use crate::session::{Cmd, Session, Task};
77
use crate::wait::Wait;
88
use crate::wd::{
9-
Capabilities, Locator, NewSessionResponse, NewWindowType, TimeoutConfiguration,
10-
WebDriverStatus, WindowHandle,
9+
Capabilities, Locator, NewSessionResponse, NewWindowType, PrintConfiguration,
10+
TimeoutConfiguration, WebDriverStatus, WindowHandle,
1111
};
1212
use base64::Engine;
1313
use http::Method;
@@ -1096,6 +1096,26 @@ impl Client {
10961096
Err(error::CmdError::NotW3C(src))
10971097
}
10981098
}
1099+
1100+
/// Get a PDF of the current page.
1101+
///
1102+
/// See [18.1 Print Page](https://www.w3.org/TR/webdriver2/#print-page) of the
1103+
/// WebDriver2 standard.
1104+
pub async fn print(
1105+
&self,
1106+
print_configuration: PrintConfiguration,
1107+
) -> Result<Vec<u8>, error::CmdError> {
1108+
let src = self
1109+
.issue(WebDriverCommand::Print(print_configuration.into_params()))
1110+
.await?;
1111+
if let Some(src) = src.as_str() {
1112+
base64::engine::general_purpose::STANDARD
1113+
.decode(src)
1114+
.map_err(error::CmdError::PdfDecodeError)
1115+
} else {
1116+
Err(error::CmdError::NotW3C(src))
1117+
}
1118+
}
10991119
}
11001120

11011121
/// Operations that wait for a change on the page.

src/error.rs

+38-2
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ impl fmt::Display for NewSessionError {
7272

7373
/// An error occurred while executing some browser action.
7474
#[derive(Debug)]
75+
#[non_exhaustive]
7576
pub enum CmdError {
7677
/// A standard WebDriver error occurred.
7778
///
@@ -118,6 +119,9 @@ pub enum CmdError {
118119
/// Could not decode a base64 image
119120
ImageDecodeError(base64::DecodeError),
120121

122+
/// Could not decode a base64 PDF.
123+
PdfDecodeError(base64::DecodeError),
124+
121125
/// Timeout of a wait condition.
122126
///
123127
/// When waiting for a for a condition using [`Client::wait`](crate::Client::wait), any of the
@@ -190,6 +194,7 @@ impl Error for CmdError {
190194
CmdError::NotW3C(..) => "webdriver returned non-conforming response",
191195
CmdError::InvalidArgument(..) => "invalid argument provided",
192196
CmdError::ImageDecodeError(..) => "error decoding image",
197+
CmdError::PdfDecodeError(..) => "error decoding PDF",
193198
CmdError::WaitTimeout => "timeout waiting on condition",
194199
}
195200
}
@@ -202,7 +207,7 @@ impl Error for CmdError {
202207
CmdError::FailedC(ref e) => Some(e),
203208
CmdError::Lost(ref e) => Some(e),
204209
CmdError::Json(ref e) => Some(e),
205-
CmdError::ImageDecodeError(ref e) => Some(e),
210+
CmdError::ImageDecodeError(ref e) | CmdError::PdfDecodeError(ref e) => Some(e),
206211
CmdError::NotJson(_)
207212
| CmdError::NotW3C(_)
208213
| CmdError::InvalidArgument(..)
@@ -224,7 +229,9 @@ impl fmt::Display for CmdError {
224229
CmdError::NotJson(ref e) => write!(f, "{}", e),
225230
CmdError::Json(ref e) => write!(f, "{}", e),
226231
CmdError::NotW3C(ref e) => write!(f, "{:?}", e),
227-
CmdError::ImageDecodeError(ref e) => write!(f, "{:?}", e),
232+
CmdError::ImageDecodeError(ref e) | CmdError::PdfDecodeError(ref e) => {
233+
write!(f, "{:?}", e)
234+
}
228235
CmdError::InvalidArgument(ref arg, ref msg) => {
229236
write!(f, "Invalid argument `{}`: {}", arg, msg)
230237
}
@@ -285,6 +292,35 @@ impl From<InvalidWindowHandle> for CmdError {
285292
}
286293
}
287294

295+
/// Error of attempting to build an invalid [`PrintConfiguration`](crate::wd::PrintConfiguration).
296+
#[derive(Debug, PartialEq, Eq)]
297+
#[non_exhaustive]
298+
pub enum PrintConfigurationError {
299+
/// One or more dimensions of the page margins/size are negative.
300+
NegativeDimensions,
301+
/// One or more dimensions of the page margins/size are NaN or infinite.
302+
NonFiniteDimensions,
303+
/// The margins overflow the page size (e.g. margins.left + margins.right >= page.width).
304+
DimensionsOverflow,
305+
/// Eighter one of print height or width are smaller than the [`PrintSize::MIN`](crate::wd::PrintSize::MIN).
306+
PrintSizeTooSmall,
307+
}
308+
309+
impl fmt::Display for PrintConfigurationError {
310+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
311+
f.write_str(match self {
312+
Self::NegativeDimensions => {
313+
"one or more dimensions of the page (margins and/or size) are negative"
314+
}
315+
Self::NonFiniteDimensions => {
316+
"one or more dimensions of the page (margins and/or size) are NaN or infinite"
317+
}
318+
Self::DimensionsOverflow => "the margins overflow the page size",
319+
Self::PrintSizeTooSmall => "the print size is too small",
320+
})
321+
}
322+
}
323+
288324
/// The error code returned from the WebDriver.
289325
#[derive(Debug, PartialEq, Eq, Hash)]
290326
#[non_exhaustive]

src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -275,3 +275,5 @@ pub mod wait;
275275
pub mod wd;
276276
#[doc(inline)]
277277
pub use wd::Locator;
278+
279+
mod print;

0 commit comments

Comments
 (0)