4

On Safari browser I need to select an Option from the dropdown but the funny thing is that it works for all the browsers except for Safari on Mac OS. I am using Safari 10.0.3 with selenium webdriver version 3.3.0

I have written the code in C#. Refer the code below -

    IWebDriver driver;
    driver = new SafariDriver();
    List<string> handles = driver.WindowHandles.ToList<string>();
    driver.SwitchTo().Window(handles.First());
    driver.Navigate().GoToUrl("https://myip/MyPage.aspx");
    SelectElement element = new SelectElement(driver.FindElement(By.Id("securityQuestion")));
    int totalOptions = element.Options.Count;
    Random rnd = new Random();
    int rndValue = rnd.Next(1, totalOptions);
    element.SelectByIndex(rndValue); // This is not working for Safari browser      
    driver.FindElement(By.Id("securityAnswer")).SendKeys("test");
    driver.FindElement(By.Id("ctl00_Content_btnNext")).Click();
    driver.Close();

No error is thrown just that it doesnt select any value from the dropdown.

  • Is it a timing issue? Maybe Safari on Mac is slow. Put a breakpoint on the `SelectElement` line then step through it. Does it work? If so, you need to add some waits. – JeffC Apr 11 '17 at 13:06
  • if it doesn't work after everything you do, how about using sendKeys to select by visible text. – Gaurang Shah Apr 13 '17 at 13:44
  • @GaurangShah tried that but then the next lines of code are not executed – FullStackdev Apr 14 '17 at 05:54
  • @RohitN. what do you mean by not executed? did it skip?? did it throw any exception? – Gaurang Shah Apr 14 '17 at 06:52
  • @Gaurang no exception just skips the code execution but this only happens on safari browser works fine for the rest infact even chrome browser on Mac OS runs this with no problem – FullStackdev Apr 15 '17 at 07:08
  • do you know how to maximize the Safari browser size via selenium web driver – FullStackdev Apr 15 '17 at 07:15

2 Answers2

0

This is a safaridriver bug. The fix is in WebKit, and being tracked here: https://bugs.webkit.org/show_bug.cgi?id=174710

As a workaround, you can modify which options of a select are selected using JavaScript and the DOM API.

Brian Burg
  • 679
  • 4
  • 10
0

Try this sample here for JS workaround - implemented as C# extension. This code works on Safari (tested on version 10.1+).

This is not the complete code, just a snippet to make it simple. You can extend it to support any functionality you like.

using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Internal;
using OpenQA.Selenium.Support.UI;

namespace Gravity.Plugins.Actions.Extensions
{
    public static class SelectExtensions
    {
        /// <summary>
        /// Select the option by the index, as determined by the "index" attribute of the
        /// element.
        /// </summary>
        /// <param name="selectElement">This <see cref="SelectElement"/>.</param>
        /// <param name="index">The value of the index attribute of the option to be selected.</param>
        public static void JsSelectByIndex(this SelectElement selectElement, int index)
        {
            // constants
            var script = $"options[{index}].selected = true;";

            // web element to act on
            var onElement = selectElement.WrappedElement;
            var onDriver = (IWrapsDriver)onElement;

            // execute
            ((IJavaScriptExecutor)onDriver).ExecuteScript(script, onElement);
        }

        /// <summary>
        /// Select all options by the text displayed.
        /// </summary>
        /// <param name="selectElement">This <see cref="SelectElement"/>.</param>
        /// <param name="text">The text of the option to be selected.</param>
        public static void JsSelectByText(this SelectElement selectElement, string text)
        {
            // constants
            var script =
                "var options = arguments[0].getElementsByTagName('option');" +
                "" +
                "for(i = 0; i < options.length; i++) {" +
                $"   if(options[i].innerText !== '{text}') {{" +
                "       continue;" +
                "    }" +
                "    options[i].selected = true;" +
                "    break;" +
                "}";

            // web element to act on
            var onElement = selectElement.WrappedElement;
            var onDriver = (IWrapsDriver)onElement;

            // execute
            ((IJavaScriptExecutor)onDriver).ExecuteScript(script, onElement);
        }

        /// <summary>
        /// Select an option by the value.
        /// </summary>
        /// <param name="selectElement"></param>
        /// <param name="value">The value of the option to be selected.</param>
        public static void JsSelectByValue(this SelectElement selectElement, string value)
        {
            // constants
            var script =
                "var options = arguments[0].getElementsByTagName('option');" +
                "" +
                "for(i = 0; i < options.length; i++) {" +
                $"   if(options[i].getAttribute('value') !== '{value}') {{" +
                "       continue;" +
                "    }" +
                "    options[i].selected = true;" +
                "    break;" +
                "}";

            // web element to act on
            var onElement = selectElement.WrappedElement;
            var onDriver = (IWrapsDriver)onElement;

            // execute
            ((IJavaScriptExecutor)onDriver).ExecuteScript(script, onElement);
        }
    }

    // Usage sample
    public class MySeleniumClass
    {
        public void DoAutomation()
        {
            var driver = new ChromeDriver()
            {
                Url = "https://gravitymvctestapplication.azurewebsites.net/UiControls"
            };
            var element = driver.FindElement(By.Id("select_menu"));
            var selectElement = new SelectElement(element);
            selectElement.JsSelectByIndex(1);
            selectElement.JsSelectByText("Two");
            selectElement.JsSelectByValue("3");
        }
    }
}
Gravity API
  • 393
  • 1
  • 7