Selenium find elements within specified element - c#

I'm running into trouble with Selenium when it comes to XING's groups. The solution I was using for more than two years to this very date does not work anymore; they must have changed something about their HTML.
The main problem is that a certain select element doesn't open (when trying to open it by clicking it) and I hence cannot access the options to "click" or to select. I see a small border embracing the drop down, as if it was clicked but didn't function in second place.
Now that I've spent quite some time on elaborating on the error, I'm quite sure this is because the same (meaning the same attributes, ...) drop down exists on the same page at another point (to sort/filter posts shown by groups). However, I want to select the (sub) forum that a new post is submitted to, and this does not work.
I tried many, many, many different things of which none worked, obviously. I'm unable to list all of my attempts here since it's simply too much and partly too long ago. Some of what I tried:
select the drop down by various methods (CSS Selector, class name, XPath, ...)
access the desired option of the drop down directly (by CSS Selector, class name, XPath; even tried to collect arrays of all elements and select the right one by index, didn't work either)
access the desired option of the drop down directly by JavaScript and 'click' it by JS
And now SO is my hope. I thought of a way to select -exactly- this drop down (rather than the other one described) by child elements and so on (this is the reason for the title of this question).
This is the HTML:
<div class="comm-navigation forum-select is-open" id="new-post-forum-select" data-is-open="true">
<a href="#" class="comm-navigation-trigger">
<span class="comm-navigation-name" title="Select forum">Select forum</span>
<i class="comm-navigation-icn-closed foundation-icon-shape-arrow-down"></i>
<i class="comm-navigation-icn-open foundation-icon-shape-arrow-up"></i>
</a>
<ul class="comm-navigation-dropdown hidden" style="width: 519px; display: block;">
<li class="comm-navigation-group forum-list">
<ul>
<li class="comm-navigation-item">
<a href="/communities/forums/100941274" class="comm-navigation-forum" data-forum-id="100941274" data-forum-name="Members" title="Members">
Members
</a>
</li>
<li class="comm-navigation-item">
<a href="/communities/forums/100941276" class="comm-navigation-forum" data-forum-id="100941276" data-forum-name="Q & A" title="Q & A">
Q & A
</a>
</li>
<li class="comm-navigation-item">
<a href="/communities/forums/100941275" class="comm-navigation-forum" data-forum-id="100941275" data-forum-name="Feedback" title="Feedback">
Feedback
</a>
</li>
</ul>
</li>
</ul>
<input type="hidden" name="post[forum_id]" id="post_forum_id" value="">
</div>
I thought of perhaps going from comm-navigation forum-select is-open (which is the same when it's still closed without is-open) to the inner elements to get the right Chrome element and then click the option.
Also, I found that there's a hidden field:
<input type="hidden" name="post[forum_id]" id="post_forum_id" value="">
Which is exactly related to my problem; value is empty as long as nothing's selected, as soon as selected, the forum's id is inserted into the value. This I could imagine if there wasn't any JS that prevents you from submitting the form without having actually selected the sub forums by drop down.
Looking forward to great solutions.

If I understood the question, then first you need to click on the span inside the first link (class=comm-navigation-trigger) with the text "Select Forum". This makes the "ul" below to be visible. Now you need to click the desired "li" inside this list. If so then read on.
Find the span with the css selector - "div[id='new-post-forum-select'] > a[class='comm-navigation-trigger'] > span". Click on this element.
Wait for the list to become visible. Use the css selector - "div[id='new-post-forum-select'] > ul[class*='comm-navigation-dropdown']". Use the ElementIsVisible ExpectedCondition. Though you may or not require this step, added this as a check.
Find the link with the required value - "div[id='new-post-forum-select'] > ul[class*='comm-navigation-dropdown'] a[class='comm-navigation-forum'][data-forum-name='Q & A']". Click on this.

Related

Razor page select component to acquire selectedItem and route multiple values

ASP .Net Core 6.0 Razor page contains a select component that I want to use for filtering the data presented on the page. The code behind processes for both get and post. Most of the get operation provides the list for for the Razor page filter selection. Two pieces of information need to be routed back to the getter. Everything tried so far will only send back one value or the other, not both. The button only sends the currentFilter. The onchange doesn't fire so the link never gets a valid #selectedFilter.
Section that provides the drop-down list:
<form method="get">
<div class="form-actions no-color">
<p>
Find by Department:
<select name="currentFilter" asp-for="#Model.DepartmentFilter" asp-items="#Model.DepartmentNameSL"
onchange="OnChangeMethod()">
<option value="">-- Department Filter --</option>
</select>
<input type="submit" value="Search" class="btn btn-primary" asp-route-id="#Model.Student.ID" />
<a asp-page="./Enroller" asp-route-id="#Model.Student.ID" asp-route-currentFilter="#selectedFilter" >Try Update List</a>
</p>
</div>
</form>
It is the code section on the page that brings me here. Documentation for Razor pages does not seem to support what my IDE will use. #{ ... } will allow code development. All example code uses #code { ... }, but the keyword 'code' is not recognized. In fact many keywords are not recognized; i.e. 'private', 'public', 'override' for example. Plus the code section has to come before the HTML or 'selectedFilter' is not recognized.
#{
string selectedFilter = string.Empty
//void OnChangeMethod(EventArgs e) => selectedFilter = e.ToString();
void OnchangeMethod()
{
selectedFilter = "selection made";
}
}
It is like I'm missing a package or documentation has not kept up with .Net 6, or .Net 6 dropped much of what used to be in prior versions or I am in some episode of the Twilight Zone and don't know it.
The HTML will get the value set in the code but it will not change it nor call the OnChangeMethod. It seems to me that the lines between Razor and Blazor are blurred and perhaps my difficulty lies there. So finding documentation that puts information in the right order would be helpful.
As it turns out the solution was very simple. What needed to take place was to include the target identifier "id" with the selected filter. The standard button for submit would then include both.
"{id:int?}"
route template was added after the #Page directive. Can't believe I missed it. But it would be helpful to know how to make the event calls work.

How to sendkeys to a <p> tag through C# and Selenium

i want to sendkeys "description" within a textarea. I have tried all the possible ways but does not work.
HTML of the element :
<div class="ta-scroll-window ng-scope ta-text ta-editor form-control" ng-hide="showHtml">
<div class="popover fade bottom" style="max-width: none; width: 305px;">
<div class="arrow"></div>
<div class="popover-content"></div>
</div>
<div class="ta-resizer-handle-overlay">
<div class="ta-resizer-handle-background"></div>
<div class="ta-resizer-handle-corner ta-resizer-handle-corner-tl"></div>
<div class="ta-resizer-handle-corner ta-resizer-handle-corner-tr"></div>
<div class="ta-resizer-handle-corner ta-resizer-handle-corner-bl"></div>
<div class="ta-resizer-handle-corner ta-resizer-handle-corner-br"></div>
<div class="ta-resizer-handle-info"></div>
</div>
<div id="taTextElement737852736512107" contenteditable="true" ta-bind="ta-bind" ng-model="html" ta-keep-styles="true" class="ng-pristine ng-valid ta-bind ng-empty ng-touched" an-form-object-name="Açıklama" name="Açıklama">
<p>
<br>
</p>
</div>
</div>
Code trial :
Dim action2 = New Actions(driver)
Dim cekbul2 = driver.FindElement(By.XPath("//*#id=""taHtmlElement737852736512107""]"))
cekbul2.SendKeys("Açıklama")
Console.Write("textarea send description")
or
Dim cekbul2 = driver.FindElement(By.XPath("//textarea[#class='ng-pristine ng-untouched ng-valid ng-scope ta-bind ta-html ta-editor form-control ng-empty ng-hide' and #id='taHtmlElement737852736512107']"))
The error is :
"no such element: Unable to locate element does not work" give error
Your html does not have a text area input field inside it.
When you use an xPath that says
'//textarea' this means that you are looking for an element that has tags of <textarea> </textarea>
It looks like your html is actually div's that are styled up to look like text areas.
That is why your second attempt will never work - because you are looking for a textarea where none exists.
Typically, in the situation where a div is styled up to work like a text area or textbox, you will find that the div has a backing input behind it.
These must be located between the
<form> and </form> tags in the html - otherwise the server would never be able to receive the data. (Html 5 provides new ways of working with this - but that is another story)
Can you examine your full html, and see if you can find the actual text area objects or the input type objects that end up containing the text content.
Type some dummy text, and use an html inspector tool within chrome or firefox to look for your dummy text.
If however, the post is completed by javascript - you may find that the javascript does not use inputs or text areas for containing the text and instead posts it external to any form elements. This is common with richtext emulators such as forum post pages.
If that is the case- you may need to experiment and find the appropriate html element that you need to send keys to in order for the content to work.
Also - could you try
Dim cekbul2 = driver.FindElement(By.XPath("//div[#id='taHtmlElement737852736512107']"))
I couldnt help but notice it had an xPath syntax error - you had no starting [ square bracket ] - also, in programming it is sometimes considered lazy a bad practice to wildcard / work with dynamics. I recommend always using the tag type for your xpaths, as opposed to '//*'
Worse case scenario, I would say that you could probably get around this by using Javascript execution. Eg: Directly setting the text, instead of 'sending the key strokes'.
However, this does not emulate human behavior - but it may be a necessary evil depending on your situation.
To send text to the <p> tag you have to use the ExecuteScript() method from IJavaScriptExecutor Interface and you can use the following code block :
((IJavaScriptExecutor)driver).ExecuteScript("document.getElementsByTagName("p")[0].innerHTML="Hasan Sarıkaya";");
I want to highlight some points here
Most probably your locator which you are using is not correct.
There are three way which I know to enter text using selenium
1)Use driver.findElement(yourLoator).sendKeys("Stringvalue");
2)You can use action class to send keys
3)You can use javascript executor to change innerHtml code
Personally ill not prefer the third solution, because we are testers I believe changing dom attribute is a good practice
Hope this will give you some help. please Let me know in case any query.

How to target multiple "li" with same classname

Hi everyone the function of my code is to take a users shoe size preference and then click on an element on the page based on their size.
I will do this by taking numerical input from the user and store it in a value, then searching for the element that matches the size they have entered.
Here is the html code from the website I am using:
<div class="form product__form product__form--size product__form--last js-select-size-mapper">
<ul class = "product-size">
<li class = "js-size-value ">
8
</li>
<li class = "js-size-value ">
9
</li>
<li class = "js-size-value ">
9.5
</li>
<li class = "js-size-value ">
10
</li>
<li class = "js-size-value ">
10.5
</li>
</ul>
</div>
I always get some sort of error regarding how the element is not clickable. The weird part is sometimes the IWebElement declaration is verified (I mean there is no error in declaring it), sometimes there is an error when I try to click.
If you need to see a better example of code, hop over to the website here.
For example, when I run this code:
var element = driver.FindElement(By.XPath("//li[contains(#class,'js-size-value ')][contains(text(),size)]"));
element.Click();
*note, I have previously declared a variable called "size", and that's what I'm referring to when it says "(text(),size)]"
I get the error:
Additional information: Unexpected error. Element is not clickable at point (825.1500244140625, 45.69999694824219). Other element would receive the click: div class="header__wrapper">
I don't know how to approach this, and need some light shed on it in general. I have searched through stackoverflow for answers, and haven't found any posts that pertain to exactlty what I am trying to accomplish, or are vague and hard to understand.
Please take caution when answering that I am new to Selenium and C# in general, so if you could add a bit of detail in your answers and not assume I know what you are talking about, that would be great.
You accidentally set size as text instead of as variable. This means selenium will search a list item with the text 'size', which doesn't exist, instead of for example size 9.5,
var element = driver.FindElement(By.XPath("//li[contains(#class,'js-size-value')][contains(text()," + size + ")]"));

Hand coded C# Coded UI Test , Control/Object location issue

I have a dropdown menu sub-item ("logout") that I want to select. I need to hover over the menu first to make the logout link appear. There's a lot of div's surrounding it; the spy tells me it's an HTMLPANE, but there's no built-in support for HtmlPanes in VS code as far as I can see. (I try typing it in and intellisense doesnt recognize it, not from htmlcontrols namespace)
Just before trying to describe this main menu object, I'm defining the variable as an HtmlDiv. I've even tried to identify it generically by referring to it as an HtmlControl.
Here's the "view source" of the dropdown menu in question. I need to get to the "Logout" link which is the bottom option in the dropdown.
<li class="my-account-top" aria-haspopup="true" aria-owns="doormat-profile">
<span class="icon-profile menu"></span>
<span class="profile-header tablet-hide"> Profile</span>
<div class="ma-menu-items left">
<a id="nav-my-account-profile" href="/my-account/profile/">Edit Profile</a>
<a id="nav-my-account-profile-view-card" href="/my-account/profile/view-card/">View ID Card</a>
<a id="nav-my-account-profile-request-card" href="/my-account/profile/request-card/">Request ID Card</a>
<a id="nav-my-account-profile-logoff" href="/my-account/profile/logoff/">Log Out</a>
</div>
</li>
</ul>
I'm not familiar with the `mouse.hover function. Can you please show me an actual example, preferably from this code? I'm not even sure if this is a way to identify it because from what I observed by recording the hover, browser resizing changes the coordinates.
I don't know if I am obliged to give a coordinate to mouse.hover, or can I just specify the name of the object control? (i.e. mouse.hover(varnameformainmenu))

Access A Link Inside A NAV Element

I'm trying to access an HTML element using Selenium (C#) but I'm currently having trouble. The element is located within a structure like this:
<nav>
<ul class="menu"> id="menu">
<li id="ignore"> </li>
<li id="test_tab">
Update
</li>
</ul>
</nav>
I need to access and click "Update". What is the best method to access this link? I have tried .findElement(By.Id("test_tab")) and similar without success. Once it has been selected I then plan to call .click().
Thanks in advance.
Very simple! First you need to determine what element is receiving the click. in this case, the <a> will be. Just use a simple css selector.
driver.FindElement(By.CssSelector("ul#menu li#test_tab > a[title='Update']")).Click();
You are trying to select the li element and hence not possible to click the link. For selecting 'a' there could be multiple options.
1)
.findElement(By.LinkText("Update")).click()
2)
IWebElement update = driver.findElement(By.Id("test_tab"));
update = update.findElement(By.TagName("a"));
update.click();
3) You could use xpaths to directly select 'a'.

Categories

Resources