Coded UI test fails to find component in WPF application - wpf

I'm trying to run a coded UI test on our application. I can record the actions OK, but when attempting to playback, I get
Microsoft.VisualStudio.TestTools.UITest.Extension.UITestControlNotFoundException:
The playback failed to find the control with the given search properties.
Additional Details:
TechnologyName: 'UIA'
FrameworkId: 'Wpf'
ControlType: 'MenuItem'
AutomationId: 'MenuItemConnectId'
When I run Snoop on the application, I see the AutomationId exists
The one odd thing about our application is a lot of the ID's are added with code behind
menuItem.SetValue(AutomationProperties.AutomationIdProperty, "MenuItemConnnectId");
menuItem.SetValue(AutomationProperties.NameProperty, "MenuItemConnect");
Any ideas why this may be failing?
Thanks.

I think there are two reasons:
1.Maybe the component can't find the property.You can see the details in the xxx.Designer.cs file.
In the method SearchProperies[].....
2.The road to search the component is broken.You can see the details in the UI control map.Maybe the the component's parent is wrong.In this situation,you can add the code to connect them.

Turns out I needed the title of the window to be set. Even though I had the Automated ID and name properties set, looks like the engine uses the window's title in order to find it on the desktop. A few more details are here:
MSDN question on Coded UI test fails to find Window (Component)

Related

How to handle Solutions, Projects and their contents in a VisualStudio extension

In short:
I'm new to VisualStudio Extensibility and my goal is to create an extension with a ToolWindow (which already works) showing different views for each context of a VisualStudio solution, i. e. a view for the solution, a view for a project etc.. The window should be opened by clicking on a context menu entry in the context menus of the Solution Explorer, Class View, Object Browser and (ideally) any other window showing contents like projects, namespaces, classes etc..
After searching I found a lot of information, but for some points I couldn't find very helpful information. How do I ...
... create a context menu item for the VisualStudio views?
... get the currently open solution as an instance in code?
... get the projects of the solution and their contens as instances in code?
... add/remove items to/from a solution/project/class/... in code?
... react to selection changes in the Solution Explorer?
What I've done, so far:
I read the docs for Starting to Develop Visual Studio Extensions and downloaded the VSSDK-Extensibility-Samples. Especially the WPF_Toolwindow example was interesting for my purposes, so I built and ran it, which was successful, so far. Another interesting sample would have been the WPFDesigner_XML, but it always throws a NullReferenceException, so I decided to stick with the former ToolWindow, which is completely fine, for now.
Furtermore, I tried to understand the example by having a close look at each file in the project, running it in the debugger and analyzing what happened. I'm confident I understood it, but am also open for corrections of my possibly misguided thoughts following.
Now, I have created a new project, based on the WPF_Toolwindow sample, renamed and adapted to my needs (basically, I created new GUIDs, renamed the namespaces and removed things I won't use). This extension still works in the debugger. I even uninstalled everything from the experimental instance and debugged the extension from scratch.
What I try to achieve:
Have the ToolWindow load a specific view/viewmodel, when the selection changes in the Solution Explorer (or any other VisualStudio view). Alternatively, there should be a context menu item for every node's context menu in the Solution Explorer tree (or any other VisualStudio view).
Get the currently open solution, the containing projects and basically everything from the Solution Explorer's content as instances processable in my viewmodel. I need to properly add/remove
classes/structs/enums to/from
a folder in a project
a namespace
properties/fields to/from a class/struct
Generate code based on information of the solution and add the file properly to a project.
Does anyone know of examples for something like this or can anyone give me some hints, where I can find further information? Any help would be appreciated. Thanks in advance.
(1) The items already have a context menu and I want to add a new command to this menu.
if you want to add a sub menu to the context menu, the following link provide a complete sample
https://github.com/visualstudioextensibility/VSX-Samples/tree/master/CommandSubmenu
(3) Yes, basically adding a file to a project without manually manipulating the project file would be nice.
You can add the file to project via Project.ProjectItems.AddFromFile, and the following provide a sample for your reference.
https://www.mztools.com/Articles/2014/MZ2014009.aspx
Update:
I select a project and a similar event is fired. Are there such events I can subscribe to?
You could use IVsMonitorSelection to implement. here is the code which retrieve related project path for your reference.
IntPtr hierarchyPointer, selectionContainerPointer;
Object selectedObject = null;
IVsMultiItemSelect multiItemSelect;
uint projectItemId;
IVsMonitorSelection monitorSelection =
(IVsMonitorSelection)Package.GetGlobalService(
typeof(SVsShellMonitorSelection));
monitorSelection.GetCurrentSelection(out hierarchyPointer,
out projectItemId,
out multiItemSelect,
out selectionContainerPointer);
IVsHierarchy selectedHierarchy = Marshal.GetTypedObjectForIUnknown(
hierarchyPointer,
typeof(IVsHierarchy)) as IVsHierarchy;
if (selectedHierarchy != null)
{
ErrorHandler.ThrowOnFailure(selectedHierarchy.GetProperty(
projectItemId,
(int)__VSHPROPID.VSHPROPID_ExtObject,
out selectedObject));
}
Project selectedProject = selectedObject as Project;
string projectPath = selectedProject.FullName;
For more information about the usage, please refer to:
https://www.mztools.com/articles/2007/mz2007024.aspx

Are there any tools for recording web browser events for seleniumn2?

I am looking for something very simple. It can use the Selenium IDE recording tool, but it does not allow me to pick what kind of locators I get.
I want to use:
driver.findElement(By.className(str))
to locate things. All I need is something which watches which UI elements on a web page get clicked and writes out the class attributes of those tags.
If I use the Selenium IDE recording (and export to the right type of thing), I get:
#Test
public void testNav() throws Exception {
driver.get(baseUrl + "/");
driver.findElement(By.name("3.1.1.5.1.1")).clear();
driver.findElement(By.name("3.1.1.5.1.1")).sendKeys("dan");
driver.findElement(By.name("3.1.1.5.1.5")).click();
driver.findElement(By.linkText("Products")).click();
driver.findElement(By.linkText("Categories")).click();
driver.findElement(By.linkText("Create a Category")).click();
driver.findElement(By.linkText("Cancel")).click();
driver.findElement(By.linkText("Products")).click();
driver.findElement(By.cssSelector("a.DisplayAdminProductsLink")).click();
driver.findElement(By.linkText("Product1")).click();
There are problems with this. First, it is not give me any By.className() calls. Why? Those first 3 calls will not help me. The framework I am using puts arbitrary things into the name. How can I get it to see the class attribute?
There actually are unique words in the class attribute of all of the above tags. I design my apps so that this is so. Yet it will not use them.
Earlier I asked:
Why is it doing a "driver.findElement().click()"? This is fragile and does not
end up working.
What I need is:
elt = driver.waitFor(By.className("c")); elt.click();
This will work reproducibly.....
I am considering to be removed from the question, as the findElement() code does work. You need to set a general time-out on the driver. It is not very obvious that this can be done, but it can.
So, continuing on....
I can go to the "Options" and change the order of the "Locator Builders" in eclipse. I can put "css" at the top. Then I get:
driver.findElement(By.cssSelector("input[name=\"3.1.1.5.1.1\"]")).clear();
driver.findElement(By.cssSelector("input[name=\"3.1.1.5.1.1\"]")).sendKeys("dan");
driver.findElement(By.cssSelector("input[name=\"3.1.1.5.1.5\"]")).click();
The tags are like:
<input class="form-control LoginUsernameField" ... />
But it does not see the class attribute.... Or I can do this manually.
Selenium looks for a unique identifier to identify elements in a webpage. classNames are a very less desired option for this purpose as they are generally not unique. Ids and names on the other hand are generally unique. This might be the reason why Selenium IDE is not selecting classNames and going for other identifiers.
Selenium IDE records user actions. You would have clicked on the element for Selenium IDE to identify it and that is why you are getting driver.findElement().click().
If you want to wait for element to wait you can try implicit wait.
When you want to use driver.findElement(By.className(str)), are you sure that there is one and only one element in the webpage that is associated with a className? If that is the case you can modify the webdriver code manually to use className.

need to create a custom control

I have below requirement:
I wanted to create a custom control in which developer should be able to access below three properties.
Label:
IsRequired
content.
Example 1:
Name(Label): TextBox/any input control(Content)
Example 2:
Name(Label)*(IsRequired): TextBox/any input control(Content)
Developer should be able to apply globalization to the Label
If the field is required then he should be able to set a property
to enable * symbol
Developer should be able set any input control as a content of the control.
I request your suggestions, if you send me a sample code that would be good for me.
This demo doesn't seem latest but should be a good start. Googling around a bit more with the keywords found in the demo will also yield some relevant results.

adding controller later

I'm trying to create an NG app where parts can be enabled/disabled dynamically. The idea is to have an "admin" page, where parts of the app can be enabled or disabled, and then see new functionality appear, in the form of an adjusted menu at the top of the page, and matching routes, controllers, etc loaded into the app (I'm using SocketStream w/ NG).
The first step was to add / remove routes dynamically, for which I found a solution at https://stackoverflow.com/a/13173667 - working well, as far as I can tell.
Next, adding items to the menu bar - easy with ng-repeat on ul/li items.
So the app adjusts its menu and recognizes the corresponding route. So far so good.
The problem comes with registering a controller. I'm calling myApp.controller('SandboxCtrl',[...]) with proper args (same as what worked when initialising statically on startup), but the controller does not appear to get loaded or inited properly. Navigating to the newly added route generates errors such as:
Error: Argument 'SandboxCtrl' is not a function, got undefined
assertArg#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:973
assertArgFn#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:984
#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:4638
update#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:14007
$broadcast#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:8098
#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:7258
wrappedCallback#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:6658
wrappedCallback#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:6658
#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:6695
$eval#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:7848
$digest#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:7713
$apply#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:7934
#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:5433
I'm currently at a loss on how to proceed. I've not been able to find a solution on the web. The app is too large to put in a jsFiddle, but I can commit the last changes on GitHub if needed.
Questions: is this feasible? what can I do to debug this? any examples I could look at?
EDIT: The code is now at https://github.com/jcw/housemon (needs node/npm/redis). It's easy to reproduce the problem: launch with "npm start", browse to localhost:3333, go to admin tab, click on "jcw-sandbox" and then "Install". Top menu will update with new a "Sandbox" entry. Clicking on that entry generates the error shown above.
Oh, almost forgot: relevant code is in client/code/app/main.coffee and client/code/modules/routes.coffee ...
The answer turns out to be two-fold:
the NG calls were made from SocketStream RPC callbacks, and had to be wrapped in $scope.$apply calls - my bad, didn't know about this SS/NG interaction
the rest of the solution was outlined by #matys84pl - pick up $controllerProvider (and $filterProvider) early on, so they can be called at a later time instead of the normal "app.controller" and "app.filter" members, which don't seem to work anymore later on
Example code in GitHub, I'll link to a specific commit so this answer stays valid:
https://github.com/jcw/housemon/commit/f199ff70e3000dbf57836f0cbcbb3306c31279de

HelperProvider always open the index file

I want to build a context sensitive help for a winforms application, to do this I use a class with a reference to the HelperProvider component, HelpNamespace is set to the index html file and when a form is loaded I register each control in the form to the helperprovider with a topic that I get from a config file :
helpProvider.SetShowHelp(control, true);
helpProvider.SetHelpNavigator(control, helpNavigator);
helpProvider.SetHelpKeyword(control, helpKeyword);
when debugging I am sure that some controls are configured with some topics different from index file but when running and pressing F1 its always the index file (HelpNamespace) that is opened. When using a HelperProvider instance for each control and no single instance for all controls, that works fine!
Why I can't use a single instance of helperProvider for all controls?
You need SetHelpKeyword for each control. A HelpNavigator.TopicId may be useful for a CHM with topic ID's inside.
I'm missing ".Topic" in your code sample above. Try the code below or download a working example from:
http://www.help-info.de/files_download/CSharp2008_CHM.zip
// set F1 help topic for controls on this form
helpProvider1.SetHelpNavigator(this.btnStart, HelpNavigator.Topic);
helpProvider1.SetHelpKeyword(this.btnStart, #"/Garden/flowers.htm");
helpProvider1.SetHelpNavigator(this.btnExit, HelpNavigator.Topic);
helpProvider1.SetHelpKeyword(this.btnExit, #"/Garden/tree.htm");
helpProvider1.SetHelpNavigator(this.chkShowHelpWithNavigationPane, HelpNavigator.Topic);
helpProvider1.SetHelpKeyword(this.chkShowHelpWithNavigationPane, #"/HTMLHelp_Examples/jump_to_anchor.htm#AnchorSample");

Resources