Canoo Webtest WebTest Canoo

Extension Step expectDialogs

Description

Provides the ability to set expectations in relation to user responses to JavaScript Dialog boxes (Alert, Confirm and Prompt dialogs). Supports nested dialog steps such as alert, confirm and prompt. See also the verifyNoDialogs step.

This step is used prior to clicking on a link or button which invokes some JavaScript that uses dialogs (Alert, Confirm or Prompt dialogs). If you don't use this step, Canoo WebTest simply clicks 'OK' on every dialog silently. This is OK if you don't care about the Dialogs, but if you do care, you have no way of telling if anything was actually clicked or what messages were displayed in the dialogs.

You may be wondering why you need to set up expectations prior to clicking on a link or button. This is mostly due to implementation issues with the way Canoo WebTest works and the way it calls HtmlUnit. It turns out to be easier at the moment to create a list of dialog expectations. As interactions with your application cause JavaScript to invoke dialogs, we simply look at the next dialog expectation on the list, check that it meets expectations (or optionally save away the dialog message text) and then remove it from the list. For tricky JavaScript there may be multiple interactions from the user. We simply list all the expected dialog interactions in the order we expect them to occur.

Often you will use the verifyNoDialogs step in conjunction with this step to ensure that your expectations for dialogs were met. The verifyNoDialogs step is used after clicking on your link or button - it checks that the list of expected dialogs is now empty, i.e. by the time you have finished interacting with your application all the dialogs you were expecting to need clicking were actually clicked.

Parameters

description
Required? no
The description of this test step.

Nested Parameters

step
Required? yes
A webtest step.

Details

Normally only one nested dialog step will be required within this step but if you have complex JavaScript, it may require the user to respond to multiple dialogs associated with one form or link click. If this is the case (as in the complex example below) you should use multiple nested steps in the same order that the user would respond to them in. Only one verifyNoDialogs is ever required after the click event to check that everything worked as planned.

If you were expecting the JavaScript to invoke 2 dialog but only one was in fact invoked, the verifyNoDialogs step will fail with an appropriate error message. Similarly, if you expected only one dialog interaction but more occurred, the intervening click request step will fail.

Simple Example

Consider the following HTML form:

If the user leaves fields blank, we want to pop up an alert as follows:

The HTML might look something like:

Simple dialog example HTML
<HTML>
<HEAD><TITLE>Simple Dialog Example</TITLE>
<SCRIPT LANGUAGE='JAVASCRIPT'>
function isEmpty(thefield) {
    var re = /^\s{1,}$/g; //match white space i.e. space, tab, form-feed, etc.
    if ((thefield.value.length==0) || (thefield.value==null)
            || ((thefield.value.search(re)) > -1)) {
        return true;
    }
    return false;
}
function validate(theForm) {
    var message="Validation errors in form:\n";
    var errorFound = false;
    if (isEmpty(theForm.name)) {
        message += "Username field must not be blank!\n";
        theForm.name.focus();
        errorFound = true;
    }
    if (isEmpty(theForm.password)) {
        message += "Password field must not be blank!\n";
        if (!errorFound) {
            theForm.password.focus();
            errorFound = true;
        }
    }
    if (errorFound) {
        alert(message);
        return false;
    }
    return true;
}
</SCRIPT>
</HEAD>
<BODY>
<FORM name='myForm' action='' method='post'>
   Username: <INPUT type='text' NAME='name' value='' SIZE='30'><br>
   Password: <INPUT type='password' NAME='password' value='' SIZE='30'><br>
   <INPUT type='button' name='submit' value=' Login '
        onClick='return validate(myForm);'>
   <INPUT type='reset' name='reset' value=' Clear '>
</FORM>
</BODY>
</HTML>

The test might look something like:

Simple dialog example Test
<webtest name="verifyDialogs: test simple dialog form validation example">
    <config .../>
    <steps>
        <invoke description="Load Pageurl="/simpleDialogExample.html"/>
        <verifyTitle description="Confirm pagetext="Simple Dialog Example"/>
        <-- Interaction 1: try with both fields blank -->
        <expectDialogs description="set up dialog expectations">
            <alert description="expect alert with save of dialog message"
                saveProperty="simpleDialog" />
        </expectDialogs>
        <clickButton description="Click Login buttonname="submit" />
        <-- check that both of our error messages were present -->
        <verifyProperty name="simpleDialogregex="true"
            text=".*Username field must not be blank.*"/>
        <verifyProperty name="simpleDialogregex="true"
            text=".*Password field must not be blank.*"/>
        <verifyNoDialogs description="Check alert dialog was used" />

        <-- Interaction 2: try with just password field blank -->
        <expectDialogs description="set up dialog expectations">
            <alert description="expect alert with save of dialog message"
                saveProperty="simpleDialog" />
        </expectDialogs>
        <setInputField name="namevalue="some username" />
        <clickButton description="Click Login buttonname="submit" />
        <not>
            <verifyProperty name="simpleDialogregex="true"
                text=".*Username field must not be blank.*"/>
        </not>
        <verifyProperty name="simpleDialogregex="true"
            text=".*Password field must not be blank.*"/>
        <verifyNoDialogs description="Check alert dialog was used" />

        <-- Interaction 3: try with just username field blank -->
        <expectDialogs description="set up dialog expectations">
            <alert description="expect alert with inline check"
                text=".*Username field must not be blank.*regex="true" />
        </expectDialogs>
        <setInputField name="namevalue="" />
        <setInputField name="passwordvalue="some password" />
        <clickButton description="Click Login buttonname="submit" />
        <verifyNoDialogs description="Check alert dialog was used" />

        <-- Interaction 4: try with correct fields -->
        <expectDialogs description="expect no dialogs - will fail if one occurs"/>
        <setInputField name="namevalue="some username" />
        <clickButton description="Click Login buttonname="submit" />
        <-- would normally check we are on a new page here -->
    </steps>
</webtest>

Complex Example

Consider an application which performs some disk administration (the samples below don't actual do anything but show the kind of JavaScript messages that such an application would need to use).

When the user clicks the clean button they receive a JavaScript confirm dialog:

If the user selects "Cancel" they receive the following alert:

If the user selects "OK" they receive the following prompt dialog as a precaution:

If the user then clicks "Cancel" or enters incorrect text, e.g. "No" in the prompt, they receive the following alert dialog:

If the user enters the correct "YES" text and clicks "OK", they receive the following alert dialog (NOTE: nothing happens despite the message - this is just a hypothetical demo):

Here is the relevant part of the build.xml:

Complex example test
<webtest name="testHardDiskErase">
  <config .../>
  <steps>
    <invoke description="Load Initial Pageurl="/diskadmin.jsp"/>
    <verifytitle description="Should be disk admin pagetext="Disk Admin Page"/>
    <-- Interaction 1: initial cancel -->
    <expectDialogs description="set up dialog expectations - save message style">
        <confirm description="Dialog1A: expect confirm - click cancel"
            response="falsesaveProperty="initialDialog" />
        <alert description="Dialog1B: expect alert - auto OK"
            saveProperty="resultDialog" />
    </expectDialogs>
    <clickbutton description="Click Clean buttonname="CleanButton" />
    <verifyProperty description="Check text from first JavaScript Dialog"
        property="initialDialogtext="Are you sure?" />
    <verifyProperty description="Check text from second JavaScript Dialog"
        property="resultDialogtext="Operation cancelled!" />
    <verifyNoDialogs description="Check all dialogs were used" />

    <-- Interaction 2: initial OK but then cancel instead of confirm -->
    <expectDialogs description="set up dialog expectations - save message style">
        <confirm description="Dialog2A: expect confirm - click OK"
            response="truesaveProperty="initialDialog" />
        <prompt description="Dialog2B: expect prompt - click cancel"
            response="falsesaveProperty="confirmDialog" />
        <alert description="Dialog2C: expect alert - auto OK"
            saveProperty="resultDialog" />
    </expectDialogs>
    <clickbutton description="Click Clean buttonname="CleanButton" />
    <verifyProperty description="Check text from first JavaScript Dialog"
        property="initialDialogtext="Are you sure?" />
    <verifyProperty description="Check text from second JavaScript Dialog"
        property="confirmDialogregex="truetext=".*very sure.*YES.*" />
    <verifyProperty description="Check text from third JavaScript Dialog"
        property="resultDialogtext="Operation aborted!" />
    <verifyNoDialogs description="Check all dialogs were used" />

    <-- Interaction 3: initial OK followed by confirm -->
    <expectDialogs description="set up dialog expectations - inline checks style">
        <confirm description="Dialog3A: expect confirm - click OK"
            response="truetext="Are you sure?" />
        <prompt description="Dialog3B: expect prompt - enter 'YES'"
            response="YESregex="truetext=".*very sure.*YES.*" />
        <alert description="Dialog3C: expect alert - auto OK"
             text="Hard disk erased!" />
    </expectDialogs>
    <clickbutton description="Click Clean buttonname="CleanButton" />
    <verifyNoDialogs description="Check all dialogs were used" />
  </steps>
</webtest>

This assumes you have some HTML containing a form and some JavaScript something like the following:

Complex example HTML/JavaScript
<html>
<title>Disk Admin Page</title>
<body>
<script>
function doubleCheck() {
var x=confirm("Are you sure?")
if (x) {
    var y=prompt("Are you very sure? Type 'YES' to confirm")
    if (y=="YES")
       alert("Hard disk erased!")
    else
       alert("Operation aborted!")
} else
    alert("Operation cancelled!")
}
</script>
<h3>Clean Disk?</h3>
<form method="POST">
<p><input type="buttonname="CleanButtonvalue="OKonclick="doubleCheck()"></p>
</form>
</body>
</html>

news

Latest build: development
Posted: 19-Jul-2016 17:36

WebTest 3.0 released, featuring upgrades to Java 5, Groovy 1.6, and HtmlUnit 2.4.
The release includes support for maven integration, IDE-integration like for unit tests, capturing of background JavaScript errors, new steps for mouseOver and mouseOut events, better parallel execution of tests and - as usual - lots of handling improvements.
Posted: 5 March 2009

WebTest @ JavaOne
Dierk König presented "Functional testing of web applications: scaling with Java" on Wed May 7, 13:30 at JavaOne 2008 in the Tools and Scripting Languages track.
Posted: 8 May 2008

New WebTest screencast available:
Data Driven WebTest
Posted: 13 November 2007

First WebTest screencast available:
Creating a first Webtest Project

Extend WebTest with Groovy! Groovy in Action is available in every good bookstore.
Groovy in Action
Posted: 29 January 2007