How do I grab hold of a pop-up that is opened from a frame? - testing

I am testing a website using WatiN.
On one of the pages I get a "report" in an Iframe, within this I frame there is a link to download and save the report. But since the only way to get to the link is to use frame.Link(...) the pop-up closes immediately after opening; Code snippet below
//Click the create graph button
ie.Button(Find.ById("ctl00_ctl00_ContentPlaceHolder1_TopBoxContentPlaceHolder_btnCreateGraph")).Click();
//Lets export the data
ie.Div(Find.ById("colorbox"));
ie.Div(Find.ById("cboxContent"));
ie.Div(Find.ById("cboxLoadedContent"));
Thread.Sleep(1000);//Used to cover performance issues
Frame frame = ie.Frame(Find.ByName(frameNameRegex));
for (int Count = 0; Count < 10000000; Count++) {double nothing = (Count/12); }//Do nothing I just need a short pause
//SelectList waits for a postback which does not occur.
try
{
frame.SelectList(Find.ById("rvReport_ctl01_ctl05_ctl00")).SelectByValue("Excel");
}
catch (Exception)
{
//Do nothing
}
//Now click export
frame.Link(Find.ById("rvReport_ctl01_ctl05_ctl01")).ClickNoWait();
IE ieNewBrowserWindow = IE.AttachTo<IE>(Find.ByUrl(urlRegex));
fileDownloadHandler.WaitUntilFileDownloadDialogIsHandled(150);
fileDownloadHandler.WaitUntilDownloadCompleted(200);
I have tried using ie instead of frame which is why all those ie.Div's are present.
if I use frame the pop-up window opens and closes instantly.
If I use ie I get a link not found error.
If I click on the link manually, while the test is "trying to find the link" the file will download correctly.
I have changed the code to use a different page that doe not have the frame and I still get the same problem download pop-up closes instantly.
[STAThread]
public void TestForMeterDataExport()
{
// Open a new Internet Explorer window and
// goto the website.
IE ie = new IE("https://<URL>", true);
FileDownloadHandler fileDownloadHandler = new FileDownloadHandler("C:\\Documents and Settings\\karnold\\Desktop\\MeterUsageReport_Large.xls");
Regex urlRegex = new Regex("<URL>\\?Mode=true&ReportID=[a-z A-Z 0-9]{30,33}&ControlID=[a-z A-Z 0-9]{30,33}&Culture=1033&UICulture=1033&ReportStack=1&OpType=Export&FileName=BuildingMeterDataReport&ContentDisposition=OnlyHtmlInline&Format=Excel");
//Find the Username text field and input the user ID
ie.TextField(Find.ByName("ctl00$ContentPlaceHolder1$txtUsername")).TypeText("<Name>");
//Find the Password text field and input the password
ie.TextField(Find.ByName("ctl00$ContentPlaceHolder1$txtPassword")).TypeText("PASS");
//Go ahead and login
ie.Button(Find.ByName("ctl00$ContentPlaceHolder1$butLogin")).Click();
//Let's use the Reports Tab
ie.Link(Find.ByUrl("https://<URL>")).Click();
// Let's get the meter data
ie.Link(Find.ByUrl("https://<URL>")).Click();
//Let's choose University of
ie.SelectList(Find.ById("ctl00_ctl00_ctl00_ContentPlaceHolder1_TopBoxContentPlaceHolder_TopBoxContentPlaceHolder_ucFacility_ddlFacility")).SelectByValue("5041");
//Set the date range for which we want to get data
ie.TextField(Find.ById("ctl00_ctl00_ctl00_ContentPlaceHolder1_TopBoxContentPlaceHolder_TopBoxContentPlaceHolder_DateRangePicker1_dpBeginDate_TextBox")).TypeText("12/09/10");
ie.TextField(Find.ById("ctl00_ctl00_ctl00_ContentPlaceHolder1_TopBoxContentPlaceHolder_TopBoxContentPlaceHolder_DateRangePicker1_dpEndDate_TextBox")).TypeText("12/10/10");
//Click the create report button
ie.Button(Find.ById("ctl00_ctl00_ctl00_ContentPlaceHolder1_TopBoxContentPlaceHolder_TopBoxContentPlaceHolder_btnSubmit")).ClickNoWait();
//Lets export the data
Thread.Sleep(2000);
//SelectList waits for a postback which does not occur.
try
{
ie.SelectList(Find.ById("ctl00_ctl00_ctl00_ContentPlaceHolder1_ContentAreaContentPlaceHolder_ContentAreaContentPlaceHolder_rvMain_ctl01_ctl05_ctl00")).SelectByValue("Excel");
}
catch (Exception)
{
ie.SelectList(Find.ById("ctl00_ctl00_ctl00_ContentPlaceHolder1_ContentAreaContentPlaceHolder_ContentAreaContentPlaceHolder_rvMain_ctl01_ctl05_ctl00")).FireEventNoWait("onchange");
//fire the postback event
}
//Now click export
ie.Link(Find.ById("ctl00_ctl00_ctl00_ContentPlaceHolder1_ContentAreaContentPlaceHolder_ContentAreaContentPlaceHolder_rvMain_ctl01_ctl05_ctl01")).ClickNoWait();
IE ieNewBrowserWindow = IE.AttachTo<IE>(Find.ByUrl(urlRegex));
fileDownloadHandler.WaitUntilFileDownloadDialogIsHandled(10);
fileDownloadHandler.WaitUntilDownloadCompleted(20);
}// close TestForMeterDataExport()
Hopefully some one can tell me what I am doing wrong. Thank you
Here is the error that I get when the program can't find the handle maybe it will help
TestCase 'M:WebTest.CommandLine.WatiNConsoleWebAndDB.TestForMeterDataExport'
failed: Error HRESULT E_FAIL has been returned from a call to a COM component.
System.Runtime.InteropServices.COMException (0x80004005): Error HRESULT E_FAIL has been returned from a call to a COM component.
at SHDocVw.IWebBrowser2.get_Document()
at WatiN.Core.Native.InternetExplorer.IEBrowser.get_NativeDocument()
at WatiN.Core.Native.InternetExplorer.IEWaitForComplete.WaitForCompleteOrTimeout()
at WatiN.Core.WaitForCompleteBase.DoWait()
at WatiN.Core.DomContainer.WaitForComplete(IWait waitForComplete)
at WatiN.Core.Native.InternetExplorer.AttachToIeHelper.FinishInitializationAndWaitForComplete(IE ie, SimpleTimer timer, Boolean waitForComplete)
at WatiN.Core.Native.InternetExplorer.AttachToIeHelper.Find(Constraint findBy, Int32 timeout, Boolean waitForComplete)
at WatiN.Core.Browser.AttachTo(Type browserType, Constraint constraint, Int32 timeout)
at WatiN.Core.Browser.AttachTo(Type browserType, Constraint constraint)
at WatiN.Core.Browser.AttachTo[T](Constraint constraint)
Web+DB_test_app.cs(139,0): at WebTest.CommandLine.WatiNConsoleWebAndDB.TestForMeterDataExport()

Thanks to Baptiste for the pointer.
//Set the handles and the file save as name
FileDownloadHandler handler = new FileDownloadHandler("MeterUsageReport_Large_Iframe.xls");
// add a watcher to look for the save file local
ie.AddDialogHandler(handler);
//Do not close dialog boxes immediately
ie.DialogWatcher.CloseUnhandledDialogs = false;
//create a single use instance that will be easily cleaned up and avoid having windows open after we are done with them
using (new UseDialogOnce(ie.DialogWatcher, handler))
{
//Now click export
frame.Link(Find.ById("rvReport_ctl01_ctl05_ctl01")).ClickNoWait();
//Grab hold of the poup dialog and download the file
handler.WaitUntilFileDownloadDialogIsHandled(30);
handler.WaitUntilDownloadCompleted(35);
}
Now for the fun this will only work if all of the work is done on localhost.
if you need to hit a server that is not local and ou want to use IE well then
2) You will need to edit the security for "trusted sites to allow scripting of downloads and Iframes.
* a) open IE
* b) Tools -> Internet options
* c) Security tab.
* d) make sure "trusted site" is highlighted
* e) click custom level, Make sure all .Net and .Net reliant components are set to enabled.
* f) Enable or prompt all activeX components
* g) Enable all downloads
* h) Enable .Net framework setup
* i) Enable scripting of web browser controls
* j) Enable allow websites to open windows without address's or status bars.
* k) Enable Launching programs or files from an Iframe.
* l) Everything under scripting is set to enabled or prompt.
* Just so you know, localhost is treated as a "low" security area so tests run on localhost do not need these changes.
* Refer to http://support.microsoft.com/kb/174360

Related

WinAppDriver having issues identify elements in a driver when the driver changes too much

For example: Launch Outlook on your desktop. Notice how there is a "splash loading screen" well the driver I have will look at this executable and wait x seconds before trying to click on the "New Email" button. However when it gets to the page where the new email button appears, it can't find it. Strange... hmm okay lets start the application but have it trigger the executable that is already in the process. It looks for the new email button and finds it no problem.
The only thing i can think of is that the driver loads the executable, the executable then changes its data drastically or something. Then all of a sudden i need to build a new driver. But I dont think this is the way to go about it.
[TestInitialize]
public void TestMethod1()
{
options.AddAdditionalCapability("app", #"C:\Program Files (x86)\<PATH>");
_driver = new WindowsDriver<WindowsElement>(new Uri("http://127.0.0.1:4723"), options);
System.Threading.Thread.Sleep(5000);
}
[TestMethod]
public void TEST()
{
LoginPage page = new LoginPage(new WindowsDriver<WindowsElement>(new Uri("http://127.0.0.1:4723"), options)); // Notice how i am building a new driver just for this page. This is VERY heavy.
page.Login("USERNAME", "PASSWORD");
}
You probably have the "splash screen issue".
Here's a explantation about what to do about it.
In short, winappdriver creates a new windowhandle for every new window it encounters. As the splash screen counts for a separate window, you should have 2 windowhandles available at the moment you wanted to click that "new email" button. The most recent windowhandle will be the highest index.
You can switch between windowhandles like this (copied from link):
// Return all window handles associated with this process/application.
// At this point hopefully you have one to pick from. Otherwise you can
// simply iterate through them to identify the one you want.
var allWindowHandles = session.WindowHandles;
// Assuming you only have only one window entry in allWindowHandles and it is in fact the correct one,
// switch the session to that window as follows. You can repeat this logic with any top window with the sameĀ²
// process id (any entry of allWindowHandles)
session.SwitchTo().Window(allWindowHandles[0]);
Also take a look at this answer. Could be useful too.

Can HTAs be used to automate web browsing?

I am new to HTAs. I just read https://msdn.microsoft.com/en-us/library/ms536496%28v=vs.85%29.aspx and am a bit confused.
Can I use HTAs to automate browsing? Say I want to download a web page and fill in a form automatically, i.e. from a script. How would an HTA help me do this, if at all? It's important that the JavaScript code in the downloaded page is run as usual. I should be able to enter somehow and fill in the form after it has finished initializing, just as if I were a human agent.
First, you need to open an IE window, as follows:
var IE = new ActiveXObject("InternetExplorer.Application");
Then navigate the IE window to the webpage you want:
IE.Navigate("www.example.com");
Wether your IE window is visible or invisible, it's up to you. Use Visible property to make it visible:
IE.Visible = true;
Then, you should wait until the webpage is completely loaded and then run a function that takes your desired actions. To do so, first, get the HTML document object from the webpage using Document property of IE object, then repeatedly check the readyState property of document object. In the code below, it is assumed that you have a function named myFunc, which takes your desired actions on the webpage. (For example, modifying the contents of the webpage.)
var doc = IE.Document;
interval = setInterval(function() {
try
{
if (doc.readyState == "complete")
{
myFunc();
clearInterval(interval);
}
}
catch (e) {}
}, 1000);
In the function myFunc, you can do anything you want with the webpage since you have HTML document object stored in doc variable. You can also use parentWindow property to get the HTML window object.

Listening for a file being clicked to - Eclipse Plugin

I am trying to write an Eclipse plugin where one of the features requires listening for when the user switches to another file in the editor via clicking.
For example, consider the screenshot below.
I want to know how to listen for when the user switching over to FakeClass.java via double-clicking on it in the Project Explorer or clicking on the tab in the editor. Furthermore, I would like to get information about the element that was clicked. Note that I am asking specifically about changing a file through the two means I asked above.
I am a beginner with Plugin development. It would be helpful to explain with that in mind. Thanks.
You can use an IPartListener to listen for changes to parts including a part being activated:
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
page.addPartListener(listener);
The partActivated method of the listener is probably what you want:
#Override
public void partActivated(final IWorkbenchPart part)
{
if (part instanceof IEditorPart) {
IEditorPart editor = (IEditorPart)part;
IEditorInput input = editor.getEditorInput();
IFile file = input.getAdapter(IFile.class);
if (file != null) {
// TODO handle file
}
}
}
I don't know of a way to tell why the part was activated.

Web browser control, modal window/popup to STAY INSIDE web browser control for Visual Studio 2015/Visual Basic 2015

this is the first time I'm posting a question here; I have searched and searched and searched here and other places and I cannot seem to get any results. I'm using VISUAL BASIC 2015 in Visual Studio 2015. QUESTION: I need to have a modal window/popup from a particular website remain INSIDE the web browser control/window on my form (WebBrowser1); when a particular link is clicked, the modal window/popup jumps out of the form and directly to the user on their screen. I have to keep this popup inside because there are other links to be clicked on that popup, but if it jumps out of the web browser control, no code will work since it's outside WebBrowser1. What I have found is code for older versions, and not 2015; if anything I can even add WebBrowser2 to have the popups/modal windows appear there if possible, just as long as I can code them to keep clicking inside the form. PLEASE HELP! THANK YOU!
window.open (and a click on <a target="_blank"> etc) can be handled via the NewWindow2 event. Hans already pointed out how to do that in comments. NewWindow3 works too, but need at least Windows XP SP2.
As for window.showModalDialog, it is a bit tricky. IE has IDispatchEx (wrapped as IExpando in .Net) implemented on scripting objects so you replace the methods and properties with your own implementation. But window.showModalDialog shows a dialog that has arguments and return values, you need to override those properties in the modal dialog you create too. The code looks roughly like tis:
void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
//skip events from frames
if(WebBrowserReadyState.Complete!=webBrowser1.ReadyState) return;
if(FindLoginFormOnPage()) {DoLogin();return;}
if(IsWelcomePage()){NavigateToPage1();return;}
if(IsPage1()){SubmitFormOnPage1();return;}
if(IsPage1FormResult()){
var document=webBrowser1.Document.DomDocument as mshtml.ITMLDocument2;
var expando =(IExpando)document.parentWindow;
expando.RemoveMember(expando.GetMethod("showModalDialog"
,BindingFlags.Instance | BindingFlags.Public);
expando.AddMethod("showModalDialog"
,new ShowModalDialogDelegate(this.MyShowModalDialog));
}
......
}
object MyShowModalDialog(string url, object varArgIn, object options)
{
using(FromMyShowModalDialog myShowModalDialog
=new MyShowModalDialog())
{
myShowModalDialog.StartupUrl=url;
myShowModalDialog.DialogArguments=varArgIn;
//omit the code to parse options
//and set dialog height/width/topleft location etc
if(myShowModalDialog.ShowDialog()==DialogResult.OK)
{
//do something on the return value before passing to the scripts
......
return myShowModalDialog.ReturnValue;
}
return null;
}
}
and in the Load event handler of MyShowModalDialog you call something like webBrowser1.Navigate to show the page requested by the parent page.
Now you need to pass the arguments to the webbrowser control on the new form. Do the same as above but replace another property this time.
expando.RemoveProperty("dialogArguments");
expando.AddProperty("dialogArguments")
.SetValue(expando,this.DialogArguments);
This will let the web page access the value passed from MyShowModalDialog and stored in this.DialogArguments.
The earliest you can access the DOM is in webBrowser1_DocumentCompleted. By that time the scipts on the page that read window.dialogArguments are probably already executed and got nothing. After overriding window.dialogArguments, you need to study the script on the page to find out how to revert that. for example, if the page has
<head>
<script>
var oMyObject = window.dialogArguments;
var sFirstName = oMyObject.firstName;
var sLastName = oMyObject.lastName;
</script>
...
<span style="color: 00ff7f">
<script>
document.write(sFirstName);
</script>
</span>
you need to change the values of sFirstName and sLastName then change the innerText property of the span, probably identify via its relationship with a named div or table cell. You can write the necessary changes in a script and call it via HtmlDocument.InvokeScript.
If the page returns a value to its parent, you need to pass it on to your parent form too. Override window.returnValue so when the script writes to window.returnValue it writes to a variable you provided
......
expando.RemoveProperty("returnValue");
expando.AddProperty("returnValue").SetValue(expando,this.ReturnValue);

Accessing the Thunderbird message when closing a message tab / window

We have developed a Thunderbird (11) plugin that allows us to save the content of a message to disk. Now we are extending this extension to allow automatic processing of a message when you close it. We run into a number of issues:
We cannot find a way to hook into a 'close tab' event. We are also having trouble getting the Message URI of the currently open tabs (we are trying catching click and keyboard events now). This information does not appear to be available in the DOM of the tab container.
Is there a way to detect closing of a mail message tab or window in a generic way, together with retrieving the URI of the closed mail message for further processing?
We have looked at the documentation of the tab container, the NsIWindowMediator, tried various event listeners, but no luck so far.
Edit: We are getting some results using the most recently closed tabs list. Not a very elegant solution but at least we have a reference to the tab. Now we only have to get the URI to the message that was contained inside the tab.
We cannot find a way to hook into a 'close tab' event.
The (badly documented) <tabmail> element allows registering tab monitors. Something like this should work:
var tabmail = document.getElementById("tabmail");
var monitor = {
onTabClosing: function(tab)
{
...
}
};
tabmail.registerTabMonitor(monitor);
We are also having trouble getting the Message URI of the currently open tabs
The <tabmail> element has a property tabInfo containing information on the currently open tabs. You probably want to look only at the tabs where mode.name is "message" (there is a bunch of other modes as well, e.g. "folder" or "contentTab"). This mode has a getBrowser() method, so something like this should do:
var tabmail = document.getElementById("tabmail");
for (var i = 0; i < tabmail.tabInfo.length; i++)
{
var tab = tabmail.tabInfo[i];
if (tab.mode.name == "message")
alert(tab.mode.getBrowser().currentURI.spec);
}
Edit: As Peter points out in the comments, the approach to get the URI for a message will only work the currently loaded message - all tabs reuse the same browser element for the mail messages. Getting the URI properly is more complicated, you have to get the nsIMsgDBHdr instance for the message via TabInfo.folderDisplay.selectedMessage and then use nsIMsgFolder.getUriForMsg() to construct the URI for it:
var tabmail = document.getElementById("tabmail");
for (var i = 0; i < tabmail.tabInfo.length; i++)
{
var tab = tabmail.tabInfo[i];
if (tab.mode.name != "message")
continue;
var message = tab.folderDisplay.selectedMessage;
alert(message.folder.getUriForMsg(message));
}
For the second part of the question:
The following example code will at provide you the msgDBHdr objects of all opened tabs. You should do some checks on the type to avoid accessing a message in a calendar tab.):
tabInfos = window.document.getElementById("tabmail").tabInfo;
for (i = 0; i < tabInfos.length; i++) {
msgHdr = tabInfos[i].folderDisplay.selectedMessage;
alert(
msgHdr.mime2DecodedSubject+"\n"
+msgHdr.messageId+"\n"
+"in view type "+tabInfos[i].mode.type
);
}
The tabinfo entries have some further interesting information. Just open the ErrorConsole and run
top.opener.window.document.getElementById("tabmail").tabInfo[0].toSource()
and read through it carefully.