I trying to create simple test that runs my application and clicks some button using CodedUI.
First I trying to find the main window, that has ControlName - "LoginForm". This is my code:
[TestMethod]
public void CodedUITestMethod()
{
var app = ApplicationUnderTest.Launch(#"C:\Program Files (x86)\application.exe");
var loginWindow = new WinClient(app);
loginWindow.SearchProperties.Add(loginWindow.ControlName, "LoginForm");
When I run it in debugger, the loginWindow object contains an error:
The property SplashForm is not a valid search property.
What could be the problem?
Redo your SearchProperties line like this:
loginWindow.SearchProperties[WinClient.PropertyNames.ControlName] = "LoginForm";
Related
I'm trying to click a button on an external windows application. The following code successfully finds the element, brings the parent window into focus and then "manually" clicks the button
This works okay...
Process tProcess = Process.GetProcesses().FirstOrDefault(x => x.MainWindowTitle.StartsWith("MainWindowName"));
if (tProcess != null)
{
TestStack.White.Application application = TestStack.White.Application.Attach(tProcess.Id);
var tWindow = application.GetWindow(SearchCriteria.ByAutomationId("SubWindowName"), InitializeOption.NoCache);
SearchCriteria searchCriteria = SearchCriteria.ByAutomationId("btnCalibrate");
var calibrateBtn = tWindow.Get<TestStack.White.UIItems.Button>(searchCriteria);
tWindow.Focus();
var clickablePoint = calibrateBtn.AutomationElement.GetClickablePoint();
Mouse.Instance.Click(clickablePoint);
}
The problem with this is that Mouse.Instance.Click(clickablePoint); moves the cursor, ideally I don't want the cursor moved.
My initial code tried to click the button directly using the following
Process tProcess = Process.GetProcesses().FirstOrDefault(x => x.MainWindowTitle.StartsWith("MainWindowName"));
if (tProcess != null)
{
TestStack.White.Application application = TestStack.White.Application.Attach(tProcess.Id);
var tWindow = application.GetWindow(SearchCriteria.ByAutomationId("SubWindowName"), InitializeOption.NoCache);
SearchCriteria searchCriteria = SearchCriteria.ByAutomationId("btnCalibrate");
var calibrateBtn = tWindow.Get<TestStack.White.UIItems.Button>(searchCriteria);
tWindow.Focus();
calibrateBtn.Click();
}
but this gives the following error every time
TestStack.White.AutomationException
HResult=0x80131500
Message=Cannot perform action on Button. AutomationId:btnCalibrate, Name:Calibrate, ControlType:button, FrameworkId:WinForm,
Source=TestStack.White
StackTrace:
at TestStack.White.UIItems.UIItem.PerformIfValid(Action action) in c:\TeamCity\buildAgent\work\89a20b30302799e\src\TestStack.White\UIItems\UIItem.cs:line 254
at TestStack.White.UIItems.UIItem.Click() in c:\TeamCity\buildAgent\work\89a20b30302799e\src\TestStack.White\UIItems\UIItem.cs:line 231
at BetfairStreamingAPI.RadForm1.radLabelBetTime_Click(Object sender, EventArgs e) in D:
Does anyone know why the second method is throwing this error and if it's possible to fix this so that the button can be clicked without manually moving the cursor?
Edit: Screenshot of attempt to set togglestate
The solution to this particular problem appears to be use .RaiseClickEvent() instead of .Click()
The following code works
Process tProcess = Process.GetProcesses().FirstOrDefault(x => x.MainWindowTitle.StartsWith("MainWindowName"));
if (tProcess != null)
{
TestStack.White.Application application = TestStack.White.Application.Attach(tProcess.Id);
var tWindow = application.GetWindow(SearchCriteria.ByAutomationId("SubWindowName"), InitializeOption.NoCache);
SearchCriteria searchCriteria = SearchCriteria.ByAutomationId("btnCalibrate");
var calibrateBtn = tWindow.Get<TestStack.White.UIItems.Button>(searchCriteria);
calibrateBtn.RaiseClickEvent();
}
It's not entirely clear from the White docs when/why this is preferred. I found method RaiseClickEvent this on this link https://github.com/TestStack/White/commit/7b6d4dbc0008c3375e2ebf8810c55cb1abf91b60
EDIT2
I think you might have found something interesting. Since your button state is Indeterminate, it could be worth turning it on before clicking it:
calibrateBtn.State = ToggleState.On;
EDIT1
Alright, let's sort this out together.
There are only two reasons for that action to fail:
The button is not enabled, which I guess can't be the case
The button is OffScreen
If you do something like
Console.WriteLine(calibrateBtn.IsOffScreen.ToString());
You should see
true
If so, try this before you click it:
var pattern = calibrateBtn.AutomationElement.GetCurrentPattern(System.Windows.Automation.InvokePattern.Pattern);
(pattern as System.Windows.Automation.InvokePattern).Invoke();
I tried to use white to click the new project button, I try using the below code, but it can not work, anyone can help me?
public void Notepad()
{
Application app = Application.Launch("C:\\Program Files (x86)\\SourceMonitor\\SourceMonitor.exe");
Window window = app.GetWindow("SourceMonitor", InitializeOption.NoCache);
Button button = window.Get<Button>("File");
button.Click();
app.Kill();
}
I already figured out how to do it, below is the correct code:
public void Notepad()
{
// Arrange
Application app = Application.Launch("C:\\Program Files (x86)\\SourceMonitor\\SourceMonitor.exe");
Window window = app.GetWindow("SourceMonitor", InitializeOption.NoCache);
// Act
MenuBar menuBar = window.MenuBar;
menuBar.MenuItem("File","New Project").Click(); ; //can use any other search criteria as well.
}
I have a requirement to capture the screen shot of the opened dialog with a particular html control highlighted ( whose static id is given ). currently I Implemented the code following manner :
public void Snapshot()
{
Image currentImage = null;
currentImage = GetOpenedDialogFrame().CaptureImage();
}
public UITestControl GetOpenedDialogFrame()
{
var dialogsFrames = new HtmlDiv(this.BrowserMainWindow.UiMobiControlDocument);
dialogsFrames.SearchProperties.Add(new PropertyExpression(HtmlControl.PropertyNames.Class, "mcw-dialog", PropertyExpressionOperator.Contains));
var dialogs = dialogsFrames.FindMatchingControls();
if (dialogs.Count == 0)
{
return null;
}
return dialogs[dialogs.Count - 1];
}
Now I have to write the code to highlight the particular html control while taking a screenshot. The DrawHighlight() method of Microsoft.VisualStudio.TestTools.UITesting.dll does not take any parameter so how can I highlight a particular html control in the screenshot.
DrawHighlight() is a method of a UI Control. It could be used in this style:
public void Snapshot()
{
Image currentImage = null;
var control = GetOpenedDialogFrame();
// TODO: protect the code below against control==null.
control.DrawHighlight();
currentImage = control.CaptureImage();
}
Whilst that answers your question about DrawHighlight, I am not sure it will achieve what you want. Please see this question the Microsoft forums where they are trying to do a similar screen capture.
Why not simply user the playback settings:
Playback.PlaybackSettings.LoggerOverrideState = HtmlLoggerState.AllActionSnapshot;
This will produce the html log file with all the screenshots that your codedui test went threw.
After searching for the matching controls you can try to highlight each one of them.
something like:
foreach( var control in controls)
{
control.drawhighlight();
}
that way you'll be able to which controls are located by the playback(qtagent to be more precise). furthermore this will help you decide which instance to refer to. (run and wait to see which controls are highlighted, pick the one you need and hard code it to be part of the test).
so after the test run you'll end up with something like:
var dialogs = dialogsFrames.FindMatchingControls();
dialogs[desiredLocation].drawhighlight();
hope this helps.
I am having trouble causing an 'autohide' dock to appear programmatically.
Couldn't find any answer around the net, though the following SO Question suggested that .Show() should have done the trick
I've tried this on the latest NuGet version of the code.
My test code is below.
Anyone know how to do it? or what I'm doing wrong?
Update: apparently this is a bug in 2.7.0, I've opened an issue for it with the project.
#roken's answer is an excellent workaround, so I've updated the code below to reflect it.
My test Code
Create a simple Visual Studio Windows Form application, and replace the main form's source file content with this code:
using System;
using System.Windows.Forms;
using dps = WeifenLuo.WinFormsUI.Docking;
namespace testDockPanel
{
public partial class Form1 : Form
{
private dps.DockPanel dockPanel;
private dps.DockContent dc;
private Control innerCtrl;
public Form1()
{
InitializeComponent();
dockPanel = new dps.DockPanel();
dockPanel.Dock = DockStyle.Fill;
dockPanel.DocumentStyle = dps.DocumentStyle.DockingWindow;
toolStripContainer1.ContentPanel.Controls.Add(dockPanel);
dc = new dps.DockContent();
dc.DockPanel = dockPanel;
dc.DockState = dps.DockState.DockRightAutoHide;
innerCtrl = new WebBrowser() { Dock = DockStyle.Fill };
dc.Controls.Add( innerCtrl );
This is the part of the code that didn't work:
// This SHOULD show the autohide-dock, but NOTHING happens.
dc.Show();
I've replaced it with #roken's suggestion and it now works:
dockPanel.ActiveAutoHideContent = dc;
innerCtrl.Focus(); // This is required otherwise it will autohide quickly.
}
}
}
To show a hidden autohide content, you can set the active auto content directly:
dockPanel.ActiveAutoHideContent = dc;
It's not clear to me if the inability to activate the content via Show() is a bug that has been introduced. If you have a free moment could you try running the code you provided against version 2.5.0 to see if Show() activates the content like you expect?
I have a winforms application.
I have a textbox on one form (call F1) and when a button is clicked on this form (call F2), it launches another form.
On F2, I want to set a string via a textbox (and save it to a variable in the class), and then when I close this form, the string will appear in a label in F1.
So I am basically sharing variables between both forms. However, I can't get this to work correctly. How would this code look?
I would add a new property to form2. Say it's for a phone number. Then I'd add a friend property m_phone() as string to form 2. After showing an instance of form2 but before closing it, you can refer to the property m_phone in form1's code.
It's an additional level of indirection from Matthew Abbott's solution. It doesn't expose form2 UI controls to form1.
EDIT
e.g.:
public string StoredText
{
get;
private set;
}
inside the set you can refer to your UI control, like return textBox1.text. Use the get to set the textbox value from an earlier load.
And:
public string GetSomeValue()
{
var form = new F2();
form.ShowDialog();
return form.StoredText;
}
Just ensure that StoredText is populated (or not, if appropriate) before the form is closed.
Are you showing the second form as a dialog, this is probably the best way to do it. If you can avoid doing shared variables, you could do the following:
public string GetSomeValue()
{
var form = new F2();
form.ShowDialog();
return form.TextBox1.Text;
}
And called in code:
Label1.Text = GetSomeValue();
This might not be the most efficient way of approaching, but you could create a class called DB (database). Inside this class, create variables like
public static bool test or public static bool[] test = new bool[5];
In your other forms, you can just create an instance. DB db = new DB(); then grab the information using db.test = true/false. This is what I've been doing and it works great.
Sorry, I'm only like a year late.