Using Selenium / C#
I have an automated test case where a user logs in (jonpark2), once the user has done so their username is stored in the text of a span class, I need to select this element and then verify an assert on it.
I have the below to try and select this:
public static void Userloggedin()
{
var userlogedin = Driver.Instance.FindElement(By.ClassName("username"));
var selectelement = new SelectElement(userlogedin);
selectelement.SelectByText("JonPark2");
}
When I run this i encounter the error OpenQa.Selenium.Support.UI.unexpectedTagNameException:Element should have been select but was div.
The below html shows in more detail what I am trying to select:
<div class="content-wrapper">
<div class="float-left">
<div class="float-right">
<section id="login">
<p>
<a title="Manage your account" class="username" href="Account/Manage">
Text - Empty Text Node
<span class="username">
Text - JonPark2
Can anyone point out where I have gone wrong ?
You are trying to select something that is not part of a <select>.
try this:
public static void Userloggedin()
{
return (
"JonPark2" == Driver.Instance.FindElement(By.cssSelector("section#login span.username")).Text;
)
}
You can select that element by XPath:
var spanElement = Driver.Instance.FindElement(By.XPath("//span[contains(#class, 'username')]"));
And then take text:
var textInSpan = spanElement.Text
Related
I have a controller in C# that, among other things, provides HTML for external links.
var htmlLinkBuilder = new StringBuilder($#"
<div>
<span>Dropdown</span>
</div>
<div class='dropdown-menu'>
");
foreach (var instance in thing.instances)
{
htmlLinkBuilder.AppendLine($#"
<a
class='dropdown-item'
href='{_configuration["Identity:Url"]}otherStuff/urlThings'
target='_blank'
rel='noopener noreferrer'
[onClickVar]
>
{instance.Name}
</a>
");
}
htmlLinkBuilder.AppendLine("</div>");
link.HtmlLink = htmlLinkBuilder.ToString();
I'm using dangerouslySetInnerHTML in a react js file which contains a handleNavClickLogging() function.
My question is, can I properly reference the function over each link with some form of
__html: htmlFromAbove.replaceAll("[onClickVar]", { () => handleNavClickLogging('External Link') } )
or how can I reference this function when clicking a dropdown item?
Expected output is an onclick function performed after clicking one of the dropdown items.
I'm trying to dynamically set an attribute(data-status) for a div if a condition is met.
I am currently using the #Html.Raw helper however it's not making its way in to the element.
I have also attempted to use Response.Write() however it just writes everything to the top of the page.
Is there a best way to actually embed this in to the code or maybe create/set a new attribute?
#foreach (var r in Model)
{
<div class="marker"
data-date="#r.date_finished"
data-name="#r.name"
#if (r.complete == "CP")
{
#Html.Raw("data-status='complete'");
}
>
</div>
}
This should do it:
<div class="marker"
data-date="#r.date_finished"
data-name="#r.name"
#{if (r.complete == "CP") { <text>data-status='complete'</text> }}>
Notice the usage of <text> tag. This is a special tag which Razor uses to output content as is.
When I run into this scenario I use a tertiary expression:
<div #(r.complete == "CP" ? "data-status='complete'" : "") >
If your logic is more complex you could also use a static helper method.
<div #r.RenderComplete() >
public static class RExtension{
public static string RenderComplete( this R r){
// logic here
}
}
I've been trying, without luck, to use IJavaScriptExecutor to find a specific header string in a page. Here's the html code form the page:
<div class="wrap">
<h2>Edit Page <a href="http://www.webtest.bugrit.net/wordpress/wp-admin/post-
new.php?post_type=page" class="add-new-h2">Add New</a></h2>
<div id...
The text I need to check for is the "Edit Page" string.
This is the closest I've come, which isn't very close:
var element = FFDriver.Instance.FindElements(By.ClassName("add-new-h2"));
IJavaScriptExecutor js = FFDriver.Instance as IJavaScriptExecutor;
if (js != null) {
string innerHtml = (string)js.ExecuteScript("return arguments[0].innerHTML;", element);
//System.Windows.Forms.MessageBox.Show(innerHtml);
if (innerHtml.Equals("Edit Page")) {
return true;
} else {
return false;
}
}
Now, I realize that the text I should expect to get from that code isn't the exact string "Edit Page". But shouldn't it return something? When I enable the MessageBox line, the innerHtml string is empty.
Or, of couse - if someone knows another, possible easier, way to check for the existance of a specific string inside a specific html tag, I'm all ears.
Your element returns you <a> element, not <h2>. Your <a> doesn't contain Edit Page string.
Try find your element like this to the parent element <h2> (only if class name add-new-h2 is unique, otherwise you will get the first matching one):
var element = FFDriver.Instance.FindElement(By.XPath(".//a[#class='add-new-h2']/.."));
var containsText = element.Text.Contains("Edit Page");
My application must be used in IE. I am automating test in which the script will do the following in listed order
select option 'Accounting' in drop-box "Category" to get Accounting-associated options displayed in drop-box "Category"
select option 'Payment" in drop-box "Name" for page 'Accounting Payment Filter' to display
verify that the 'Employee' text-box in this page is visible
HTML source BEFORE option 'Payment' is selected (the page 'Accounting Payment Filter' has not displayed):
<form id="Main">
<span id="Entity">
<div>
<select id="drop_Category">
<option value =""/>
<option value = "Accounting">
<select id="drop_Name"> <-!
<option value =""/>
<option value ="Payment">
HTML source AFTER option 'Payment' is selected (page 'Accounting Payment Filter' displays and there is an iframe)
<form id="Main">
<span id="Entity">
<div class="ig_Control">
<div class ="ig_content">
<iframe title ="javascript:''">
<html>
<body>
<form id="Form1">
<div id="Panel1">
<table id="table1"
<tr>
<td>
<input id="Employee">
<div>
<select id="drop_Category">
<option value =""/>
<option value = "Accounting">
<select id="drop_Name"> <-!
<option value =""/>
<option value ="Payment">
I have the code up to 'Payment' option is selected. Now I call SwitchIframe function, then find and verify the text-box:
public static bool IsTextboxVisible (IWebDriver driver, Dictionary of all needed data )
{
//....
//Call to switch into iframe
SwitchIFrame(driver,stringXPath);
//Verify text-box is visible
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(1));
//Script crashes here- can't find element
var Textbox = wait.Until(d => d.FindElement(By.Id(TexboxID)));
return Textbox.Displayed;
}
public static void SwitchIFrame (IWebDriver driver,string strXPath)
{
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
var iFrame = wait.Until(d => d.FindElement(By.XPath(strXPath)));
driver.SwitchTo().Frame(iFrame);
}
Script can't find the text-box even when I increase the waiting time. Then I tried finding the ID "drop_Name" instead, and the script can find that drop-box. That means it did not switch into the iframe. So I switch that SAME iframe one more time:
public static bool IsTextboxVisible (IWebDriver driver, Dictionary of all needed data )
{
//....
//Call to switch into iframe
SwitchIFrame(driver,stringXPath);
//Call again to switch into the same iframe
SwitchIFrame(driver,stringXPath);
//Verify text-box is visible
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(1));
//Script crashes here- can't find element
var Textbox = wait.Until(d => d.FindElement(By.Id(TexboxID)));
return Textbox.Displayed;
}
Now script can find the text-box though sometimes is still given the exception that the XPath cannot be evaluated or not results in a web element. I update function SwitchIFrame:
public static void SwitchIFrame (IWebDriver driver,string strXPath)
{
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
try
{
var iFrame = wait.Until(d => d.FindElement(By.XPath(strXPath)));
driver.SwitchTo().Frame(iFrame);
}
catch (NoSuchFrameException)
{
var iFrame = wait.Until(d => d.FindElement(By.XPath(strXPath)));
driver.SwitchTo().Frame(iFrame);
}
}
But the same exception still happens sometimes in the 'try...' block. My questions:
Why do I have to switch the same iframe twice to get inside one iframe?
Why didn't 'try...catch...' in SwitchIframe function catch the
exception?
Any help is highly appreciated.
You may need to switch around the order of events a little bit. Based on the code you have I would actually wait on those additional divs that are loaded after the selection to become visible.
public static bool IsTextboxVisible (IWebDriver driver, Dictionary of all needed data )
{
//Verify text-box is visible
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
var Textbox = wait.Until(d => d.FindElement(By.ClassName("ig_content")));
SwitchIFrame(driver,stringXPath);
return Textbox.Displayed;
}
public static void SwitchIFrame (IWebDriver driver,string strXPath)
{
//var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
var iFrame = driver.FindElement(By.XPath(strXPath));
driver.SwitchTo().Frame(iFrame);
}
The reason for the change of order is that those divs are connected to the original html document. Assuming those divs appear when the iFrame is loaded you should be the able to switch to the new iFrame document. If your xPath does not work (IE may or may not play well with it) I would try using the index position of the frame in the switch to. This might be more reliable since the frame does not have an id to find.
driver.SwitchTo().Frame(1);
I removed the wait from the switch statement because in this case if the iFrame is dependent on the divs loading all you should need to do is have the divs there and the frame is loaded a long with it.
I am currently working on a C# project using ASP.NET. And I'd like to implement a list of dropboxes. So a User starts with a dropbox and can select a method and next to the dropbox is a + and - button, which enables a user to add more dropboxes. So I am wondering how can I implement that is it possible to build a List of dropboxes in ASP.NET?
You don't need any server side code for this, client side scripting is ideal solution for your needs.
Having such HTML:
<div id="MainPlaceholder">
<div id="DropDownPlaceholder">
<select name="myDropDown">
<option value="1">First</option>
<option value="2">Second</option>
<option value="3">Third</option>
</select>
<button type="button" onclick="AddDropDown(this);">+</button>
<button type="button" onclick="RemoveDropDown(this);">-</button>
</div>
</div>
You need the following pure JavaScript to make it work:
<script type="text/javascript">
var added_counter = 0;
function AddDropDown(sender) {
var parent = sender.parentNode;
//make fresh clone:
var oClone = parent.cloneNode(true);
//append to main placeholder:
parent.parentNode.appendChild(oClone);
//store change in global variable:
added_counter++;
}
function RemoveDropDown(sender) {
//don't allow to remove when there is only one left
if (added_counter <= 0) {
alert("One drop down must exist");
return;
}
var parent = sender.parentNode;
//disable so value won't be passed when form submitted:
parent.getElementsByTagName("select")[0].disabled = true;
//hide:
parent.style.display = "none";
//store change in global variable:
added_counter--;
}
</script>
The code has comments, but if you need any further explanation please feel free to ask.
Live test case.
Edit: As you need to read the selected values on the server side code, better approach would be to change the name of each cloned drop down:
var totalAddedCounter = 0;
function AddDropDown(sender) {
var parent = sender.parentNode;
//make fresh clone:
var oClone = parent.cloneNode(true);
//assign unique name:
oClone.getElementsByTagName("select")[0].name += "_" + totalAddedCounter;
//append to main placeholder:
parent.parentNode.appendChild(oClone);
//store change in global variable:
added_counter++;
totalAddedCounter++;
}
Now the tricky part is reading those values. Instead of plain dropboxlistID.Text you will have to iterate over all posted values looking for what you need:
foreach (string key in Request.Form.Keys)
{
if (key.StartsWith("dropboxlistID"))
{
string text = Request.Form[key];
//.....
}