| // <copyright file="TargetLocator.cs" company="Selenium Committers"> |
| // Licensed to the Software Freedom Conservancy (SFC) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The SFC licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| // </copyright> |
| |
| using OpenQA.Selenium.Internal; |
| using System; |
| using System.Collections.Generic; |
| using System.Collections.ObjectModel; |
| using System.Text.RegularExpressions; |
| |
| namespace OpenQA.Selenium; |
| |
| /// <summary> |
| /// Provides a mechanism for finding elements on the page with locators. |
| /// </summary> |
| internal sealed class TargetLocator : ITargetLocator |
| { |
| private readonly WebDriver driver; |
| |
| /// <summary> |
| /// Initializes a new instance of the <see cref="TargetLocator"/> class |
| /// </summary> |
| /// <param name="driver">The driver that is currently in use</param> |
| /// <exception cref="ArgumentNullException">If <paramref name="driver"/> is <see langword="null"/>.</exception> |
| public TargetLocator(WebDriver driver) |
| { |
| this.driver = driver ?? throw new ArgumentNullException(nameof(driver)); |
| } |
| |
| /// <summary> |
| /// Move to a different frame using its index |
| /// </summary> |
| /// <param name="frameIndex">The index of the </param> |
| /// <returns>A WebDriver instance that is currently in use</returns> |
| public IWebDriver Frame(int frameIndex) |
| { |
| Dictionary<string, object> parameters = new Dictionary<string, object>(); |
| parameters.Add("id", frameIndex); |
| this.driver.Execute(DriverCommand.SwitchToFrame, parameters); |
| return this.driver; |
| } |
| |
| /// <summary> |
| /// Move to different frame using its name |
| /// </summary> |
| /// <param name="frameName">name of the frame</param> |
| /// <returns>A WebDriver instance that is currently in use</returns> |
| /// <exception cref="ArgumentNullException">If <paramref name="frameName"/> is <see langword="null"/>.</exception> |
| public IWebDriver Frame(string frameName) |
| { |
| if (frameName == null) |
| { |
| throw new ArgumentNullException(nameof(frameName), "Frame name cannot be null"); |
| } |
| |
| string name = Regex.Replace(frameName, @"(['""\\#.:;,!?+<>=~*^$|%&@`{}\-/\[\]\(\)])", @"\$1"); |
| ReadOnlyCollection<IWebElement> frameElements = this.driver.FindElements(By.CssSelector("frame[name='" + name + "'],iframe[name='" + name + "']")); |
| if (frameElements.Count == 0) |
| { |
| frameElements = this.driver.FindElements(By.CssSelector("frame#" + name + ",iframe#" + name)); |
| if (frameElements.Count == 0) |
| { |
| throw new NoSuchFrameException("No frame element found with name or id " + frameName); |
| } |
| } |
| |
| return this.Frame(frameElements[0]); |
| } |
| |
| /// <summary> |
| /// Move to a frame element. |
| /// </summary> |
| /// <param name="frameElement">a previously found FRAME or IFRAME element.</param> |
| /// <returns>A WebDriver instance that is currently in use.</returns> |
| /// <exception cref="ArgumentNullException">If <paramref name="frameElement"/> is <see langword="null"/>.</exception> |
| /// <exception cref="ArgumentException">If <paramref name="frameElement"/> cannot be converted to an <see cref="IWebDriverObjectReference"/>.</exception> |
| public IWebDriver Frame(IWebElement frameElement) |
| { |
| if (frameElement == null) |
| { |
| throw new ArgumentNullException(nameof(frameElement), "Frame element cannot be null"); |
| } |
| |
| IWebDriverObjectReference? elementReference = frameElement as IWebDriverObjectReference; |
| if (elementReference == null) |
| { |
| if (frameElement is IWrapsElement elementWrapper) |
| { |
| elementReference = elementWrapper.WrappedElement as IWebDriverObjectReference; |
| } |
| } |
| |
| if (elementReference == null) |
| { |
| throw new ArgumentException($"{nameof(frameElement)} cannot be converted to {nameof(IWebDriverObjectReference)}", nameof(frameElement)); |
| } |
| |
| Dictionary<string, object> elementDictionary = elementReference.ToDictionary(); |
| |
| Dictionary<string, object> parameters = new Dictionary<string, object>(); |
| parameters.Add("id", elementDictionary); |
| this.driver.Execute(DriverCommand.SwitchToFrame, parameters); |
| return this.driver; |
| } |
| |
| /// <summary> |
| /// Select the parent frame of the currently selected frame. |
| /// </summary> |
| /// <returns>An <see cref="IWebDriver"/> instance focused on the specified frame.</returns> |
| public IWebDriver ParentFrame() |
| { |
| Dictionary<string, object> parameters = new Dictionary<string, object>(); |
| this.driver.Execute(DriverCommand.SwitchToParentFrame, parameters); |
| return this.driver; |
| } |
| |
| /// <summary> |
| /// Change to the Window by passing in the name |
| /// </summary> |
| /// <param name="windowHandleOrName">Window handle or name of the window that you wish to move to</param> |
| /// <returns>A WebDriver instance that is currently in use</returns> |
| /// <exception cref="ArgumentNullException">If <paramref name="windowHandleOrName"/> is <see langword="null"/>.</exception> |
| public IWebDriver Window(string windowHandleOrName) |
| { |
| if (windowHandleOrName is null) |
| { |
| throw new ArgumentNullException(nameof(windowHandleOrName)); |
| } |
| |
| Dictionary<string, object> parameters = new Dictionary<string, object>(); |
| parameters.Add("handle", windowHandleOrName); |
| try |
| { |
| this.driver.Execute(DriverCommand.SwitchToWindow, parameters); |
| return this.driver; |
| } |
| catch (NoSuchWindowException) |
| { |
| // simulate search by name |
| string? original = null; |
| try |
| { |
| original = this.driver.CurrentWindowHandle; |
| } |
| catch (NoSuchWindowException) |
| { |
| } |
| |
| foreach (string handle in this.driver.WindowHandles) |
| { |
| this.Window(handle); |
| if (windowHandleOrName == this.driver.ExecuteScript("return window.name")!.ToString()) |
| { |
| return this.driver; // found by name |
| } |
| } |
| |
| if (original != null) |
| { |
| this.Window(original); |
| } |
| |
| throw; |
| } |
| } |
| |
| /// <summary> |
| /// Creates a new browser window and switches the focus for future commands |
| /// of this driver to the new window. |
| /// </summary> |
| /// <param name="typeHint">The type of new browser window to be created. |
| /// The created window is not guaranteed to be of the requested type; if |
| /// the driver does not support the requested type, a new browser window |
| /// will be created of whatever type the driver does support.</param> |
| /// <returns>An <see cref="IWebDriver"/> instance focused on the new browser.</returns> |
| public IWebDriver NewWindow(WindowType typeHint) |
| { |
| Dictionary<string, object> parameters = new Dictionary<string, object>(); |
| parameters.Add("type", typeHint.ToString().ToLowerInvariant()); |
| |
| Response response = this.driver.Execute(DriverCommand.NewWindow, parameters); |
| |
| Dictionary<string, object> result = (Dictionary<string, object>)response.Value!; |
| string newWindowHandle = result["handle"].ToString()!; |
| this.Window(newWindowHandle); |
| |
| return this.driver; |
| } |
| |
| /// <summary> |
| /// Change the active frame to the default |
| /// </summary> |
| /// <returns>Element of the default</returns> |
| public IWebDriver DefaultContent() |
| { |
| Dictionary<string, object?> parameters = new Dictionary<string, object?>(); |
| parameters.Add("id", null); |
| this.driver.Execute(DriverCommand.SwitchToFrame, parameters); |
| return this.driver; |
| } |
| |
| /// <summary> |
| /// Finds the active element on the page and returns it |
| /// </summary> |
| /// <returns>Element that is active</returns> |
| public IWebElement ActiveElement() |
| { |
| Response response = this.driver.Execute(DriverCommand.GetActiveElement, null); |
| return this.driver.GetElementFromResponse(response)!; |
| } |
| |
| /// <summary> |
| /// Switches to the currently active modal dialog for this particular driver instance. |
| /// </summary> |
| /// <returns>A handle to the dialog.</returns> |
| public IAlert Alert() |
| { |
| // N.B. We only execute the GetAlertText command to be able to throw |
| // a NoAlertPresentException if there is no alert found. |
| this.driver.Execute(DriverCommand.GetAlertText, null); |
| return new Alert(this.driver); |
| } |
| } |