Skip to main content

rustant_core/browser/
snapshot.rs

1//! Page snapshot types for capturing browser page state.
2
3use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5
6/// The mode used for capturing a page snapshot.
7#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
8#[serde(rename_all = "snake_case")]
9pub enum SnapshotMode {
10    /// Raw HTML source.
11    Html,
12    /// Accessibility / ARIA tree representation.
13    AriaTree,
14    /// Extracted text content.
15    Text,
16    /// Base64-encoded screenshot PNG.
17    Screenshot,
18}
19
20impl std::fmt::Display for SnapshotMode {
21    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22        match self {
23            SnapshotMode::Html => write!(f, "html"),
24            SnapshotMode::AriaTree => write!(f, "aria_tree"),
25            SnapshotMode::Text => write!(f, "text"),
26            SnapshotMode::Screenshot => write!(f, "screenshot"),
27        }
28    }
29}
30
31/// A captured snapshot of a browser page.
32#[derive(Debug, Clone, Serialize, Deserialize)]
33pub struct PageSnapshot {
34    /// Current URL of the page.
35    pub url: String,
36    /// Page title.
37    pub title: String,
38    /// The snapshot mode used.
39    pub mode: SnapshotMode,
40    /// The captured content (HTML, text, ARIA tree, or base64 screenshot).
41    pub content: String,
42    /// When the snapshot was taken.
43    pub timestamp: DateTime<Utc>,
44}
45
46impl PageSnapshot {
47    /// Create a new page snapshot.
48    pub fn new(
49        url: impl Into<String>,
50        title: impl Into<String>,
51        mode: SnapshotMode,
52        content: impl Into<String>,
53    ) -> Self {
54        Self {
55            url: url.into(),
56            title: title.into(),
57            mode,
58            content: content.into(),
59            timestamp: Utc::now(),
60        }
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    use super::*;
67
68    #[test]
69    fn test_snapshot_mode_serde_roundtrip() {
70        let modes = vec![
71            SnapshotMode::Html,
72            SnapshotMode::AriaTree,
73            SnapshotMode::Text,
74            SnapshotMode::Screenshot,
75        ];
76        for mode in &modes {
77            let json = serde_json::to_string(mode).unwrap();
78            let deserialized: SnapshotMode = serde_json::from_str(&json).unwrap();
79            assert_eq!(*mode, deserialized);
80        }
81    }
82
83    #[test]
84    fn test_snapshot_mode_display() {
85        assert_eq!(SnapshotMode::Html.to_string(), "html");
86        assert_eq!(SnapshotMode::AriaTree.to_string(), "aria_tree");
87        assert_eq!(SnapshotMode::Text.to_string(), "text");
88        assert_eq!(SnapshotMode::Screenshot.to_string(), "screenshot");
89    }
90
91    #[test]
92    fn test_page_snapshot_creation() {
93        let snapshot = PageSnapshot::new(
94            "https://example.com",
95            "Example",
96            SnapshotMode::Html,
97            "<html><body>Hello</body></html>",
98        );
99        assert_eq!(snapshot.url, "https://example.com");
100        assert_eq!(snapshot.title, "Example");
101        assert_eq!(snapshot.mode, SnapshotMode::Html);
102        assert_eq!(snapshot.content, "<html><body>Hello</body></html>");
103    }
104
105    #[test]
106    fn test_page_snapshot_serde() {
107        let snapshot = PageSnapshot::new(
108            "https://docs.rs",
109            "Docs.rs",
110            SnapshotMode::Text,
111            "Welcome to docs.rs",
112        );
113        let json = serde_json::to_string(&snapshot).unwrap();
114        let deserialized: PageSnapshot = serde_json::from_str(&json).unwrap();
115        assert_eq!(deserialized.url, snapshot.url);
116        assert_eq!(deserialized.title, snapshot.title);
117        assert_eq!(deserialized.mode, snapshot.mode);
118        assert_eq!(deserialized.content, snapshot.content);
119    }
120
121    #[test]
122    fn test_snapshot_mode_json_values() {
123        assert_eq!(
124            serde_json::to_string(&SnapshotMode::Html).unwrap(),
125            "\"html\""
126        );
127        assert_eq!(
128            serde_json::to_string(&SnapshotMode::AriaTree).unwrap(),
129            "\"aria_tree\""
130        );
131        assert_eq!(
132            serde_json::to_string(&SnapshotMode::Screenshot).unwrap(),
133            "\"screenshot\""
134        );
135    }
136}