Skip to main content

playwright_rs/protocol/
file_payload.rs

1// FilePayload protocol type
2//
3// Represents a file to be uploaded with explicit name, MIME type, and buffer.
4//
5// See: https://playwright.dev/docs/api/class-locator#locator-set-input-files
6
7/// FilePayload represents a file for advanced file uploads.
8///
9/// Allows explicit control over filename, MIME type, and file contents
10/// when uploading files to input elements.
11///
12/// # Example
13///
14/// ```ignore
15/// # use playwright_rs::protocol::FilePayload;
16/// let file = FilePayload::builder()
17///     .name("document.pdf".to_string())
18///     .mime_type("application/pdf".to_string())
19///     .buffer(vec![/* PDF bytes */])
20///     .build();
21/// ```
22///
23/// See: <https://playwright.dev/docs/api/class-locator#locator-set-input-files>
24#[derive(Debug, Clone)]
25pub struct FilePayload {
26    /// File name
27    pub name: String,
28    /// MIME type
29    pub mime_type: String,
30    /// File contents as bytes
31    pub buffer: Vec<u8>,
32}
33
34use crate::error::Result;
35use std::fs;
36use std::path::Path;
37
38impl FilePayload {
39    /// Creates a new builder for FilePayload
40    pub fn builder() -> FilePayloadBuilder {
41        FilePayloadBuilder::default()
42    }
43
44    /// Creates a FilePayload from a file path.
45    ///
46    /// Automatically detects the MIME type based on the file extension.
47    /// Reads the file into memory.
48    pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Self> {
49        let path = path.as_ref();
50        let name = path
51            .file_name()
52            .ok_or_else(|| crate::Error::InvalidPath(format!("Path {:?} has no filename", path)))?
53            .to_string_lossy()
54            .into_owned();
55
56        let mime_type = crate::protocol::mime::from_path(path).to_string();
57        let buffer = fs::read(path)?;
58
59        Ok(Self {
60            name,
61            mime_type,
62            buffer,
63        })
64    }
65
66    /// Creates a FilePayload from a file path with an explicit MIME type.
67    pub fn from_file<P: AsRef<Path>>(path: P, mime_type: &str) -> Result<Self> {
68        let path = path.as_ref();
69        let name = path
70            .file_name()
71            .ok_or_else(|| crate::Error::InvalidPath(format!("Path {:?} has no filename", path)))?
72            .to_string_lossy()
73            .into_owned();
74
75        let buffer = fs::read(path)?;
76
77        Ok(Self {
78            name,
79            mime_type: mime_type.to_string(),
80            buffer,
81        })
82    }
83}
84
85/// Builder for FilePayload
86#[derive(Debug, Clone, Default)]
87pub struct FilePayloadBuilder {
88    name: Option<String>,
89    mime_type: Option<String>,
90    buffer: Option<Vec<u8>>,
91}
92
93impl FilePayloadBuilder {
94    /// Sets the file name
95    pub fn name(mut self, name: String) -> Self {
96        self.name = Some(name);
97        self
98    }
99
100    /// Sets the MIME type
101    pub fn mime_type(mut self, mime_type: String) -> Self {
102        self.mime_type = Some(mime_type);
103        self
104    }
105
106    /// Sets the file buffer (contents as bytes)
107    pub fn buffer(mut self, buffer: Vec<u8>) -> Self {
108        self.buffer = Some(buffer);
109        self
110    }
111
112    /// Builds the FilePayload
113    ///
114    /// # Panics
115    ///
116    /// Panics if any required field (name, mime_type, buffer) is missing
117    pub fn build(self) -> FilePayload {
118        FilePayload {
119            name: self.name.expect("name is required for FilePayload"),
120            mime_type: self
121                .mime_type
122                .expect("mime_type is required for FilePayload"),
123            buffer: self.buffer.expect("buffer is required for FilePayload"),
124        }
125    }
126}