Using C# and Selenium, I am building an automated script where I, amongst other things, try to select a certain value from a droplist (value being specified in a .csv-file). I get the error;
"An error occurred executing the click atom (WARNING: The server did not provide any stacktrace information)"
I have no idea what a click atom is, much less how to fix it... Any help is appreciated greatly!
thanks in advance
this is the code for the droplist:
public bool isellHOSelectAdultsDroplist(string adults)
{
writeToLog(String.Format("Selecting adults from drop list"), this.GetType().Name);
String xpathString = HO_ADULT_SELECTION;
if(GpoExplicitWaitXpathElement(xpathString, 3, 5))
{
IWebElement dropListObjects = webDriver.FindElement(By.XPath(xpathString));
writeToLog(String.Format("DEBUG: Trying to click on appropriate number of adults..."), this.GetType().Name);
selectValueFromAdultDropList(dropListObjects, adults);
return true;
}
else
{
return false;
}
}
//...and this is my select-method
private void selectValueFromAdultDropList(IWebElement dropListObjects, string adults)
{
SelectElement manipulateDroplistObject = new SelectElement(dropListObjects);
manipulateDroplistObject.SelectByValue(adults);
String selection = manipulateDroplistObject.SelectedOption.Text;
int numberOfElements = manipulateDroplistObject.Options.Count;
writeToLog("Number of elements in Adult Droplist: " + numberOfElements, this.GetType().Name);
writeToLog("Selection from adult droplist: " + selection, this.GetType().Name);
}
I'll answer the specific question you asked, which is, "What is a click atom?" There is quite a bit of functionality in the IE driver, and the implementation of this functionality rests on three pillars.
First is IE's COM interfaces. These are the objects and methods that have been used to automate various parts of IE for more than a decade.
The second technology is so-called "native events." That is, using OS-level mechanisms to perform user interactions, like key presses and mouse clicks. On Windows, that means using the Windows SendMessage API. Almost anytime you're using the keyboard or the mouse with the IE driver, you're using native events by default.
Finally, a good portion of the IE driver functionality is implemented using JavaScript functions, which are shared by all of the browsers. These functions are known as "automation atoms".
One of the very few exceptions to using native events for mouse operations is in selecting an <option> element from a <select> element. Since IE doesn't give discoverable dimensions to <option> elements, the IE driver is forced to simulate the click action via JavaScript. This means using the automation atom for the click action. In your case, something must've gone wrong executing that JavaScript, which was faithfully reported as a "failure to execute the click atom." Without more detail, including sample HTML pages to reproduce the issue, it will be exceedingly difficult to diagnose the root cause of the issue.
It's at this point I will echo the call to update to the latest IE driver. Some of the code in this area has been overhauled, and at the least, it should be possible to extract more precise errors from failure cases with a more recent driver.
Related
I just updated my Chrome Driver to the latest version - 73.0.3683.68 and ever since my "Click" Function is not working properly (it does work at times, but not everytime).
Chrome version: Version 73.0.3683.75 (Official Build) (64-bit)
I code with C#.
The biggest problem is that Selenium acts as if the "Click" worked properly and moves on to the next function and there it fails because the element is not present on the screen yet.
It should be noted that prior to clicking on the element, we do verify that the element is clickable.
Is there a way to make sure the "Click" function actually occurred?
A function like Click and Verify?
Thanks.
Hey I was able to resolve my issue by updating to ChromeDriver 74.0.3729.6. You will need to use the beta version of Chrome as well. In your code you will need to setup a binary path to point to Chrome Beta since it doesn't use the same path as the current release. Chrome reported in their documentation that it was sometimes sending clicks to the wrong element with version 73.0.3683.68.
Here is the site for more information: http://chromedriver.chromium.org/downloads Look at the release notes and you will find the information there.
I hope this resolves your issue.
I am not sure what the click does but let's say it takes you to a new page. You could add a method that looks to see if the button you just clicked is still visible, if so, click it again. That being said, when you debug it and step into it, does it work? Maybe try a MoveToElement first? You could also add a java click instead which tends to be more reliable in all honesty.We added a try catch and did the c# click and then did a js click if the c# click failed. Best of both worlds.
public static void Click(IWebElement element)
{
var actions = new Actions(driver);
actions.MoveToElement((element));
actions.Click(element).Perform();
}
public static void JClick(IWebElement element)
{
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].click();", element);
}
public static void LastChanceClick(IWebElement element)
{
try
{
Click(element);
}
catch (Exception)
{
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].click();", element);
}
}
I am working from the sample project here: http://www.codeproject.com/Articles/8086/Extending-the-save-file-dialog-class-in-NET
I have hidden the address/location bar at the top and made other modifications but I can't for the life of me manage to disable the button that lets you go up to the parent folder. Ist is in the ToolbarWindow32 class which is the problem. This is what I have at the moment but it is not working:
int parentFolderWindow = GetDlgItem(parent, 0x440);
//Doesn't work
//ShowWindow((IntPtr)parentFolderWindow, SW_HIDE);
//40961 gathered from Spy++ watching messages when clicking on the control
// doesn't work
//SendMessage(parentFolderWindow, TB_ENABLEBUTTON, 40961, 0);
// doesn't work
//SendMessage(parentFolderWindow, TB_SETSTATE, 40961, 0);
//Comes back as '{static}', am I working with the wrong control maybe?
GetClassName((IntPtr)parentFolderWindow, lpClassName, (int)nLength);
Alternatively, if they do use the parent folder button and go where I don't want them to, I'm able to look at the new directory they land in, is there a way I can force the navigation to go back?
Edit: Added screenshot
//Comes back as '{static}', am I working with the wrong control maybe?
You know you are using the wrong control, you expected to see "ToolbarWindow32" back. A very significant problem, a common one for Codeproject.com code, is that this code cannot work anymore as posted. Windows has changed too much since 2004. Vista was the first version since then that added a completely new set of shell dialogs, they are based on IFileDialog. Much improved over its predecessor, in particular customizing the dialog is a lot cleaner through the IFileDialogCustomize interface. Not actually what you want to do, and customizations do not include tinkering with the navigation bar.
The IFileDialogEvents interface delivers events, the one you are looking for is the OnFolderChanging event. Designed to stop the user from navigating away from the current folder, the thing you really want to do.
While this looks good on paper, I should caution you about actually trying to use these interfaces. A common problem with anything related to the Windows shell is that they only made it easy to use from C++. The COM interfaces are the "unfriendly" kind, interfaces based on IUnknown without a type library you can use the easily add a reference to your C# or VB.NET project. Microsoft published the "Vista bridge" to make these interfaces usable from C# as well, it looks like this. Yes, yuck. Double yuck when you discover you have to do this twice, this only works on later Windows versions and there's a strong hint that you are trying to do this on XP (judging from the control ID you found).
This is simply not something you want to have to support. Since the alternative is so simple, use the supported .NET FileOk event instead. A Winforms example:
private void SaveButton_Click(object sender, EventArgs e) {
string requiredDir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
using (var dlg = new SaveFileDialog()) {
dlg.InitialDirectory = requiredDir;
dlg.FileOk += (s, cea) => {
string selectedDir = System.IO.Path.GetDirectoryName(dlg.FileName);
if (string.Compare(requiredDir, selectedDir, StringComparison.OrdinalIgnoreCase) != 0) {
string msg = string.Format("Sorry, you cannot save to this directory.\r\nPlease select '{0}' instead", requiredDir);
MessageBox.Show(msg, "Invalid folder selection");
cea.Cancel = true;
}
};
if (dlg.ShowDialog() == DialogResult.OK) {
// etc...
}
}
}
I don't this is going to work. Even if you disable the button they can type ..\ and click save and it will take them up one level. You can't exactly disable the file name text box and maintain the functionality of the dialog.
You'd be better off either using the FolderBrowserDialog and setting it's RootFolder property and asking the user to type the filename in or auto generating it.
If the folder you are wanting to restrict the users to isn't an Environment.SpecialFolder Then you'll need to do some work to make the call to SHBrowseForFolder Manually using ILCreateFromPath to get a PIDLIST_ABSOLUTE for your path to pass to the BROWSEINFO.pidlRoot
You can reflect FolderBrowserDialog.RunDialog to see how to make that call.
Since you want such custom behaviors instead of developing low level code (that is likely yo break in the next versions of windows) you can try to develop your file picker form.
Basically it is a simple treeview + list view. Microsoft has a walk-through .
It will take you half a day but once you have your custom form you can define all behaviors you need without tricks and limits.
I've a C# app that responds correctly to a global hotkey. I want to get the selected text from another app which has the focus if the global hotkey is pressed.
I tested native Win32 Api, then SendKeys (CTRL + C, Clipboard,...) and now Microsoft UI Automation! The problem is, this only works in Notepad, but not in Internet Explorer or Word or other apps.
I think there must be a better solution than the code I have. I read that sending CTRL + C should work fine, but that only works in Notepad too.
Here's the method I call when the global hotkey is fired:
public String GetSelectedTextFromApp()
{
String output = "";
AutomationElement focused = AutomationElement.FocusedElement;
object pattern;
TextPatternRange[] trs;
if (focused.TryGetCurrentPattern(TextPattern.Pattern, out pattern))
{
TextPattern tp = (TextPattern)pattern;
trs = tp.GetSelection();
output = trs[0].GetText(-1);
}
return output;
}
The control you're trying to automate might not be implementing TextPattern. It might only implement ValuePattern. Also, it's possible that the control you're focused on isn't the control which actually contains the text, but rather a wrapping control under which you'll find an AutomationElement implementing the above mentioned patterns. Another possibility is, like Andrii said, is that the control doesn't support UIA at all (though I find it hard to believe in case of MS Word).
In such cases, it's worth working with UISpy.exe which will help you see the visual tree of the application you're trying to automate. You'll also be able to see the supported Patterns for each AutomationElement. You can also call GetSupportedPatterns() on every AutomationElement, to see which Patterns are currently supported.
If anyone can help me I'd appreciate it.
I'm working on a C# file in Visual Studio 2010 that I need to be able to test a website with multiple form pages, for the purpose of an example we'll refer to them all as 1.aspx, 2.aspx etc.
I've my code that fills out the first page (1.aspx) fine, and click the "continue" button to load the next page, but when it gets to 2.aspx it won't continue to fill out the form.
We'll say an element on the 2.aspx page is called "DOB". On trying to run from the start (I've all the pages form data in the one .cs file) I get an error like "DOB does not exist in the current context".
Anyone's insight into this would be really appreciated!
In all honesty, it sounds like you might be better off using the WatiN Framework. I have been writing automation with it for years and the way that it is implemented and its ease-of-use make it worth the slight learning curve.
Just to add a bit more to the answer; and yes, this is pseudo-code:
[Test]
public void Should_attach_to_browser()
{
ExecuteTest(browser =>
{
browser.GoTo(NewWindowUri);
browser.Link(Find.First()).Click();
var findBy = Find.ByTitle("New window");
var newWindow = Browswer.AttachTo(browser.GetType(), findBy);
newWindow.Close();
});
}
In the code above, note the Browser.AttachTo(browser.GetType(), findBy); method. Based on what I have understood of your question, the .AttachTo() method would work well since you would be able to take the focus off the current form and assign it to the next in your work/execution flow.
I have an application which writes HTML to a WebBrowser control in a .NET winforms application.
I want to detect somehow programatically if the Internet Settings have Javascript (or Active Scripting rather) disabled.
I'm guessing you need to use something like WMI to query the IE Security Settings.
EDIT #1: It's important I know if javascript is enabled prior to displaying the HTML so solutions which modify the DOM to display a warning or that use tags are not applicable in my particular case. In my case, if javascript isn't available i'll display content in a native RichTextBox instead and I also want to report whether JS is enabled back to the server application so I can tell the admin who sends alerts that 5% or 75% of users have JS enabled or not.
Thanks to #Kickaha's suggestion. Here's a simple method which checks the registry to see if it's set. Probably some cases where this could throw an exception so be sure to handle them.
const string DWORD_FOR_ACTIVE_SCRIPTING = "1400";
const string VALUE_FOR_DISABLED = "3";
const string VALUE_FOR_ENABLED = "0";
public static bool IsJavascriptEnabled( )
{
bool retVal = true;
//get the registry key for Zone 3(Internet Zone)
Microsoft.Win32.RegistryKey key = Registry.CurrentUser.OpenSubKey(#"Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\3", true);
if (key != null)
{
Object value = key.GetValue(DWORD_FOR_ACTIVE_SCRIPTING, VALUE_FOR_ENABLED);
if( value.ToString().Equals(VALUE_FOR_DISABLED) )
{
retVal = false;
}
}
return retVal;
}
Note: in the interest of keep this code sample short (and because I only cared about the Internet Zone) - this method only checks the internet zone. You can modify the 3 at end of OpenSubKey line to change the zone.
If you are having troubles with popups popping up, i've included a solution for you, and if you want to disable/enable javascript on th client machine (or even just read/query if it is enabled/disabled) ive included that answer for you as well, here we go:
Which popup message do you want to disable? If it's the alert message, try this, obviously resolving the window or frame object to your particular needs, I’ve just assumed top-level document, but if you need an iframe you can access it using window.frames(0). for the first frame and so on... (re the JavaScript part)... here is some code, assuming WB is your webbrowser control...
WB.Document.parentWindow.execScript "window.alert = function () { };", "JScript"
You must run the above code only after the entire page is done loading, i understand this is very difficult to do (and a full-proof version hasn't been published yet) however I have been doing it (full proof) for some time now, and you can gather hints on how to do this accurately if you read some of my previous answers labelled "webbrowser" and "webbrowser-control", but getting back to the question at hand, if you want to cancel the .confirm JavaScript message, just replace window.alert with window.confirm (of course, qualifying your window. object with the correct object to reach the document hierarchy you are working with). You can also disable the .print method with the above technique and the new IE9 .prompt method as well.
If you want to disable JavaScript entirely, you can use the registry to do this, and you must make the registry change before the webbrowser control loads into memory, and every time you change it (on & off) you must reload the webbrowser control out and into memory (or just restart your application).
The registry key is \HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\ - the keyname is 1400 and the value to disable it is 3, and to enable it is 0.
Of course, because there are 5 zones under the Zones key, you need to either change it for the active zone or for all zones to be sure. However, you really don't need to do this if all you want to do is supress js dialog popup messages.
Let me know how you go, and if I can help further.
Here is a suggestion - Encode the warning into your webpage as default. Create a javascript that runs on page load which removes that element. The warning will be there when ever javascript is not allowed to run.
It's a long while since I coded client side HTML javascript to interact with the DOM so I may be a little out of date. i.e. you will need to fix details, but I hope I get the general idea across.
<script>
document.getElemntByID("noJavascriptWarning").innerHTML="";
</script>
and in your HTML body
<DIV id="noJavascriptWarning" name="noJavaScriptWarning">Please enable Javascript</DIV>