Skip to main content

playwright_rs/protocol/
dialog.rs

1// Copyright 2026 Paul Adamson
2// Licensed under the Apache License, Version 2.0
3//
4// Dialog protocol object
5//
6// Represents a browser dialog (alert, confirm, prompt, or beforeunload)
7// dispatched via page.on('dialog') events.
8
9use crate::error::Result;
10use crate::server::channel_owner::{ChannelOwner, ChannelOwnerImpl, ParentOrConnection};
11use serde_json::{Value, json};
12use std::any::Any;
13use std::sync::Arc;
14
15/// Dialog represents a browser dialog (alert, confirm, prompt, or beforeunload).
16///
17/// Dialogs are dispatched via the page.on('dialog') event. Dialogs must be
18/// explicitly accepted or dismissed, otherwise the page will freeze waiting
19/// for the dialog to be handled.
20///
21/// See module-level documentation for usage examples.
22///
23/// See: <https://playwright.dev/docs/api/class-dialog>
24#[derive(Clone)]
25pub struct Dialog {
26    base: ChannelOwnerImpl,
27}
28
29impl Dialog {
30    /// Creates a new Dialog from protocol initialization
31    ///
32    /// This is called by the object factory when the server sends a `__create__` message
33    /// for a Dialog object.
34    pub fn new(
35        parent: Arc<dyn ChannelOwner>,
36        type_name: String,
37        guid: Arc<str>,
38        initializer: Value,
39    ) -> Result<Self> {
40        let base = ChannelOwnerImpl::new(
41            ParentOrConnection::Parent(parent),
42            type_name,
43            guid,
44            initializer,
45        );
46
47        Ok(Self { base })
48    }
49
50    /// Returns the dialog's type.
51    ///
52    /// Returns one of:
53    /// - "alert" - Simple notification dialog
54    /// - "confirm" - Yes/No confirmation dialog
55    /// - "prompt" - Text input dialog
56    /// - "beforeunload" - Page unload confirmation dialog
57    ///
58    /// See: <https://playwright.dev/docs/api/class-dialog#dialog-type>
59    pub fn type_(&self) -> &str {
60        self.initializer()
61            .get("type")
62            .and_then(|v| v.as_str())
63            .unwrap_or("")
64    }
65
66    /// Returns the message displayed in the dialog.
67    ///
68    /// See: <https://playwright.dev/docs/api/class-dialog#dialog-message>
69    pub fn message(&self) -> &str {
70        self.initializer()
71            .get("message")
72            .and_then(|v| v.as_str())
73            .unwrap_or("")
74    }
75
76    /// Returns the default value for prompt dialogs.
77    ///
78    /// For prompt dialogs, returns the default input value.
79    /// For other dialog types (alert, confirm, beforeunload), returns an empty string.
80    ///
81    /// See: <https://playwright.dev/docs/api/class-dialog#dialog-default-value>
82    pub fn default_value(&self) -> &str {
83        self.initializer()
84            .get("defaultValue")
85            .and_then(|v| v.as_str())
86            .unwrap_or("")
87    }
88
89    /// Returns the [`Page`](crate::protocol::Page) that owns this dialog.
90    ///
91    /// The dialog's parent in the protocol object hierarchy is the Page.
92    ///
93    /// See: <https://playwright.dev/docs/api/class-dialog#dialog-page>
94    pub fn page(&self) -> Option<crate::protocol::Page> {
95        let parent = self.parent()?;
96        parent
97            .as_any()
98            .downcast_ref::<crate::protocol::Page>()
99            .cloned()
100    }
101
102    /// Accepts the dialog.
103    ///
104    /// For prompt dialogs, optionally provides text input.
105    /// For other dialog types, the promptText parameter is ignored.
106    ///
107    /// # Arguments
108    ///
109    /// * `prompt_text` - Optional text to enter in a prompt dialog
110    ///
111    /// # Errors
112    ///
113    /// Returns error if:
114    /// - Dialog has already been accepted or dismissed
115    /// - Communication with browser process fails
116    ///
117    /// See: <https://playwright.dev/docs/api/class-dialog#dialog-accept>
118    pub async fn accept(&self, prompt_text: Option<&str>) -> Result<()> {
119        let params = if let Some(text) = prompt_text {
120            json!({ "promptText": text })
121        } else {
122            json!({})
123        };
124
125        self.channel().send_no_result("accept", params).await?;
126
127        Ok(())
128    }
129
130    /// Dismisses the dialog.
131    ///
132    /// For confirm dialogs, this is equivalent to clicking "Cancel".
133    /// For prompt dialogs, this is equivalent to clicking "Cancel".
134    ///
135    /// # Errors
136    ///
137    /// Returns error if:
138    /// - Dialog has already been accepted or dismissed
139    /// - Communication with browser process fails
140    ///
141    /// See: <https://playwright.dev/docs/api/class-dialog#dialog-dismiss>
142    pub async fn dismiss(&self) -> Result<()> {
143        self.channel().send_no_result("dismiss", json!({})).await?;
144
145        Ok(())
146    }
147}
148
149impl ChannelOwner for Dialog {
150    fn guid(&self) -> &str {
151        self.base.guid()
152    }
153
154    fn type_name(&self) -> &str {
155        self.base.type_name()
156    }
157
158    fn parent(&self) -> Option<Arc<dyn ChannelOwner>> {
159        self.base.parent()
160    }
161
162    fn connection(&self) -> Arc<dyn crate::server::connection::ConnectionLike> {
163        self.base.connection()
164    }
165
166    fn initializer(&self) -> &Value {
167        self.base.initializer()
168    }
169
170    fn channel(&self) -> &crate::server::channel::Channel {
171        self.base.channel()
172    }
173
174    fn dispose(&self, reason: crate::server::channel_owner::DisposeReason) {
175        self.base.dispose(reason)
176    }
177
178    fn adopt(&self, child: Arc<dyn ChannelOwner>) {
179        self.base.adopt(child)
180    }
181
182    fn add_child(&self, guid: Arc<str>, child: Arc<dyn ChannelOwner>) {
183        self.base.add_child(guid, child)
184    }
185
186    fn remove_child(&self, guid: &str) {
187        self.base.remove_child(guid)
188    }
189
190    fn on_event(&self, _method: &str, _params: Value) {
191        // Dialog doesn't emit events
192    }
193
194    fn was_collected(&self) -> bool {
195        self.base.was_collected()
196    }
197
198    fn as_any(&self) -> &dyn Any {
199        self
200    }
201}
202
203impl std::fmt::Debug for Dialog {
204    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
205        f.debug_struct("Dialog")
206            .field("guid", &self.guid())
207            .field("type", &self.type_())
208            .field("message", &self.message())
209            .field("default_value", &self.default_value())
210            .finish()
211    }
212}