I am working on a, hand coded, Coded UI test for an application.
The application has a certain function that operates in 2 windows. When a button is clicked, a new window appears and then the user makes a selection upon which that window closes, and then the user continues taking actions on the main window.
With Selenium, I would handle that by iterating through all the window handles and switching by using passing it the URL of the page I wanted using the "driver.SwitchTo().Window(handle)" method. However, with Coded UI, I have not found a similar solution. Using the Process class I can do something similar that could work:
Process[] myList = Process.GetProcessesByName("iexplore");
foreach (Process item in myList)
if (item.MainWindowTitle.Contains("Window Title"))
{
item.Kill();
}
The problem is that the application that I am testing is poorly designed and all windows throughout the application have the same name, thus it will not work.
Is there a method which can be used to switch to a different window on Coded UI? Or what would be the best approach?
Take a look at this question, it might help: Interacting with multiple instances of an application in Coded UI
You don't do "switching" in CUIT, every window and control is accessed via a UITestControl object. If you want to do stuff on an other window you create a new object for it. If you can't differentiate the two windows with search properties you can use the Instance property or FindMatchingControls method.
To catch a window creation event you can use a winhook. It gives you the window handle of every window created. Using that you can find out if the window created is the window you are waiting for and then use the UITestControlFactory.FromWindowHandle to create a UITestControl for CUIT to interact with. If you have a generated class for that window you can create an instance of that class and call its CopyFrom method to pass to it the control you created from the window handle.
I am using:
public static HtmlDocument WaitForPopup(string popupName, string text)
{
BrowserWindow browser = new BrowserWindow();
browser.SearchProperties.Add(BrowserWindow.PropertyNames.Name, popupName,
PropertyExpressionOperator.Contains);
browser.WindowTitles.Add(popupName);
browser.WaitForControlExist();
browser.WaitForControlReady();
browser.SetFocus();
HtmlDocument html = new HtmlDocument(browser);
html.SearchProperties.Add(HtmlDocument.PropertyNames.InnerText, text,
PropertyExpressionOperator.Contains);
html.WaitForControlExist();
html.WaitForControlReady();
Playback.Wait(1000);
return html;
}
Just call WaitForPopup("your window name", "some constant text in window") and continue with tests there.
Note that this method will return html of the new window and you can use it further on.
Related
We have a kiosk mode application for Windows Mobile 5 that was going strong for a year at least in production. It uses window subclassing through the SetWindowLong windows API function to override the behavior of the taskbar to prevent users from ever leaving our application or other explicitly allowed applications.
My callback overrides the handling of a few window messages and calls the default handler for other messages. This is done by storing the previous function pointer returned by SetWindowLong, and using it inside of the new function by calling CallWindowProc on it.
Then we had to update the application to be compatible with Windows Mobile 6.5.3, and started having a bunch of problems. I followed this article to disable the bottom menu buttons which are new on 6.5. On a single application, it works fine and the menu respects my callback. As soon as the user opens up another application through ours, that window seems to be recreated, and I had to devise a mechanism to detect foreground window changes and then "resubclass" the window again.
In my code, I don't have control of when exactly this window is recreated, so my first attempt was to use the GetWindowLong function to obtain the current callback address and test it against my own function address. I learned the hard way that I can't just compare the values like that, since it does not always return the function pointer.
Because I'm not able to test if my method is the current handler that way, I end up sometimes setting my method as the handler, and the previous handler is also my own method (in this case, the window was not recreated and thus already had my method set). This results in an infinite loop, since my callback ends up calling itself indefinitely.
How can I know if my custom function is the one being used by a certain window, so that I can avoid this infinite recursion?
Don't use SetWindowLong(GWL_WNDPROC) to subclass a window. Use SetWindowSubClass() instead (like Raymond Chen said):
Subclassing Controls
Safer subclassing
Amongst providing safer subclassing semantics (such as allowing multiple subclasses at a time), it also allows you to associate user-defined data with each subclass. So you could use GetWindowSubclass() to check if you have already subclassed the window or not.
Or, you could simply keep track of whether or not you have already subclassed the window. A simple boolean variable will suffice. Once your subclass is in place, you MUST remove the subclass before the window is fully destroyed. So, for instance, when the subclass receives the WM_NCDESTROY message, you can remove the subclass and clear your boolean at the same time, and then the next time you see the window again your boolean will tell you that you need to subclass the window.
Send the custom message to window. Handle this message in your custom function to return some value that will indicate that it was your custom handler.. and so on.
if(SendMessage(hwnd, mymsg, 0, 0) != myvalue)
;// It's not your handler
I've got a VS editor extension, and when the user performs a certain action, I'd like to send them to a specific location in the code- not unlike Go To Definition or what happens when you click on a stack frame in the debugger.
So far, I used dte.ItemOperations.OpenFile to open the actual file, and I have the relevant ITextDocument, but I don't know how to set the view to the relevant place in the file. It seems like ITextView and IVsTextView and friends have the methods that I need but I'm unsure how to get the instances I need from my ITextDocument.
How can I go to the file and location I want from a VS extension?
The easiest way to do this is to take the return of ItemOperations.OpenFile and navigate from it to the IWpfTextView
IWpfTextView GetWpfTextViewForDteWindow(
Window window,
System.IServiceProvider serviceProvider,
IVsEditorAdaptersFactoryService vsEditorAdaptersFactoryService)
{
var path = Path.Combine(window.Document.Path, window.Document.Name);
IVsUIHierarchy vsuiHierarchy;
uint itemID;
IVsWindowFrame vsWindowFrame;
if (VsShellUtilities.IsDocumentOpen(
serviceProvider,
path,
Guid.Empty,
out vsuiHierarchy,
out itemID,
out vsWindowFrame))
{
// Note this may have multiple IVsTextView instances associated with it in a split window but
// this will retrieve at least one
var vsTextView = VsShellUtilities.GetTextView(vsWindowFrame);
var wpfTextView = vsEditorAdaptersFactoryService.GetWpfTextView(vsTextView);
return wpfTextView;
}
return null;
}
Do note that there is not necessarily a 1-1 mapping between a DTE Window object and ITextView instance. The Window object essentially represents what is visually displayed as a tab and a given tab can contain many ITextView instances. The most common case is when there is a horizontal split in the window. Probably doesn't matter too much for this scenario but wanted to make sure that it got called out
Is there a way to create/enable having multiple windows using "command + n" in a non document based application? I want to have unlimited instance of that window (not actually unlimited, but might be 6-7 instances) using command + n
Or I have to create a document based app and port all my code in new project template is the only solution?
I can see the menu button for "New" is disabled right now.
A few ways to do this.
First connect the New menu item to an IBAction method.
Name the method whatever makes sense to you.
Next, you will want to add some kind of property to your controller ( app delegate for simplicity ) that is basically a window stack only storing a reference to each window or window controller. NSMutableArray should do nicely.
Now you can do the next part a few ways, but I would recommend creating an NSWindowController subclass with a nib/xib (especially if these windows will have the same basic things in them).
Do what you want in the nib file.
Now in your IBAction method, create a new instance of your window controller class, add it to your mutable array. Tell it to load its window.
You only have to decide if the controller should be removed from the stack and set to nil if its window is closed.
Many ways to handle that, and up to your design to know what is correct.
Try this :-
NSWindowController *yourWindow=[[[[yourWindowController alloc]init]retain]autorelease];
[yourWindow loadWindow];
I'm working on a concept that works like copy & paste but uses my own algorithm instead of using the clipboard.
We have users that use many different programs that contain part numbers. This is how my concept would work.
User highlights part number from any application (word, excel, pdf, JDE, etc)
Either by hotkey or clicking on another application the user launches my routine.
My routine grabs that text from the original application and processes it accordingly.
I know how to use the clipboard to get text.
What I'm not sure of is how to get currently selected text from the application that was active prior to running my code? Do I need to force my user to copy to clipboard first and then run my app or can I create my own copy/paste type windows add-in?
Preferred VB for this but can also use C++ or C# if easier.
As to the question why, because we want to the action to be seamless to the user. There will be several behind the scenes actions that take place and then the user will be presented a browser with pertinent information related to that part number. Ultimately, I don't want an in-between screen to pop up, but rather completely hidden from the user. If I require them to copy and then run my routine then I'm adding in one extra step to the user path that I'm hoping to avoid.
I looked into right click menu context a bit but found that each program can have their own override. I wasn't able to locate a way to globally override all right click context menus to include a new action.
From this article:
var element = AutomationElement.FocusedElement;
if (element != null)
{
object pattern;
if (element.TryGetCurrentPattern(TextPattern.Pattern, out pattern))
{
var tp = (TextPattern) pattern;
var sb = new StringBuilder();
foreach (var r in tp.GetSelection())
{
sb.AppendLine(r.GetText(-1));
}
var selectedText = sb.ToString();
}
}
It's in C# but it should be pretty trivial to translate.
I have a main menu window. On clicking any menu item it opens a child window using window.open? I am writing automated test script for this using Watin. How do i write Test script for the child windows.
The Watin.Core.IE class has a static AttatchToIE method you can use. It takes a Watin.Core.Constraint object as an argument (i.e. you have to use Find.ById, Find.ByName, etc.) to help Watin find the window you are looking for, and it returns a reference to an IE object.
Example:
IE myIE = IE.AttatchToIE(Find.ByTitle("Child Window Title"));
From there you can use the myIE object to run your tests, make sure it loads, make sure it has the expected text, etc.