SelectTag

Technology specific object identification, supported applications, web technologies, and 3rd party controls.
zshadow
Posts: 28
Joined: Sat Aug 30, 2014 5:17 pm

SelectTag

Post by zshadow » Tue Dec 09, 2014 4:55 pm

Hi,

I am trying to select an item in the Selectbox, i.e. a country in our example, which in turn open up the city selection box, this happens when I click on the country manually the city selection box appears, with the list of cities of the country. However when I try to do this with ranorex, see code below, I can select the country but the city drop down doe's not appear.

Code: Select all

SelectTag countrySelectTag = "/dom[@domain='localhost:8080']//select[#'selectedCountry']";
           
           countrySelectTag.EnsureVisible();
           countrySelectTag.Focus();
       
  countrySelectTag.Click(Location.CenterRight, 1000);
          
           foreach (OptionTag SingleOption in countrySelectTag.Find(".//option"))
           {
           
repo.SymptomDrivenDiagnostics.SelectedCountry.Click();
           
//  repo.GroupcallMessengerRoot.SendMessage.Recipients.SendTo.dd_SendTo.Click();
           
Report.Info("INFO", SingleOption.ToString());
           
if (SingleOption.ToString().Contains("UK")){
           
Report.Info("UK Found");
           
SingleOption.MoveTo();
           
SingleOption.Click(Location.Center, 1000);
           
//SingleOption.Select();
           
//SingleOption.Selected = true;
           
//countryOpt.PressKeys("{ENTER}");
           
SingleOption.Click();
           
break;
           
}
 }

User avatar
odklizec
Ranorex Guru
Ranorex Guru
Posts: 7469
Joined: Mon Aug 13, 2012 9:54 am
Location: Zilina, Slovakia

Re: SelectTag

Post by odklizec » Tue Dec 09, 2014 5:52 pm

Hi,

Have you tried InvokeAction instead of click? In many cases it's more reliable option than stimulating mouse click.
Read more about it here (scroll down to Invoke Action)...
http://www.ranorex.com/support/user-gui ... tions.html
Pavel Kudrys
Ranorex explorer at Descartes Systems

Please add these details to your questions:
  • Ranorex Snapshot. Learn how to create one >here<
  • Ranorex xPath of problematic element(s)
  • Ranorex version
  • OS version
  • HW configuration

krstcs
Posts: 2683
Joined: Tue Feb 07, 2012 4:14 pm
Location: Austin, Texas, USA

Re: SelectTag

Post by krstcs » Tue Dec 09, 2014 7:57 pm

Actually, it has been my experience that invoke action is not as reliable as click. The invoke action itself works fine, but the events are not fired in many cases, so the system under test does not realize the event was raised and doesn't act accordingly.


For the problem at hand, I would suggest that you use keyboard arrow keys (Up and Down) and enter instead. They are much more reliable than mouse clicks for select/option tags because of how each browser treats the select tag differently.

You could also try sending the key sequence for the country name to the select tag. In most situations this will automatically select the matching option tag. Then you can send the enter key stroke to launch the event.
Shortcuts usually aren't...

zshadow
Posts: 28
Joined: Sat Aug 30, 2014 5:17 pm

Re: SelectTag

Post by zshadow » Tue Dec 09, 2014 8:20 pm

Code: Select all

Hi krstcs,

I have tried using your suggested solution below, basically I want to click on the item where the desired index equals the selected index, I tried adding an extra else if to say if (desiredIndex == selectedIndex) then click, but I wasn't sure how you would click on the desired item ?

My function call:
SelectTag countrySelectTag = "/dom[@domain='localhost:8080']//select[#'selectedCountry']";

OptionTag optUK = "/dom[@domain='localhost:8080']//select[#'selectedCountry']/option[@value='UK:GB']";


SelectOption(countrySelectTag,optUK,30);

==============Your code=======================

public static void SelectOption(SelectTag selectTag, OptionTag optionTag, Duration dur) {
   List<string> options = GetOptionsText(selectTag);

   int desiredIndex = options.IndexOf(optionTag.TagValue);

   DoSelectAction(selectTag, desiredIndex, options, dur);
}

private static List<string> GetOptionsText(SelectTag selectTag) {
   List<string> options = new List<string>();

   foreach (OptionTag ot in selectTag.Find<OptionTag>(".//option")) {
      options.Add(ot.TagValue != null ? ot.TagValue : "");
   }

   return options;
}


private static void DoSelectAction(SelectTag selectTag, int desiredIndex, List<string> options, Duration dur) {
   int selectedIndex = 0;

   if (selectTag.TagValue != null) {
      List<OptionTag> optiontags = new List<OptionTag>(selectTag.Find<OptionTag>(".//optiontag[@TagValue='" + selectTag.TagValue + "']"));

      if (options.Count > 0) {
         OptionTag selectedOptionTag = optiontags[0];

         selectedIndex = options.IndexOf(selectedOptionTag.TagValue);
      }
   }
   
   Keyboard.PrepareFocus(selectTag);

   Duration oldKeyPressTime = Keyboard.DefaultKeyPressTime;
   Keyboard.DefaultKeyPressTime = 15;
   Duration keyPressDuration = dur;

   if (desiredIndex < selectedIndex) {
      for (int i = desiredIndex; i < selectedIndex; i++) {
         //up
         Report.Log(ReportLevel.Info, "Keyboard", "Key 'Up' Press with focus on '" + selectTag.GetPath() + "'.");
         Keyboard.Press(System.Windows.Forms.Keys.Up, Keyboard.DefaultScanCode, keyPressDuration, 1, true);//Keyboard.DefaultKeyPressTime, 1, true);
      }
   } else if (selectedIndex < desiredIndex) {
      for (int i = selectedIndex; i < desiredIndex; i++) {
         //down
         Report.Log(ReportLevel.Info, "Keyboard", "Key 'Down' Press with focus on '" + selectTag.GetPath() + "'.");
         Keyboard.Press(System.Windows.Forms.Keys.Down, Keyboard.DefaultScanCode, keyPressDuration, 1, true);//Keyboard.DefaultKeyPressTime, 1, true);
      }
   }

   Report.Log(ReportLevel.Info, "Keyboard", "Key 'Enter' Press with focus on '" + selectTag.GetPath() + "'.");
   Keyboard.Press(System.Windows.Forms.Keys.Enter, Keyboard.DefaultScanCode, keyPressDuration, 1, true);//Keyboard.DefaultKeyPressTime, 1, true);

   Keyboard.DefaultKeyPressTime = oldKeyPressTime;
}

krstcs
Posts: 2683
Joined: Tue Feb 07, 2012 4:14 pm
Location: Austin, Texas, USA

Re: SelectTag

Post by krstcs » Tue Dec 09, 2014 9:24 pm

There is a line near the bottom of the DoSelectAction() method that presses the enter key. This is probably where you would want to insert the click action instead of using enter, but enter does the same thing as clicking so I'm not sure what it gains you.

If you are using my methods, you shouldn't need to add anything to them unless you are wanting something different than "Use the arrow keys to find the given <optiontag> inside the given <selecttag> and press enter when it is found." That is what these methods do.

Maybe I'm misunderstanding what you are trying to do?
Shortcuts usually aren't...

zshadow
Posts: 28
Joined: Sat Aug 30, 2014 5:17 pm

Re: SelectTag

Post by zshadow » Tue Dec 09, 2014 9:46 pm

The problem is that it's not finding my option in the list it just seems to loop to the end, how would you check for the match of my option in the list, i.e. UK in the list of countries in the down ?

zshadow
Posts: 28
Joined: Sat Aug 30, 2014 5:17 pm

Re: SelectTag

Post by zshadow » Tue Dec 09, 2014 9:57 pm

Sorry forgot to add the code to check for match.

Code: Select all

if (desiredIndex < selectedIndex) {
      	for (int i = desiredIndex; i < selectedIndex; i++) {
      		//up
      		Report.Info("up");
      		Report.Log(ReportLevel.Info, "Keyboard", "Key 'Up' Press with focus on '" + selectTag.GetPath() + "'.");
      		Keyboard.Press(System.Windows.Forms.Keys.Up, Keyboard.DefaultScanCode, keyPressDuration, 1, true);//Keyboard.DefaultKeyPressTime, 1, true);
      	}
      } else if (selectedIndex < desiredIndex) {
      	for (int i = selectedIndex; i < desiredIndex; i++) {
      		Report.Info("down");
      		//down
      		Report.Log(ReportLevel.Info, "Keyboard", "Key 'Down' Press with focus on '" + selectTag.GetPath() + "'.");
      		Keyboard.Press(System.Windows.Forms.Keys.Down, Keyboard.DefaultScanCode, keyPressDuration, 1, true);//Keyboard.DefaultKeyPressTime, 1, true);
      	}
      } else if (selectedIndex == desiredIndex) {
      	Report.Info("match");
      	Report.Log(ReportLevel.Info, "Keyboard", "Key 'Down' Press with focus on '" + selectTag.GetPath() + "'.");
      	Keyboard.Press(System.Windows.Forms.Keys.Down, Keyboard.DefaultScanCode, keyPressDuration, 1, true);//Keyboard.DefaultKeyPressTime, 1, true);
      }

krstcs
Posts: 2683
Joined: Tue Feb 07, 2012 4:14 pm
Location: Austin, Texas, USA

Re: SelectTag

Post by krstcs » Tue Dec 09, 2014 10:03 pm

Change the last two lines of your == clause like below, so that it presses "Enter" instead of "Down".

Code: Select all

Report.Log(ReportLevel.Info, "Keyboard", "Key 'Enter' Press with focus on '" + selectTag.GetPath() + "'.");
Keyboard.Press(System.Windows.Forms.Keys.Enter, Keyboard.DefaultScanCode, keyPressDuration, 1, true);
Shortcuts usually aren't...

zshadow
Posts: 28
Joined: Sat Aug 30, 2014 5:17 pm

Re: SelectTag

Post by zshadow » Tue Dec 09, 2014 10:39 pm

I tried that but it only seems to select the first item in the list, the selected index is set to zero, I have attached an extract of the report below, thanks.

00:01.171 Info Validation Jump to itemEdit in Spy
Validating Exists on item 'SymptomDrivenDiagnostics.SelectedCountry'.
00:03.469 Info User {OptionTag:UK:GB}
00:03.530 Info User UK:GB
00:03.950 Info User 184
00:04.251 Info User 184
00:04.266 Info User 0
00:04.972 Info Keyboard Key 'Enter' Press with focus on '/dom[@domain='localhost:8080']//select[#'selectedCountry']'.
00:05.152 Info User down
00:05.527 Info Keyboard Key 'Down' Press with focus on '/dom[@domain='localhost:8080']//select[#'selectedCountry']'.
00:05.648 Info User down
.
.

Code: Select all

      
 public static void SelectOption(SelectTag selectTag, OptionTag optionTag, Duration dur) {
      	
      	List<string> options = GetOptionsText(selectTag);
      	Report.Info(optionTag.ToString());
      	int desiredIndex = options.IndexOf(optionTag.TagValue);
      	
      	Report.Info(optionTag.TagValue.ToString());
      	Report.Info(desiredIndex.ToString());
      	DoSelectAction(selectTag, desiredIndex, options, dur);
      	
       }

       private static List<string> GetOptionsText(SelectTag selectTag) {
       	List<string> options = new List<string>();

       	foreach (OptionTag ot in selectTag.Find<OptionTag>(".//option")) {
       		options.Add(ot.TagValue != null ? ot.TagValue : "");
       	}
       	return options;
       }

       private static void DoSelectAction(SelectTag selectTag, int desiredIndex, List<string> options, Duration dur) {
       	int selectedIndex = 0;

       	if (selectTag.TagValue != null) {
       		List<OptionTag> optiontags = new List<OptionTag>(selectTag.Find<OptionTag>(".//optiontag[@TagValue='" + selectTag.TagValue + "']"));

       		if (options.Count > 0) {
       			OptionTag selectedOptionTag = optiontags[0];

       			selectedIndex = options.IndexOf(selectedOptionTag.TagValue);
       		}
       	}
       	
       	Keyboard.PrepareFocus(selectTag);

       	Duration oldKeyPressTime = Keyboard.DefaultKeyPressTime;
       	Keyboard.DefaultKeyPressTime = 15;
       	Duration keyPressDuration = dur;
       	
    Report.Info(desiredIndex.ToString()); 	
	Report.Info(selectedIndex.ToString());
	
       	

       	Report.Log(ReportLevel.Info, "Keyboard", "Key 'Enter' Press with focus on '" + selectTag.GetPath() + "'.");
       	Keyboard.Press(System.Windows.Forms.Keys.Enter, Keyboard.DefaultScanCode, keyPressDuration, 1, true);//Keyboard.DefaultKeyPressTime, 1, true);

       	Keyboard.DefaultKeyPressTime = oldKeyPressTime;
      if (desiredIndex < selectedIndex) {
      	for (int i = desiredIndex; i < selectedIndex; i++) {
      		//up
      		Report.Info("up");
      		Report.Log(ReportLevel.Info, "Keyboard", "Key 'Up' Press with focus on '" + selectTag.GetPath() + "'.");
      		Keyboard.Press(System.Windows.Forms.Keys.Up, Keyboard.DefaultScanCode, keyPressDuration, 1, true);//Keyboard.DefaultKeyPressTime, 1, true);
      	}
      } else if (selectedIndex < desiredIndex) {
      	for (int i = selectedIndex; i < desiredIndex; i++) {
      		Report.Info("down");
      		//down
      		Report.Log(ReportLevel.Info, "Keyboard", "Key 'Down' Press with focus on '" + selectTag.GetPath() + "'.");
      		Keyboard.Press(System.Windows.Forms.Keys.Down, Keyboard.DefaultScanCode, keyPressDuration, 1, true);//Keyboard.DefaultKeyPressTime, 1, true);
      	}
      } else if (selectedIndex == desiredIndex) {
      	Report.Info("match");
      	Report.Log(ReportLevel.Info, "Keyboard", "Key 'Enter' Press with focus on '" + selectTag.GetPath() + "'.");
		Keyboard.Press(System.Windows.Forms.Keys.Enter, Keyboard.DefaultScanCode, keyPressDuration, 1, true);//DefaultKeyPressTime, 1, true);
      }
      }
      
      public static void RaiseSelectValueChangedEvent(Element element, string eventName)
        {
            var tag = element;
            bool usedTempId = false;
            try
            {
                var selectTag = GetAncestorSelectTag(element);

                var id = selectTag["id"] as string;
                if (string.IsNullOrEmpty(id))
                {
                    id = "_rxtmp" + new Random().Next(int.MaxValue);
                    selectTag["id"] = id;
                    usedTempId = true;
                }

                var script = @"var _rxtag = document.getElementById('" + id + @"');
                                   window.setTimeout(function(){
                                   var ev = document.createEvent('UIEvents'); " +
                                   (usedTempId ? "_rxtag.removeAttribute('id'); " : "") +
                                   @"ev.initUIEvent('" + eventName + @"', true, true, window, 1);
                                   _rxtag.dispatchEvent(ev);}, 1);";

                var host = GetScriptHost(tag);
                host.InvokeAction("executescript", script);
            }
            catch (Exception ex)
            {
                throw new RanorexException("Failed to raise event '" + eventName + "'. ", ex);
            }
        }

        static Element GetAncestorSelectTag(Element element)
        {
            var current = element.Parent;
            while (current != null)
            {
                if (("" + current["tagname"]) == "select")
                    return current;
                current = current.Parent;
            }
            return null;
        }

        static Element GetScriptHost(Element element)
        {
            var current = element.Parent;
            while (current != null)
            {
                foreach (var act in current.Actions)
                    if (act.Name == "executescript")
                        return current;
                current = current.Parent;
            }
            return null;
        }

krstcs
Posts: 2683
Joined: Tue Feb 07, 2012 4:14 pm
Location: Austin, Texas, USA

Re: SelectTag

Post by krstcs » Wed Dec 10, 2014 2:38 pm

OK, so if you look at the report segment you posted, you will notice that the "Enter" key is pressed BEFORE you start moving through the list.

I think there is something going on deeper in your code, probably at the spot where you are trying to find the index of the item in the option list. Try to find the issue there and see if that fixes it.

Also, I would take the == part out of your if, you don't need it. The methods I put together, if you are still using them, will do that for you when it finds the item. That == may be short-circuiting the logic. In other words, return the code back to the way I posted it and see if it works.
Shortcuts usually aren't...

zshadow
Posts: 28
Joined: Sat Aug 30, 2014 5:17 pm

Re: SelectTag

Post by zshadow » Wed Dec 10, 2014 8:23 pm

Hi krstcs,

I put your original code back but it seem to select random country evry time I run the code. I get the same result when I use my code based on your idea of keypresses shown below, it may be a bug in our application, or is it something I am doing wrong? For example for this run it says its found UK, but Turkmenistan is selcted in the dropdown.

Code: Select all

 SelectTag countrySelectTag = "/dom[@domain='localhost:8080']//select[#'selectedCountry']";
        OptionTag optUK = /dom[@domain='localhost:8080']//select[#'selectedCountry']/option[@value='UK:GB']";

 	countrySelectTag.EnsureVisible();
	countrySelectTag.Focus();
	countrySelectTag.Click(Location.CenterRight, 1000);
        
        foreach (OptionTag SingleOption in countrySelectTag.Find(".//option"))
     	{
       		Report.Info("INFO", SingleOption.ToString());
        	
        	if (SingleOption.ToString().Contains("UK"))
        	{
        		Report.Info("Uk Found");
        		SingleOption.Selected = true;
        		
        		Keyboard.Press(System.Windows.Forms.Keys.Enter, Keyboard.DefaultScanCode, 30, 1, true);
       			Report.Info("INFO", SingleOption.ToString());
       			break;
        	}
        	Keyboard.Press(System.Windows.Forms.Keys.Down, Keyboard.DefaultScanCode, 10, 1, true);
     		
        }
=====report output=====
00:14.550 Info INFO {OptionTag:Turkey:TR}
00:14.590 Info INFO {OptionTag:Turkmenistan:TM}
00:14.621 Info INFO {OptionTag:Turks and Caicos Islands:TC}
00:14.661 Info INFO {OptionTag:U.A.E:AE}
00:14.691 Info INFO {OptionTag:UK:GB}
00:14.721 Info User Uk Found
00:15.642 Info INFO {OptionTag:UK:GB}
00:15.762 Info User 184
00:16.003 Info Delay Jump to item
Waiting for 10s.

krstcs
Posts: 2683
Joined: Tue Feb 07, 2012 4:14 pm
Location: Austin, Texas, USA

Re: SelectTag

Post by krstcs » Wed Dec 10, 2014 8:40 pm

I'm not perfect, so there could be an issue with my code that I didn't anticipate.

However, I've been using it for about a year without problems, with different lists and different default selections in the lists. It should work with any select/option tag element in any browser.

Can you reproduce the behavior on you site manually? If you click the drop-down and then use the arrow keys and enter, does it work?
Shortcuts usually aren't...

zshadow
Posts: 28
Joined: Sat Aug 30, 2014 5:17 pm

Re: SelectTag

Post by zshadow » Wed Dec 10, 2014 9:47 pm

Hi,

I have tried it manually it works fine, would my code do the same as yours ?
I have attached list containing the list of countries, to see if you could reproduce the issue.

Your help is greatly appreciated,
You do not have the required permissions to view the files attached to this post.

zshadow
Posts: 28
Joined: Sat Aug 30, 2014 5:17 pm

Re: SelectTag

Post by zshadow » Thu Dec 11, 2014 7:29 pm

Hi,

The code below seems to be doing what I wanted, thanks for all your help.

Code: Select all

         SelectTag countrySelectTag = "/dom[@domain='localhost:8080']//select[#'selectedCountry']";
        OptionTag optUK = /dom[@domain='localhost:8080']//select[#'selectedCountry']/option[@value='UK:GB']";
   
 	countrySelectTag.EnsureVisible();
	countrySelectTag.Focus();
	countrySelectTag.Click(Location.CenterRight, 1000);
        
        foreach (OptionTag SingleOption in countrySelectTag.Find(".//option"))
     	{
       		if (SingleOption.ToString().Contains("UK"))
        	{
               		SingleOption.MoveTo();
        		Delay.Seconds(1);
        		Keyboard.Press(System.Windows.Forms.Keys.Enter, Keyboard.DefaultScanCode, 30, 1, true);
        		
      			break;
        	}
        	Keyboard.Press(System.Windows.Forms.Keys.Down, Keyboard.DefaultScanCode, 10, 1, true);
        }

CookieMonster
Certified Professional
Certified Professional
Posts: 74
Joined: Mon Aug 14, 2006 7:17 pm
Location: CH

Re: SelectTag

Post by CookieMonster » Fri Dec 12, 2014 9:41 am

Hi all,
I also struggled in past with the automation of the select tag on website. Here is a part of my code. May it helps, to solve your problems. With this approach it also invokes the event javascript.

Regards
Dan

Code: Select all

SelectTag ranorexSelectTag = element.Element;				
IList<OptionTag> options = ranorexSelectTag.Options;
IList<OptionTag> optionTagList = options.Where(tempOption => tempOption.InnerText != null && tempOption.InnerText.Equals(innerTextValue,StringComparison.OrdinalIgnoreCase)).ToList();
				
if(optionTagList.Count == 1)
{
	OptionTag singleOptionTag = optionTagList.ElementAt(0);
	singleOptionTag.Selected = true;
	ranorexSelectTag.TagValue = singleOptionTag.Value;
}