Handling unexpected active Windows

A common problem in GUI testing is the appearance of an unexpected active window -- for example, a warning message box in an HTML browser. This topic describes how to handle this problem.

Imagine that you record a click on a secure page, and this link takes you to a page that is not secure. Assume your browser's security setting is adjusted to cause a message box to appear, warning you that the next page will not be secure. You click OK to dismiss the warning message, and then you click on a check box on the unsecure page. The recorded Functional Tester script would look something like this:

linkThatLeavesSecurePage().click(); 
Dialog_HtmlDialogButtonOK().click(); 
CheckboxOnTheUnsecurePage().click(); 

When you play the script back against a browser with a different security setting, the script does not play back because the Dialog_HtmlDialogButtonOK() cannot be found. You can comment out the Dialog_HtmlDialogButtonOK().click(); statement, but you will have failures when the dialog does show up.

One solution is to wait for the message to appear. If it does not appear, you can continue. The solution can be achieved with the following code:

linkThatLeavesSecurePage().click();
try 
{
    Dialog_HtmlDialogButtonOK().click();
}
catch(ObjectNotFoundException e) {} 
CheckboxOnTheUnsecurePage().click();

This code accomplishes your primary goal. If the warning message appears, you dismiss it. If it does not appear, you eventually stop waiting and then continue. However, you may not want to wait the default amount of time for the warning message to show up. If you are sure that when the warning message does show up it will arrive within 5 seconds, you can speed this up by coding as follows:

linkThatLeavesSecurePage().click();
try
{
    Dialog_HtmlDialogButtonOK().waitForExistence(5,1);
    Dialog_HtmlDialogButtonOK().click();
}
catch(ObjectNotFoundException e) {}
CheckboxOnTheUnsecurePage().click();

A reasonable objection to this approach is that you need to add this special code wherever a link on a browser might switch pages and cause a change in security. Handling this situation in a common place without changing many test scripts would be more efficient. By implementing the onObjectNotFound exception you can handle the event whenever it occurs. By putting the implementation in a helper super script, you can handle the event for any Functional Tester script that extends this helper super class.

The code in the following example implements a base class for scripts that test HTML applications. This base class implements onObjectNotFound. The onObjectNotFound method looks through all the HTML domains and looks for any HTML dialog boxes. Every HTML dialog box is dismissed by pressing Enter. If any dialog boxes are dismissed, the TestObject method is restarted. If no dialog boxes are dismissed, the method does nothing, and the ObjectNotFoundException is thrown as usual.

import com.rational.test.ft.script.*;
import com.rational.test.ft.object.interfaces.*;
/**
* This class provides some base capabilities for working
* with HTML.
*/
public abstract class HtmlScript extends RationalTestScript
{
/**
* Overrides the base implementation of onObjectNotFound. Whenever
* this event occurs, look through all the active domains (places
* where objects might be found). For HTML domains (Java
* and other domains are skipped) finds all the top objects.
* If the top object is an Html Dialog, * types an Enter key to dismiss the dialog.
* Logs a warning when this happens.
*/
public void onObjectNotFound(ITestObjectMethodState testObjectMethodState)
{
   boolean dismissedAWindow = false;
   DomainTestObject domains[] = getDomains();
   for (int i = 0; i < domains.length; ++i)
   {
       if (domains[i].getName().equals("Html"))
       {
           // HTML domain is found.
           TestObject[] topObjects = domains[i].getTopObjects();
           if (topObjects != null)
           {
               try
               {
                   for (int j = 0; j < topObjects.length; ++j)
                   {
                       if (topObjects[j].getProperty(".class").equals("Html.Dialog"))
                       {
                           // A top-level HtmlDialog is found.
                           logWarning("HtmlScript.onObjectNotFound - dismissing dialog.");
                           try
                           {
                               dismissedAWindow = true;
                               ((TopLevelTestObject)topObjects[j]).inputKeys("{enter}");
                           }
                           catch(RuntimeException e) {}
                       }
                   }
               }
               finally
               {
                   //unregister all references to top objects
                   unregister(topObjects);
               }
           }
                       
       }
   }
   if (dismissedAWindow)
   {
       //  try again
       testObjectMethodState.findObjectAgain();
   }
   else
   {
       logWarning("HtmlScript.onObjectNotFound; no Html Dialog to dismiss");
   }
}
}

Note that the above implementation of HtmlScript is only suitable for testing HTML. You may want to be able to use this base class for any script, including scripts testing Java . In this case, make sure that the TestObject is a Functional Tester HTMLobject before dismissing the HTML dialog boxes. You can add the following code to the beginning of the onObjectNotFound method:

if (!testObjectMethodState.getTestObject().
          getPropertyFromMap(IMapPropertyName.DOMAIN).equals("Html"))
{
    return;
}