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