thirtyfour/switch_to.rs
1use crate::common::command::Command;
2use crate::error::WebDriverErrorInfo;
3use crate::session::handle::SessionHandle;
4use crate::WindowHandle;
5use crate::{
6 error::{WebDriverError, WebDriverResult},
7 Alert, WebElement,
8};
9use std::sync::Arc;
10
11/// Struct for switching between frames/windows/alerts.
12#[derive(Debug)]
13pub struct SwitchTo {
14 handle: Arc<SessionHandle>,
15}
16
17impl SwitchTo {
18 /// Create a new SwitchTo struct. This is typically created internally
19 /// via a call to `WebDriver::switch_to()`.
20 pub fn new(handle: Arc<SessionHandle>) -> Self {
21 Self {
22 handle,
23 }
24 }
25
26 /// Get the active element for this session.
27 #[deprecated(
28 since = "0.30.0",
29 note = "This method has been moved to WebDriver::active_element()"
30 )]
31 pub async fn active_element(self) -> WebDriverResult<WebElement> {
32 self.handle.active_element().await
33 }
34
35 /// Switch to the specified alert.
36 #[deprecated(
37 since = "0.30.0",
38 note = "This method has been deprecated. See the `Alert` module for new method names"
39 )]
40 pub fn alert(self) -> Alert {
41 Alert::new(self.handle)
42 }
43
44 /// Switch to the default frame.
45 #[deprecated(
46 since = "0.30.0",
47 note = "This method has been moved to WebDriver::enter_default_frame()"
48 )]
49 pub async fn default_content(self) -> WebDriverResult<()> {
50 self.handle.enter_default_frame().await
51 }
52
53 /// Switch to the frame specified at the index.
54 #[deprecated(since = "0.30.0", note = "This method has been moved to WebDriver::enter_frame()")]
55 pub async fn frame_number(self, frame_number: u16) -> WebDriverResult<()> {
56 self.handle.enter_frame(frame_number).await
57 }
58
59 /// Switch to the frame contained within the element.
60 #[deprecated(
61 since = "0.30.0",
62 note = "This method has been moved to WebElement::enter_frame()"
63 )]
64 pub async fn frame_element(self, frame_element: &WebElement) -> WebDriverResult<()> {
65 frame_element.clone().enter_frame().await
66 }
67
68 /// Switch to the parent of the frame the client is currently contained within.
69 #[deprecated(
70 since = "0.30.0",
71 note = "This method has been moved to WebDriver::enter_parent_frame()"
72 )]
73 pub async fn parent_frame(self) -> WebDriverResult<()> {
74 self.handle.enter_parent_frame().await?;
75 Ok(())
76 }
77
78 /// Create a new window.
79 #[deprecated(since = "0.30.0", note = "This method has been moved to WebDriver::new_window()")]
80 pub async fn new_window(self) -> WebDriverResult<WindowHandle> {
81 self.handle.new_window().await
82 }
83
84 /// Create a new tab.
85 #[deprecated(since = "0.30.0", note = "This method has been moved to WebDriver::new_tab()")]
86 pub async fn new_tab(self) -> WebDriverResult<WindowHandle> {
87 self.handle.new_tab().await
88 }
89
90 /// Switch to the specified window.
91 #[deprecated(
92 since = "0.30.0",
93 note = "This method has been moved to WebDriver::switch_to_window()"
94 )]
95 pub async fn window(self, handle: WindowHandle) -> WebDriverResult<()> {
96 self.handle.switch_to_window(handle).await
97 }
98
99 /// Switch to the specified named window.
100 #[deprecated(
101 since = "0.30.0",
102 note = "This method has been moved to WebDriver::switch_to_named_window()"
103 )]
104 pub async fn window_name(self, name: &str) -> WebDriverResult<()> {
105 let original_handle = self.handle.window().await?;
106 let handles = self.handle.windows().await?;
107 for handle in handles {
108 self.handle.switch_to_window(handle).await?;
109 let ret = self.handle.execute(r#"return window.name;"#, Vec::new()).await?;
110 let current_name: String = ret.convert()?;
111 if current_name == name {
112 return Ok(());
113 }
114 }
115
116 self.handle.switch_to_window(original_handle).await?;
117 Err(WebDriverError::NoSuchWindow(WebDriverErrorInfo::new(format!(
118 "unable to find named window: {name}"
119 ))))
120 }
121}
122
123impl SessionHandle {
124 /// Return the element with focus, or the `<body>` element if nothing has focus.
125 ///
126 /// # Example:
127 /// ```no_run
128 /// # use thirtyfour::prelude::*;
129 /// # use thirtyfour::support::block_on;
130 /// #
131 /// # fn main() -> WebDriverResult<()> {
132 /// # block_on(async {
133 /// # let caps = DesiredCapabilities::chrome();
134 /// # let driver = WebDriver::new("http://localhost:4444", caps).await?;
135 /// // If no element has focus, active_element() will return the body tag.
136 /// let active_elem = driver.active_element().await?;
137 /// assert_eq!(active_elem.tag_name().await?, "body");
138 ///
139 /// // Now let's manually focus an element and try active_element() again.
140 /// let elem = driver.find(By::Id("my-element-id")).await?;
141 /// elem.focus().await?;
142 ///
143 /// // And fetch the active element again.
144 /// let active_elem = driver.active_element().await?;
145 /// assert_eq!(active_elem.element_id(), elem.element_id());
146 /// # driver.quit().await?;
147 /// # Ok(())
148 /// # })
149 /// # }
150 /// ```
151 pub async fn active_element(self: &Arc<SessionHandle>) -> WebDriverResult<WebElement> {
152 let r = self.cmd(Command::GetActiveElement).await?;
153 r.element(self.clone())
154 }
155
156 /// Switch to the default frame.
157 ///
158 /// # Example:
159 /// ```no_run
160 /// # use thirtyfour::prelude::*;
161 /// # use thirtyfour::support::block_on;
162 /// #
163 /// # fn main() -> WebDriverResult<()> {
164 /// # block_on(async {
165 /// # let caps = DesiredCapabilities::chrome();
166 /// # let driver = WebDriver::new("http://localhost:4444", caps).await?;
167 /// // Enter the first iframe.
168 /// driver.enter_frame(0).await?;
169 /// // We are now inside the iframe.
170 /// driver.find(By::Id("button1")).await?;
171 /// driver.enter_default_frame().await?;
172 /// // We are now back in the original window.
173 /// # driver.quit().await?;
174 /// # Ok(())
175 /// # })
176 /// # }
177 /// ```
178 pub async fn enter_default_frame(&self) -> WebDriverResult<()> {
179 self.cmd(Command::SwitchToFrameDefault).await?;
180 Ok(())
181 }
182
183 /// Switch to an iframe by index. The first iframe on the page has index 0.
184 ///
185 /// # Example:
186 /// ```no_run
187 /// # use thirtyfour::prelude::*;
188 /// # use thirtyfour::support::block_on;
189 /// #
190 /// # fn main() -> WebDriverResult<()> {
191 /// # block_on(async {
192 /// # let caps = DesiredCapabilities::chrome();
193 /// # let driver = WebDriver::new("http://localhost:4444", caps).await?;
194 /// // Enter the first iframe.
195 /// driver.enter_frame(0).await?;
196 /// // We can now search for elements within the iframe.
197 /// let elem = driver.find(By::Id("button1")).await?;
198 /// elem.click().await?;
199 /// # driver.quit().await?;
200 /// # Ok(())
201 /// # })
202 /// # }
203 /// ```
204 pub async fn enter_frame(&self, frame_number: u16) -> WebDriverResult<()> {
205 self.cmd(Command::SwitchToFrameNumber(frame_number)).await?;
206 Ok(())
207 }
208
209 /// Switch to the parent frame.
210 ///
211 /// # Example:
212 /// ```no_run
213 /// # use thirtyfour::prelude::*;
214 /// # use thirtyfour::support::block_on;
215 /// #
216 /// # fn main() -> WebDriverResult<()> {
217 /// # block_on(async {
218 /// # let caps = DesiredCapabilities::chrome();
219 /// # let driver = WebDriver::new("http://localhost:4444", caps).await?;
220 /// // Find the iframe element and enter the iframe.
221 /// let elem_iframe = driver.find(By::Id("iframeid1")).await?;
222 /// elem_iframe.enter_frame().await?;
223 /// // We can now search for elements within the iframe.
224 /// let elem = driver.find(By::Id("button1")).await?;
225 /// elem.click().await?;
226 /// // Now switch back to the parent frame.
227 /// driver.enter_parent_frame().await?;
228 /// // We are now back in the parent document.
229 /// # driver.quit().await?;
230 /// # Ok(())
231 /// # })
232 /// # }
233 /// ```
234 pub async fn enter_parent_frame(&self) -> WebDriverResult<()> {
235 self.cmd(Command::SwitchToParentFrame).await?;
236 Ok(())
237 }
238
239 /// Switch to the specified window.
240 ///
241 /// # Example:
242 /// ```no_run
243 /// # use thirtyfour::prelude::*;
244 /// # use thirtyfour::support::block_on;
245 /// #
246 /// # fn main() -> WebDriverResult<()> {
247 /// # block_on(async {
248 /// # let caps = DesiredCapabilities::chrome();
249 /// # let driver = WebDriver::new("http://localhost:4444", caps).await?;
250 /// // Open a new tab.
251 /// driver.new_tab().await?;
252 ///
253 /// // Get window handles and switch to the new tab.
254 /// let handles = driver.windows().await?;
255 /// driver.switch_to_window(handles[1].clone()).await?;
256 ///
257 /// // We are now controlling the new tab.
258 /// driver.goto("https://www.rust-lang.org").await?;
259 /// # driver.quit().await?;
260 /// # Ok(())
261 /// # })
262 /// # }
263 /// ```
264 pub async fn switch_to_window(&self, handle: WindowHandle) -> WebDriverResult<()> {
265 self.cmd(Command::SwitchToWindow(handle)).await?;
266 Ok(())
267 }
268
269 /// Switch to the window with the specified name. This uses the `window.name` property.
270 /// You can set a window name via `WebDriver::set_window_name("someName").await?`.
271 ///
272 /// # Example:
273 /// ```no_run
274 /// # use thirtyfour::prelude::*;
275 /// # use thirtyfour::support::block_on;
276 /// #
277 /// # fn main() -> WebDriverResult<()> {
278 /// # block_on(async {
279 /// # let caps = DesiredCapabilities::chrome();
280 /// # let driver = WebDriver::new("http://localhost:4444", caps).await?;
281 /// // Set main window name so we can switch back easily.
282 /// driver.set_window_name("mywindow").await?;
283 ///
284 /// // Open a new tab.
285 /// driver.new_tab().await?;
286 ///
287 /// // Get window handles and switch to the new tab.
288 /// let handles = driver.windows().await?;
289 /// driver.switch_to_window(handles[1].clone()).await?;
290 ///
291 /// // We are now controlling the new tab.
292 /// assert_eq!(driver.title().await?, "");
293 /// driver.switch_to_named_window("mywindow").await?;
294 ///
295 /// // We are now back in the original tab.
296 /// # driver.quit().await?;
297 /// # Ok(())
298 /// # })
299 /// # }
300 /// ```
301 pub async fn switch_to_named_window(
302 self: &Arc<SessionHandle>,
303 name: &str,
304 ) -> WebDriverResult<()> {
305 let original_handle = self.window().await?;
306 let handles = self.windows().await?;
307 for handle in handles {
308 self.switch_to_window(handle).await?;
309 let ret = self.execute(r#"return window.name;"#, Vec::new()).await?;
310 let current_name: String = ret.convert()?;
311 if current_name == name {
312 return Ok(());
313 }
314 }
315
316 self.switch_to_window(original_handle).await?;
317 Err(WebDriverError::NoSuchWindow(WebDriverErrorInfo::new(format!(
318 "unable to find named window: {name}"
319 ))))
320 }
321
322 /// Switch to a new window.
323 ///
324 /// # Example:
325 /// ```no_run
326 /// # use thirtyfour::prelude::*;
327 /// # use thirtyfour::support::block_on;
328 /// #
329 /// # fn main() -> WebDriverResult<()> {
330 /// # block_on(async {
331 /// # let caps = DesiredCapabilities::chrome();
332 /// # let driver = WebDriver::new("http://localhost:4444", caps).await?;
333 /// // Open a new window.
334 /// let handle = driver.new_window().await?;
335 /// # driver.quit().await?;
336 /// # Ok(())
337 /// # })
338 /// # }
339 /// ```
340 pub async fn new_window(&self) -> WebDriverResult<WindowHandle> {
341 self.cmd(Command::NewWindow).await?.value()
342 }
343
344 /// Switch to a new tab.
345 ///
346 /// # Example:
347 /// ```no_run
348 /// # use thirtyfour::prelude::*;
349 /// # use thirtyfour::support::block_on;
350 /// #
351 /// # fn main() -> WebDriverResult<()> {
352 /// # block_on(async {
353 /// # let caps = DesiredCapabilities::chrome();
354 /// # let driver = WebDriver::new("http://localhost:4444", caps).await?;
355 /// // Open a new tab in the current window.
356 /// let handle = driver.new_tab().await?;
357 /// # driver.quit().await?;
358 /// # Ok(())
359 /// # })
360 /// # }
361 /// ```
362 pub async fn new_tab(&self) -> WebDriverResult<WindowHandle> {
363 self.cmd(Command::NewTab).await?.value()
364 }
365}