Execute a java script to make an element visible - c#

I'm trying to automate the use of a website using Selenium, at one time I want to click on a hidden button defined this way :
<body>
<div class="smenu" id="smenu4">
<input tabIndex="-1" type="button" onclick="SearchEng" value="FindEng" />
<!--> Lots of inputs <!-->
</div>
</body>
I already tried to simply click the button, but it doesn't work. I can select it and retrieve information though. That's why I'm now trying to run a javascript to make the button visible before clicking it. Here is my code :
IWebElement element = driver.FindElement(By.XPath("//div[#id='smenu4']/input[#value=FindEng"));
String js = "arguments[0].style.height='auto'; arguments[0].style.visibility='visible';";
((IJavaScriptExecutor)driver).ExecuteScript(js, element);
The thing is nothing happens when I launch it. Is it possible that I can't run scripts ? Can you run them on any website ? - I use internet explorer 11, windows 7. Thanks !

Inspect the element in your Browser and check that what is the reason that the element is invisible. Or just simply compare the element when it is visible or not. Possible reasons:
The element is not in the DOM yet.
The element hasn't got width and/or height.
visibility parameter. (http://www.w3schools.com/cssref/pr_class_visibility.asp)
display parameter. (http://www.w3schools.com/cssref/pr_class_display.asp)
When you know the reason, you will know the solution :)

Related

IE & Edge Selenium drivers unable to find element in drop-down list

I'm trying to select an element from a drop-down menu.
On my page, the drop-down items are all spans and looks something like this:
<span class="dropdownlist" id="MyID">
<span class>Option 1</span>
<span class>Option 2</span>
<span class>Option 3</span>
<span class>Option 4</span>
Because the only identifier is the innerText (I don't want to use nth:childs). I have to use XPaths to match against which looks something like this (I escape the " marks as I'm using C#):
//*[#id=\"MyID\"]/span[text()=\"Option 1\"]
When I run this using the Chrome Driver it works perfectly fine. However, when I use the IEDriver or EdgeDriver neither of these can find the element in the list.
All my CSS selectors (and some none text driven XPaths) up until this point in my test work fine, it is simply the drop-down field that is causing my problems.
Im currently starting my IE Driver with no capabilities set, could there be an option there I should be using perhaps?
UPDATE: I've tried using a CssSelector and this returns with an error saying that the element in the list I'm trying to click is not displayed. Running a little assertion to check if the element is displayed before clicking it returns false.
UPDATE 2: I've trying running some Java Script from inside my code to assign an ID to the element and then trying to click it using that, but I'm getting the same error (again, this method works in chrome and the ID is getting assigned properly)
Here's a picture of the control:
Code involves first clicking the field which makes the drop list appear, then selecting the item from the list.
dropDownField.Click();
IWebElement listItemToSelect=
driver.FindElement(By.XPath("//span[text()=\"Bangkok\"]"));
WebDriverWait wait = new WebDriverWait(driver,
TimeSpan.FromSeconds(10));
wait.Until(ExpectedConditions.ElementToBeClickable(By.XPath("//span[text()=\"Bangkok\"]")));
listItemToSelect.Click();

ElementNotVisibleException try to use Xpath to Enter data into a textbox with Selenium

I am using Selenium in C# to Enter data into textboxes on a webpage:
But i am getting this error:
OpenQA.Selenium.ElementNotVisibleException: Element is not currently visible and so may not be interacted with
I'm using #name, but there are 2 controls on the page with name="MinPrice"
heres the HTML:
<div class="form-group for-sale">
<label>Min Price</label>
<input class="form-control" name="MinPrice" min="0" placeholder="Minimum Price" value="" type="number"></input>
and this is the xpath I'm using:
txtMinPrice = Driver.Instance.FindElement(By.Name("MinPrice"));
I also tried using XPath, but similar results:
txtMinPrice = Driver.Instance.FindElement(By.XPath("//input[contains(#name,'MinPrice') and type='number']"));
If anyone has any type of idea....this is driving me nuts.
ElementNotVisibleException exception occurs when selenium can find an element in the DOM but it is not rendered on the screen.
When I have encountered this error before it has been generally caused by one of three things:
Selenium is trying to interact with an object that is present in the DOM but has not yet rendered on the screen, in which case you might consider adding some type of delay. (Avoid sleep if you can but it is useful for debugging)
The element is below the visible screen, in which case you would need to scroll to interact with it.
There is an overlapping element that is blocking the display of the element.
Add a sleep(10) in to make sure everything on the page has loaded first before any user actions are preformed. If that doesn't work also add
driver.manage().window().maximize() at the start of your test to make sure all the page elements is in view.
If that doesn't work its your xpath. Try something like //*[#class="form-group for-sale"]/input
Or use the Firefinder add on in mozilla firefox to check your xpath is valid and exists on the page.
Selenium is good at scrolling down to view an item, but when it comes to Scrolling back up it's a PiA, and usually throws that exception. I usually just do something like
element.SendKeys(Keys.Home);
Thread.Sleep(100);

Finding Button within Button Group Class Using Selenium Webdriver in C#

My end goal is to be able to click Yes or No on a webpage.
Using fire bug I can see the Yes and No buttons reside in a class called "btn-group"
<div class="btn-group btn-group-default answer-toggle" aria-label="..." role="group">
<button class="btn ng-pristine ng-valid active btn-secondary ng-touched" btn-radio="true" ng-model="consultation.previousSoundVoid" ng-class="{'btn-secondary': consultation.previousSoundVoid}" type="button">
Yes
</button>
<button class="btn ng-pristine ng-untouched ng-valid" btn-radio="false" ng-model="consultation.previousSoundVoid" ng-class="{'btn-secondary': consultation.previousSoundVoid == false}" type="button">
No
</button>
</div>
I think I could find Element by XPath but I am trying to improve my Selenium skill.
I am hoping there is a way to first find the "btn-group" class then somehow choose Yes or No within that.
Or be able to create variables for both the Yes and No options. If I do:
var button = Driver.Instance.FindElements(By.ClassName("btn"));
It returns 21 options. I found that:
button[15].Text returns "Yes"
button[16].Text returns "No"
Instead of having to look through all 21 results and worrying about if the index changes, can I search the results by text somehow?
The best way is to identify those element using text and xpath since they do not have any unique id
//button[.='Yes']
Desperate to use cssSelector?
.btn.ng-pristine.ng-valid.active.btn-secondary.ng-touched
since it is a compound class
You can also go for nth-child() with css
[role='group']>button:nth-child(1)
whereas 2 will let you select the button with text No
Case 1: When answer-toggle is unique in the HTML page
Driver.Instance.FindElements(By.XPath("//div[contains(#class,'answer-toggle')]//button[contains(text(),'Yes')]")).Click();
This will first locate a div that has answer-toggle in its class name and the find a button that has text Yes
Case 2: answer-toggle is not unique in your HTML page the you can use the complete class name as follows
Driver.Instance.FindElements(By.XPath("//div[#class='btn-group btn-group-default answer-toggle']//button[contains(text(),'Yes')]")).Click();
or
Driver.Instance.FindElements(By.XPath("//div[#class,'btn-group btn-group-default answer-toggle']//button[contains(text(),'Yes')]")).Click();
Case 3: If there is only one button in your HTML page that has text "Yes"
Driver.Instance.FindElements(By.XPath("//button[contains(text(),'Yes')]")).Click();
Same thing applies for No button. You just have to replace Yes with No.
There are definitely multiple options to locate the buttons, but I think that answer-toggle class sounds a good thing to rely on:
var buttons = Driver.Instance.FindElements(By.CssSelector("div.answer-toggle button.btn"));

Selenium Click() does not work with ASP.NET LinkButton

I'm Writing a Selenium text case for an ASPX page. I want to click this ASP.NET asp:LinkButton element:
<asp:LinkButton runat="server" OnClick="Test_Click" Text="Just try to click me" ID="testtest123"></asp:LinkButton>
Which appears like this in the HTML page generated by .NET:
<a id="testtest123" href="javascript:__doPostBack('testtest123','')">Just try to click me</a>
But while Selenium has no problem finding the element, the Click() does nothing. I get no element missing exceptions or timeouts, the testcase just runs on as if the click fired properly.
Here's the simple line for clicking the element;
Browser.Driver.FindElement(By.Id("testtest123")).Click();
This code works fine with other ASP elements such as buttons and text boxes. I use C# to write my test cases using the 64 bit webdriver and IE 11.
I researched the solutions here: ASP.Net LinkButton Prevent Postback Not Working - JavaScript but they do not seem to apply to my situation:
Any help would be greatly appreciated!
EDIT: I posted another thread about the issue on this website:
https://code.google.com/p/selenium/issues/detail?id=7846&can=8&colspec=ID%20Stars%20Type%20Status%20Priority%20Milestone%20Owner%20Summary
I had a similar problem where some controls were rendered as espected and other don't, so are you sure the link ID is "testtest123"?
You have to set Client ID Mode to static in order to make the HTML ID be the same as in the .NET (the default is inherit, but in the web.config it is generlly set to be AutoID).
<asp:LinkButton runat="server" OnClick="Test_Click" Text="Just try to click me" ID="testtest123" ClientIDMode ="Static"></asp:LinkButton>
If the rendered HTML is actually <A id=testtest123 then that is not valid HTML since the attribute does not have quotation marks around the value. If this is actual value then the problem is further upstream than Selenium
One possibility is that selenium is correctly clicking the element, but that the linkbutton's javascript code is not executing quickly enough for the rest of your test. This is because when selenium encounters an <input type="submit"> tag (like asp.net button controls), it knows that it has to wait for the form submission before going to the next test step. However, a linkbutton is just an <a> tag, and worse, it has javascript as the href as opposed to a url. So it's possible that the postback javascript takes 50 milliseconds to execute or whatever, in that case, it's possible a test like this:
step n: click linkbutton - selenium does not know how long this takes so proceeds to next step
step n+1: click some button - if this happens before the js finishes executing, it would be like step n did not happen at all
This is plausible in the case of selenium because it operates at the speed of a program, whereas a human tester would never be able to click the next step quickly enough to cause such a problem. The fix for this is to add a delay step, or, to add a watch step on a javascript variable that you set on click of your linkbutton.
Edit:
Ok, so then this is not the issue. I'm almost positive it has something to do with the javascript in the href, though, so could you try the answer here: https://stackoverflow.com/a/18847713/1981387 ?

"SCRIPT5 Access is denied" error on IE9 when firing .click() from onchange

We want to reduce the number of steps it takes for a user to upload a file on our website; so we're using jQuery to open and postback files using the below markup (simplified):
<a onclick="$('#uplRegistrationImage').click();">
Change profile picture
</a>
<!-- Hidden to keep the UI clean -->
<asp:FileUpload ID="uplRegistrationImage"
runat="server"
ClientIDMode="static"
Style="display:none"
onchange="$('#btnSubmitImage').click();" />
<asp:Button runat="server"
ID="btnSubmitImage"
ClientIDMode="static"
Style="display:none"
OnClick="btnSubmitImage_OnClick"
UseSubmitBehavior="False" />
This works absolutely fine in Firefox and Chrome; opening the file dialog when the link is clicked and firing the postback when a file is selected.
However in IE9 after the file upload has loaded and a user has selected a file; insteaed of the OnChange working I get a "SCRIPT5 Access is denied" error. I've tried setting an arbitrary timeout, setting intervals to check if a file is given to no avail.
There are a number of other questions relating to this; however none appear to have a decent answer (One said set the file dialog to be transparent and hover behind a button!)
Has anyone else resolved this? Or is it absolutely necessary that I provide a button for IE users?
For security reasons, what you are trying to do is not possible. It seems to be the IE9 will not let you submit a form in this way unless it was an actual mouse click on the File Upload control that triggers it.
For arguments sake, I was able to use your code to do the submit in the change handler, but it worked only when I clicked the Browse button myself. I even set up polling in the $(document).ready method for a variable set by the change handler that indicates a submission should be triggered - this didn't work either.
The solutions to this problem appear to be:
Styling the control in such a way that it sits behind a button. You mentioned this in your question, but the answer provided by Romas here In JavaScript can I make a "click" event fire programmatically for a file input element? does in fact work (I tried in IE9, Chrome v23 and FF v15).
Using a Flash-based approach (GMail does this). I tried out the Uploadify demo and it seems to work quite nicely.
Styling a File Upload:
http://www.quirksmode.org/dom/inputfile.html
http://www.shauninman.com/archive/2007/09/10/styling_file_inputs_with_css_and_the_dom
References:
jQuery : simulating a click on a <input type="file" /> doesn't work in Firefox?
IE9 file input triggering using Javascript
getting access is denied error on IE8
Hey this solution works.
for download we should be using MSBLOB
$scope.getSingleInvoicePDF = function(invoiceNumberEntity) {
var fileName = invoiceNumberEntity + ".pdf";
var pdfDownload = document.createElement("a");
document.body.appendChild(pdfDownload);
AngularWebService.getFileWithSuffix("ezbillpdfget",invoiceNumberEntity,"pdf" ).then(function(returnedJSON) {
var fileBlob = new Blob([returnedJSON.data], {type: 'application/pdf'});
if (navigator.appVersion.toString().indexOf('.NET') > 0) { // for IE browser
window.navigator.msSaveBlob(fileBlob, fileName);
} else { // for other browsers
var fileURL = window.URL.createObjectURL(fileBlob);
pdfDownload.href = fileURL;
pdfDownload.download = fileName;
pdfDownload.click();
}
});
};
This solution looks like it might work. You'll have to wrap it in a <form> and get it to post in the jquery change handler, and probably handle it in form_load using the __eventtarget or and iframe or whatever it is that web forms uses, but it allows you to select a file, and by submitting the form, it should send it. I can't test it however, since I don't have an environment set up at home.
http://jsfiddle.net/axpLc/1/
<a onclick="$('#inputFile').click();">
Change profile picture
</a>
<div id='divHide'>
<input id='inputFile' type='file' />
</div>
$('#inputFile').change(function() { alert('ran'); });
#divHide { display:none; }
Well, like SLC stated you should utilize the <Form> tag.
First you should indicate the amount of files; which should be determined by your input fields. The second step will be to stack them into an array.
<input type="file" class="upload" name="fileX[]"/>
Then create a loop; by looping it will automatically be determined based on the input field it's currently on.
$("input[#type=file]:nth(" + n +")")
Then you'll notice that each file chosen; will replace the input name to the file-name. That should be a very, very basic way to submit multiple files through jQuery.
If you'd like a single item:
$("input[#type=file]").change(function(){
doIt(this, fileMax);
});
That should create a Div where the maximum file found; and attaches to the onEvent. The correlating code above would need these also:
var fileMax = 3;
<input type="file" class="upload" name="fileX[]" />
This should navigate the DOM parent tree; then create the fields respectively. That is one way; the other way is the one you see above with SLC. There are quite a few ways to do it; it's just how much of jQuery do you want manipulating it?
Hopefully that helps; sorry if I misunderstood your question.

Categories