Skip to main content

playwright_rs/protocol/
screenshot.rs

1// Screenshot types and options
2//
3// Provides configuration for page and element screenshots, matching Playwright's API.
4
5use serde::Serialize;
6
7/// Screenshot image format
8///
9/// # Example
10///
11/// ```ignore
12/// use playwright_rs::protocol::ScreenshotType;
13///
14/// let screenshot_type = ScreenshotType::Jpeg;
15/// ```
16#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
17#[serde(rename_all = "lowercase")]
18pub enum ScreenshotType {
19    /// PNG format (lossless, supports transparency)
20    Png,
21    /// JPEG format (lossy compression, smaller file size)
22    Jpeg,
23}
24
25/// Clip region for screenshot
26///
27/// Specifies a rectangular region to capture.
28///
29/// # Example
30///
31/// ```ignore
32/// use playwright_rs::protocol::ScreenshotClip;
33///
34/// let clip = ScreenshotClip {
35///     x: 10.0,
36///     y: 20.0,
37///     width: 300.0,
38///     height: 200.0,
39/// };
40/// ```
41#[derive(Debug, Clone, Copy, PartialEq, Serialize)]
42pub struct ScreenshotClip {
43    /// X coordinate of clip region origin
44    pub x: f64,
45    /// Y coordinate of clip region origin
46    pub y: f64,
47    /// Width of clip region
48    pub width: f64,
49    /// Height of clip region
50    pub height: f64,
51}
52
53/// Screenshot options
54///
55/// Configuration options for page and element screenshots.
56///
57/// Use the builder pattern to construct options:
58///
59/// # Example
60///
61/// ```ignore
62/// use playwright_rs::protocol::{ScreenshotOptions, ScreenshotType, ScreenshotClip};
63///
64/// // JPEG with quality
65/// let options = ScreenshotOptions::builder()
66///     .screenshot_type(ScreenshotType::Jpeg)
67///     .quality(80)
68///     .build();
69///
70/// // Full page screenshot
71/// let options = ScreenshotOptions::builder()
72///     .full_page(true)
73///     .build();
74///
75/// // Clip region
76/// let clip = ScreenshotClip {
77///     x: 10.0,
78///     y: 10.0,
79///     width: 200.0,
80///     height: 100.0,
81/// };
82/// let options = ScreenshotOptions::builder()
83///     .clip(clip)
84///     .build();
85/// ```
86///
87/// See: <https://playwright.dev/docs/api/class-page#page-screenshot>
88#[derive(Debug, Clone, Default)]
89pub struct ScreenshotOptions {
90    /// Image format (png or jpeg)
91    pub screenshot_type: Option<ScreenshotType>,
92    /// JPEG quality (0-100), only applies to jpeg format
93    pub quality: Option<u8>,
94    /// Capture full scrollable page
95    pub full_page: Option<bool>,
96    /// Clip region to capture
97    pub clip: Option<ScreenshotClip>,
98    /// Hide default white background (PNG only)
99    pub omit_background: Option<bool>,
100    /// Screenshot timeout in milliseconds
101    pub timeout: Option<f64>,
102}
103
104impl ScreenshotOptions {
105    /// Create a new builder for ScreenshotOptions
106    pub fn builder() -> ScreenshotOptionsBuilder {
107        ScreenshotOptionsBuilder::default()
108    }
109
110    /// Convert options to JSON value for protocol
111    pub(crate) fn to_json(&self) -> serde_json::Value {
112        let mut json = serde_json::json!({});
113
114        if let Some(screenshot_type) = &self.screenshot_type {
115            json["type"] = serde_json::to_value(screenshot_type).unwrap();
116        }
117
118        if let Some(quality) = self.quality {
119            json["quality"] = serde_json::json!(quality);
120        }
121
122        if let Some(full_page) = self.full_page {
123            json["fullPage"] = serde_json::json!(full_page);
124        }
125
126        if let Some(clip) = &self.clip {
127            json["clip"] = serde_json::to_value(clip).unwrap();
128        }
129
130        if let Some(omit_background) = self.omit_background {
131            json["omitBackground"] = serde_json::json!(omit_background);
132        }
133
134        // Timeout is required in Playwright 1.56.1+
135        if let Some(timeout) = self.timeout {
136            json["timeout"] = serde_json::json!(timeout);
137        } else {
138            json["timeout"] = serde_json::json!(crate::DEFAULT_TIMEOUT_MS);
139        }
140
141        json
142    }
143}
144
145/// Builder for ScreenshotOptions
146///
147/// Provides a fluent API for constructing screenshot options.
148#[derive(Debug, Clone, Default)]
149pub struct ScreenshotOptionsBuilder {
150    screenshot_type: Option<ScreenshotType>,
151    quality: Option<u8>,
152    full_page: Option<bool>,
153    clip: Option<ScreenshotClip>,
154    omit_background: Option<bool>,
155    timeout: Option<f64>,
156}
157
158impl ScreenshotOptionsBuilder {
159    /// Set the screenshot format (png or jpeg)
160    pub fn screenshot_type(mut self, screenshot_type: ScreenshotType) -> Self {
161        self.screenshot_type = Some(screenshot_type);
162        self
163    }
164
165    /// Set JPEG quality (0-100)
166    ///
167    /// Only applies when screenshot_type is Jpeg.
168    pub fn quality(mut self, quality: u8) -> Self {
169        self.quality = Some(quality);
170        self
171    }
172
173    /// Capture full scrollable page beyond viewport
174    pub fn full_page(mut self, full_page: bool) -> Self {
175        self.full_page = Some(full_page);
176        self
177    }
178
179    /// Set clip region to capture
180    pub fn clip(mut self, clip: ScreenshotClip) -> Self {
181        self.clip = Some(clip);
182        self
183    }
184
185    /// Hide default white background (creates transparent PNG)
186    pub fn omit_background(mut self, omit_background: bool) -> Self {
187        self.omit_background = Some(omit_background);
188        self
189    }
190
191    /// Set screenshot timeout in milliseconds
192    pub fn timeout(mut self, timeout: f64) -> Self {
193        self.timeout = Some(timeout);
194        self
195    }
196
197    /// Build the ScreenshotOptions
198    pub fn build(self) -> ScreenshotOptions {
199        ScreenshotOptions {
200            screenshot_type: self.screenshot_type,
201            quality: self.quality,
202            full_page: self.full_page,
203            clip: self.clip,
204            omit_background: self.omit_background,
205            timeout: self.timeout,
206        }
207    }
208}
209
210#[cfg(test)]
211mod tests {
212    use super::*;
213
214    #[test]
215    fn test_screenshot_type_serialization() {
216        assert_eq!(
217            serde_json::to_string(&ScreenshotType::Png).unwrap(),
218            "\"png\""
219        );
220        assert_eq!(
221            serde_json::to_string(&ScreenshotType::Jpeg).unwrap(),
222            "\"jpeg\""
223        );
224    }
225
226    #[test]
227    fn test_builder_jpeg_with_quality() {
228        let options = ScreenshotOptions::builder()
229            .screenshot_type(ScreenshotType::Jpeg)
230            .quality(80)
231            .build();
232
233        let json = options.to_json();
234        assert_eq!(json["type"], "jpeg");
235        assert_eq!(json["quality"], 80);
236    }
237
238    #[test]
239    fn test_builder_full_page() {
240        let options = ScreenshotOptions::builder().full_page(true).build();
241
242        let json = options.to_json();
243        assert_eq!(json["fullPage"], true);
244    }
245
246    #[test]
247    fn test_builder_clip() {
248        let clip = ScreenshotClip {
249            x: 10.0,
250            y: 20.0,
251            width: 300.0,
252            height: 200.0,
253        };
254        let options = ScreenshotOptions::builder().clip(clip).build();
255
256        let json = options.to_json();
257        assert_eq!(json["clip"]["x"], 10.0);
258        assert_eq!(json["clip"]["y"], 20.0);
259        assert_eq!(json["clip"]["width"], 300.0);
260        assert_eq!(json["clip"]["height"], 200.0);
261    }
262
263    #[test]
264    fn test_builder_omit_background() {
265        let options = ScreenshotOptions::builder().omit_background(true).build();
266
267        let json = options.to_json();
268        assert_eq!(json["omitBackground"], true);
269    }
270
271    #[test]
272    fn test_builder_multiple_options() {
273        let options = ScreenshotOptions::builder()
274            .screenshot_type(ScreenshotType::Jpeg)
275            .quality(90)
276            .full_page(true)
277            .timeout(5000.0)
278            .build();
279
280        let json = options.to_json();
281        assert_eq!(json["type"], "jpeg");
282        assert_eq!(json["quality"], 90);
283        assert_eq!(json["fullPage"], true);
284        assert_eq!(json["timeout"], 5000.0);
285    }
286}