I am testing a web page that contains a table. You can click a "Create new" link to add records to the grid. Once "Create New" is clicked, a dialog appears with some text boxes, another grid and a Cancel and Save button. You can then click a link to add a record to the dialog's grid which makes another dialog appear with text boxes and a Cancel and Save button. At my test level class, I currently click on these buttons then wait for the dialog's to open or close. I need to formulate a generic method which encompasses both the click and the wait, for each and every button. So instead of 2 lines of code at my test level to click an element and wait for a window, I would have one line of code that handles that. Below is my dilemma:
I need to be able to apply an If condition where a passed parameter of IWebElement equals a certain IWebElement, but it does not allow me to do this. The if statement doesn't find a match for some reason, so code inside the if statement never gets reached. Am I missing something? If not, is there a workaround?
NOTE: Using button.text == SaveOrganizationBtn.Text is a workaround, but would fail in my specific case, because some of these buttons might not have been loaded into the HTML for a certain test (i.e. A form has not been invoked), so the if statement fails. It would never be able to grab the Text property because it cant find the element in the first place.
Example code:
ClickButton(SaveNetworkBtn);
public void ClickButton(IWebElement button)
{
if (button == SaveOrganizationBtn)
{
SaveOrganizationBtn.Click();
WaitForOrganizationFormToClose();
}
if (button == SaveNetworkBtn)
{
SaveNetworkBtn.Click();
WaitForNetworkFormToClose();
}
Use the Equals() method for your scenario. == will not work for this. you need to check it as if(button.Equals(SaveOrganizationBtn)). The result for this will be true, if it is the same object else it will return false.
I hope, it will help you.
I found a solution, however awkward it might look. I will mark this as the answer if no one else provides a better solution.
ClickButton(SaveNetworkBtn);
public bool ClickButton(IWebElement button)
{
bool buttonClicked = false;
if (Driver.FindElements(By.Id("SaveOrg-Button-ID")).Count > 1)
{
if (button == SaveOrganizationBtn)
{
SaveOrganizationBtn.Click();
WaitForOrganizationFormToClose();
buttonClicked = true;
return buttonClicked;
}
}
if (Driver.FindElements(By.Id("SaveNet-Button-ID")).Count > 1)
{
if (button == SaveNetworkBtn)
{
SaveNetworkBtn.Click();
WaitForNetworkFormToClose();
buttonClicked = true;
return buttonClicked;
}
}
return buttonClicked;
}
I don't fully understand your scenario but it seems like something like this might work... you will have to decide. Instead of passing in button, just check if the button exists on the page, if it does... click it.
ClickButton();
public bool ClickButton()
{
IReadOnlyCollection<IWebElement> saveOrg = Driver.FindElements(By.Id("SaveOrg-Button-ID"));
if (saveOrg.Any())
{
saveOrg.ElementAt(0).Click();
WaitForOrganizationFormToClose();
return true;
}
IReadOnlyCollection<IWebElement> saveNet = Driver.FindElements(By.Id("SaveNet-Button-ID"));
if (saveNet.Any())
{
saveNet.ElementAt(0).Click();
WaitForNetworkFormToClose();
return true;
}
return false;
}
NOTE: .Any() works the same as .Count > 0, I found it a while back and like it a little better but it's a personal preference.
Related
i have a problem in Unity3d scripts.
I'm trying to make a sort of combination to open a box.
To open this box, i have to insert a combination of 3 buttons correctly.
This 3 buttons(That are simple GameObject, already placed in my scene) have already an animation, when my character collide with one of them, this one will fall down (same animation to other 2).
So, the combination that i want to insert is "the first correct button is "Button n*2", the second correct button is "Button n*1" and the third correct button is "Button n*3"", but i really don't have idea of how i have to do this.
I tried with if statements but if for example the combination is 123-312-123 the animation of the boxes will show up.
I want that only if i do the combination 213 the box is open, than if i go wrong i have to repeat the combination.
Can anyone help me?
Simple way, have a collection of right sequence:
int[] solution = new int[]{2,1,3};
then anytime a button is used, add its value to another collection:
List<int> sequence = new list<int>();
void OnPress(int buttonValue)
{
if(sequence.Contains(buttonValue)){ return; } // Don't add twice
sequence.Add(buttonValue);
if(sequence.Count == solution.Length)
{
if(CompareSequence())
{
// win
}
else
{
sequence.Clear();
}
}
}
bool CompareSequence()
{
// this should not be since we checked before but just to be sure
if(solution.Length != sequence.Count){ return false; }
for(int i = 0; i < solution.Length; i++)
{
if(solution[i] != sequence[i]){ return false; }
}
return true;
}
Each action on button would pass its own value that gets added to the list.
When the list and the solution are same length, they get compared. If they are same, you move to win section, if not, the sequence is cleared and user needs to refill content.
I have a WPF CheckBox inside a Popup, and I'm finding if it is inside the item template of a TreeView, then the CheckBox does not respond to user input. If it is outside of the TreeView, then there are no problems.
I have created a relatively minimal mock-up here:
https://github.com/logiclrd/TestControlsInPopupsNotWorking
Does anyone know why the CheckBox controls popped up from within the TreeView cannot be checked?
I think this is an oversight in the design of the TreeView. Take a look at this:
Note: Some code excerpts were tidied up to avoid wrapping.
// This method is called when MouseButonDown on TreeViewItem and also listen
// for handled events too. The purpose is to restore focus on TreeView when
// mouse is clicked and focus was outside the TreeView. Focus goes either to
// selected item (if any) or treeview itself
internal void HandleMouseButtonDown()
{
if (!this.IsKeyboardFocusWithin)
{
if (_selectedContainer != null)
{
if (!_selectedContainer.IsKeyboardFocused)
_selectedContainer.Focus();
}
else
{
// If we don't have a selection - just focus the TreeView
this.Focus();
}
}
}
This method is called from TreeViewItem.OnMouseButtonDown, which we can see is a class-level handler that's configured to receive handled events too:
EventManager.RegisterClassHandler(
typeof(TreeViewItem),
Mouse.MouseDownEvent,
new MouseButtonEventHandler(OnMouseButtonDown),
/* handledEventsToo: */ true);
I have verified with the debugger that Handled is set to true by the time the event makes it to the TreeViewItem.
When you press down on the left mouse button over the CheckBox, the CheckBox begins a speculative 'click' operation and marks the event as handled. Normally, an ancestor element wouldn't see a handled event bubble up, but in this case it explicitly asked for them.
The TreeView sees that this.IsKeyboardFocusWithin resolves to false because the focused element is in another visual tree (the popup). It then gives focus back to the TreeViewItem.
Now, if you look in ButtonBase:
protected override void OnLostKeyboardFocus(KeyboardFocusChangedEventArgs e)
{
base.OnLostKeyboardFocus(e);
if (ClickMode == ClickMode.Hover)
{
// Ignore when in hover-click mode.
return;
}
if (e.OriginalSource == this)
{
if (IsPressed)
{
SetIsPressed(false);
}
if (IsMouseCaptured)
ReleaseMouseCapture();
IsSpaceKeyDown = false;
}
}
We see that IsPressed is set to false when focus is lost. If we then go to OnMouseLeftButtonUp, we see this:
bool shouldClick = !IsSpaceKeyDown && IsPressed && ClickMode == ClickMode.Release;
With IsPressed now false, the click operation never completes, all because the TreeViewItem stole focus away from you when you tried to click the button.
As a work-around, I have had success so far with using the NuGet library Ryder (which looks like a freely-usable open-source (MIT license) version of Microsoft Detours) to intercept the HandleMouseButtonDown method in TreeView.
The Ryder library can be found in the NuGet library, and the code behind it can be found here:
https://github.com/6A/Ryder
Hooking the HandleMouseButtonDown method is pretty simple:
var realMethod = typeof(System.Windows.Controls.TreeView).GetMethod("HandleMouseButtonDown", BindingFlags.Instance | BindingFlags.NonPublic);
var replacementMethod = typeof(Program).GetMethod(nameof(TreeView_HandleMouseButtonDown_shim), BindingFlags.Static | BindingFlags.NonPublic);
Redirection.Redirect(realMethod, replacementMethod);
The shim that replaces the method can basically do what the real method does but with a fix that detects the cross-visual-tree focus situation:
static void TreeView_HandleMouseButtonDown_shim(TreeView #this)
{
// Fix as seen in: https://developercommunity.visualstudio.com/content/problem/190202/button-controls-hosted-in-popup-windows-do-not-wor.html
if (!#this.IsKeyboardFocusWithin)
{
// BEGIN NEW LINES OF CODE
var keyboardFocusedControl = Keyboard.FocusedElement;
var focusPathTrace = keyboardFocusedControl as DependencyObject;
while (focusPathTrace != null)
{
if (ReferenceEquals(#this, focusPathTrace))
return;
focusPathTrace = VisualTreeHelper.GetParent(focusPathTrace) ?? LogicalTreeHelper.GetParent(focusPathTrace);
}
// END NEW LINES OF CODE
var selectedContainer = (System.Windows.Controls.TreeViewItem)TreeView_selectedContainer_field.GetValue(#this);
if (selectedContainer != null)
{
if (!selectedContainer.IsKeyboardFocused)
selectedContainer.Focus();
}
else
{
// If we don't have a selection - just focus the treeview
#this.Focus();
}
}
}
Some reflection is needed since this interacts with a private field that is not otherwise exposed from the TreeView class, but as work-arounds go, this is a lot less invasive than what I tried at first, which was importing the entirety of the TreeView class (and related types) from Reference Source into my project in order to alter the one member. :-)
I have two buttons, back and next:
By.XPath("/html/body/div/div[3]/main/div/div/form/div[1]/div[2]/div[1]/nav/div/button[1]")
By.XPath("/html/body/div/div[3]/main/div/div/form/div[1]/div[2]/div[1]/nav/div/button[2]")
First goes to previous page, second goes to the next page of my list. When I open my page, first button will be disabled until I get to another page or both will be disabled if my list is short or emty. I need to click those buttons if they are not disabled. Only diference between disabled and not is class attribute:
class="disabled btn btn-plain btn-default-hover"
class="btn btn-plain btn-default-hover"
So how can I check if buttons class atribute contains 'disabled'? scenario goes like this - if second button active click 'next' and then if first button active click 'back'
//el is the web element
if(el.getAttribute("class").split(" ").contains("disabled"))
{
//your code
}
Let's say you have two buttons with the ids "button1" and "button2"..
You can check with something like this:
if(document.getElementById("button1").className.indexOf("disabled") > 1) {
// what to do if disabled...
} else {
// what to do if active...
}
And of course, you can do the same for the other button...
by using jquery write the following code
var ClassAtttr = $("#YourElementId").attr("class");
if (ClassAtttr.indexOf('Your Expression'))
{
//do somthing
}
Why not try the '.Enabled'
WebElement backButton = driver.FindElement('Your Locator');
if(backButton.Enabled)
{
'Your action to be performed
}
I'm using C# in VS2005. For my application I need to create four radio buttons. My form looks like:
A(Radio Button)
B(Radio Button)
C(Radio Button)
D(Radio Button)
Submit (Button)
When a user clicks the submit button I need to know which radio button is checked. How can I determine this?
I would add all the radio buttons to a List<RadioButton> which would help you innumerate through them when the submit is checked to figure out which one is checked.
You can use the Checked Property of a RadioButton to see if it is checked:
bool isChecked = radA.Checked;
I often use the following helper function to get exactly the RadioButton which is checked:
public RadioButton GetCheckedRadioButton(Control container)
{
if (container == null) {
return null;
}
else if (container is RadioButton) {
return GetCheckedRadioButton(container.Parent);
}
else {
foreach (Control childControl in container.Controls) {
if (childControl is RadioButton) {
RadioButton radioBtn = (RadioButton) childControl;
if (radioBtn.Checked) {
return radioBtn;
}
}
}
return null;
}
}
Then, you can simply call this function using one of your controls or it's container, and do a switch statement, as such:
switch(GetCheckedRadioButton(radA)) {
case radA:
// radA is checked
break;
case radB:
// radB is checked
break;
}
Personally, I find it less verbose than the usual:
if(radA.Checked) {
//radA is checked
}
else if(radB.Checked) {
//radB is checked
}
If you know for sure that you will only need 4 RadioButtons, then I'd just write code similar to this.
if (Radio1.Checked) ...
if (Radio2.Checked) ...
if (Radio3.Checked) ...
...
If you know that only one of them can be checked at the same time (using a group box or some other mechanism) then you can optimise this by using "else if" instead.
However if there is a possibility that you will need more, this can get wasteful, so I agree with other answers, you should put them in a collection of your choice and use it to loop through them, to see which ones are checked.
Is there a straighforward way to set additional text to appear in a tooltip when a user's mouse is held over an item in a CheckedListBox?
What I would expect to be able to do in code is:
uiChkLstTables.DisplayOnHoverMember = "DisplayOnHoverProperty"; //Property contains extended details
Can anyone point me in the right direction to do this? I've already found a couple of articles that involve detecting which item the mouse is currently over and creating a new tooltip instance, but this sounds a little too contrived to be the best way.
Thanks in advance.
Add a Tooltip object to your form and then add an event handler for the CheckedListBox.MouseHover that calls a method ShowToolTip();
Add MouseMove event of your CheckedListBox which has the following code:
//Make ttIndex a global integer variable to store index of item currently showing tooltip.
//Check if current location is different from item having tooltip, if so call method
if (ttIndex != checkedListBox1.IndexFromPoint(e.Location))
ShowToolTip();
Then create the ShowToolTip method:
private void ShowToolTip()
{
ttIndex = checkedListBox1.IndexFromPoint(checkedListBox1.PointToClient(MousePosition));
if (ttIndex > -1)
{
Point p = PointToClient(MousePosition);
toolTip1.ToolTipTitle = "Tooltip Title";
toolTip1.SetToolTip(checkedListBox1, checkedListBox1.Items[ttIndex].ToString());
}
}
Alternately, you could use a ListView with checkboxes instead. This control has
builtin support for tooltips.
Contrived or not; that's what there is...
I'm not aware of an easier way than you have already described (although I'd probably re-use a tooltip instance, rather than creating new all the time). If you have articles that show this, then use them - or use a 3rd party control that supports this natively (none leap to mind).
I would like to expand upon Fermin's answer in order to perhaps make his wonderful solution slightly more clear.
In the form that you're working in (likely in the .Designer.cs file), you need to add a MouseMove event handler to your CheckedListBox (Fermin originally suggested a MouseHover event handler, but this did not work for me).
this.checkedListBox.MouseMove += new System.Windows.Forms.MouseEventHandler(this.showCheckBoxToolTip);
Next, add two class attributes to your form, a ToolTip object and an integer to keep track of the last checkbox whose tool tip was shown
private ToolTip toolTip1;
private int toolTipIndex;
Finally, you need to implement the showCheckBoxToolTip() method. This method is very similar to Fermin's answer, except that I combined the event callback method with the ShowToolTip() method. Also, notice that one of the method parameters is a MouseEventArgs. This is because the MouseMove attribute requires a MouseEventHandler, which then supplies MouseEventArgs.
private void showCheckBoxToolTip(object sender, MouseEventArgs e)
{
if (toolTipIndex != this.checkedListBox.IndexFromPoint(e.Location))
{
toolTipIndex = checkedListBox.IndexFromPoint(checkedListBox.PointToClient(MousePosition));
if (toolTipIndex > -1)
{
toolTip1.SetToolTip(checkedListBox, checkedListBox.Items[toolTipIndex].ToString());
}
}
}
Run through your ListItems in your checkbox list of items and set the appropriate text as the item 'title' attribute, and it will display on hover...
foreach (ListItem item in checkBoxList.Items)
{
//Find your item here...maybe a switch statement or
//a bunch of if()'s
if(item.Value.ToString() == "item 1")
{
item.Attributes["title"] = "This tooltip will display when I hover over item 1 now, thats it!!!";
}
if(item.Value.ToString() == "item 2")
{
item.Attributes["title"] = "This tooltip will display when I hover over item 2 now, thats it!!!";
}
}