2011/10/17

Remarkable Changes in Past Versions of Selenium 2 WebDriver

For a long time I kept the code base of our tests running on Selenium 2.0a6. The reasons for not upgrading were different for different Selenium 2 versions - perceived stability problems in InternetExplorer or Firefox, changes being not to enough beneficial for our tests and sometimes even lack of time for the change.

Now it seems Selenium 2.8 is a good candidate for upgrade.  Following enumeration summarizes the changes we waited for and I want to use it as a thanks to all the Selenium 2 developers who participated in the effort. I also hope it wil help to anybody upgrading or considering the upgrade to a newer Selenium 2 .

1/  RenderedWebElement deprecated and removed in 2.0rc3,  method isDisplayed() was moved to WebElement class.

2/ Mouseover works since 2.0 RC2:

import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.interactions.Action;
Actions builder = new Actions(driver);
Action hoverAction = builder.moveToElement(mouseOverElement).build();
hoverAction.perform();

3/ For some time it was necessary to send Enter to a button in MSIE to press it,
but since version 2.2 clicking on buttons (WebElement.click()) seems to work flawlessly.

4/ Version 2.3 brought the nice Alert class for confirmation and alert dialogs, rendering thus JavaScript workarounds obsolete:

package org.openqa.selenium;
public interface Alert
{
  void dismiss();
  void accept();
  String getText();
  void sendKeys(String keysToSend);
}

the usage:

Alert prompt = driver.switchTo().alert();
// some short sleep here
log.debug( prompt.getText() );
prompt.sendKeys("AAA");
// some short sleep here
prompt.accept();

5/ And finally, since 2.8 important parts of the advanced interactions, double-click and right-click, work both for MSIE end FF (since 2.5for MSIE):

Actions builder = new Actions(driver);
Action doubleClick = builder.doubleClick(element).build();
doubleClick.perform();

Actions builder = new Actions(driver);
Action rightClick = builder.contextClick(element).build();
rightClick.perform();

2011/10/12

Java Applets - Building with Maven, Communicating with JavaScript

I have recently realized that I've not written any applet for some time and need to refresh my know-how. I hope writing it here will save some time for you if you are in similar situation.

The example will show the communication of Java Applet with Javascript in both ways -  Java-to-JS and JS-to-Java.

Building Applet with Maven

To help Maven to find applet classes and compile the applet, you need to add Java plugin dependency:
<dependency>
  <groupId>sun.plugin</groupId>
  <artifactId>plugin</artifactId>
  <version>1.6</version>
  <scope>system</scope>
  <systemPath>${java.home}/lib/plugin.jar</systemPath>
</dependency>

You'll also want to include content of your manifest file as the default genreated one does not contain Main-Class property/header:
<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-jar-plugin</artifactId>
      <configuration>
        <archive>
          <manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile>
        </archive>
      </configuration>
    </plugin>
  </plugins>
</build>

Example of the manifest:
Manifest-Version: 1.0
Main-Class: org.bithill.SimpleApplet

Deployment

One of things that changed significantly since writing my last applet  is an introduction of the deployment toolkit - a JavaScript library for including an applet into a web page. It looks like a marvel when compared to the tedious and error-prone applet or object tag creation and checking of the browser differences.

<script src="deployJava.js"></script>
<script>
  var attributes =
  {
    id: 'simpleApplet',
    codebase:'../../../target', // directory with the jar
    code:'org.bithill.SimpleApplet.class',
    archive:'SimpleApplet-1.0.jar',
    width: 100, height: 50,
    boxbgcolor: '#eeeeee'
  };
  var parameters = {};
  var version = '1.6';

  deployJava.runApplet(attributes, parameters, version);
</script> 
The Applet and Its Iteraction with JavaScript
package org.bithill;

import static java.lang.System.out;
import netscape.javascript.JSException;
import netscape.javascript.JSObject;
import java.applet.Applet;
import java.util.Date;

public class SimpleApplet extends Applet
{
   private JSObject js; // object for communication with JavaScript

   /** Evaluates given JavaScript expression.
    * @param jsExpression expression
    */
   public String jsEval(String jsExpression)
   {
      try { js.eval(jsExpression); }
      catch (JSException ex) { ex.printStackTrace();  }
      return new Date() + " | " + jsExpression;
   }

    /** Initializes the applet.
     *  It's called only once before the applet is started.
     */
    @Override
    public void init()
    {
       try { js = JSObject.getWindow(this);  }
       catch (JSException ex) { ex.printStackTrace();  }
    }
}

The applet gets reference to JSObject for interacting with JavaScript engine instance in the page. It is then used in jsEval() method which also return time-stamped input to demonstrate reading of the method's rerurn value. In page you need only several lines of JavaScript to connect the things together:

<script>function getAlertExpression(msg) { return "alert('" + msg + "')"; }</script>

<button onclick="document.getElementById('msgbox').innerText = ( simpleApplet.jsEval( getAlertExpression('HI') ) )">
show alert
</button>

<div id="msgbox">-- last action --</div> 

How does it work? The button has JavaScript onclick handler that calls the applet's the jsEval() method and puts its retrurn value to prepared msgbox div. Notice that applet's id is used as reference. Method jsEval() evalueates JavaScript expression in the page -that results in showing an alert dialog.