001: // Copyright © 2004-2007 ASERT. Released under the Canoo Webtest license.
002: package com.canoo.webtest.extension.dialogs;
003:
004: import com.canoo.webtest.ant.WebtestTask;
005: import com.canoo.webtest.boundary.AntBoundary;
006: import com.canoo.webtest.engine.Context;
007: import com.canoo.webtest.engine.StepFailedException;
008: import com.canoo.webtest.steps.AbstractStepContainer;
009: import com.canoo.webtest.steps.Step;
010: import com.canoo.webtest.util.ConversionUtil;
011: import com.gargoylesoftware.htmlunit.*;
012: import org.apache.commons.lang.ClassUtils;
013: import org.apache.log4j.Logger;
014: import org.apache.tools.ant.Task;
015:
016: import java.util.Iterator;
017:
018: /**
019: * Saves away one or more JavaScript dialog expectations in preparation for subsequent automatic user response(s).<p>
020: *
021: * @author Paul King, ASERT
022: * @webtest.step category="Extension"
023: * name="expectDialogs"
024: * description="Provides the ability to set expectations in relation to user responses to <key>javascript</key> Dialog boxes (Alert, Confirm and Prompt dialogs). Supports nested dialog steps such as <stepref name='alert'/>, <stepref name='confirm'/> and <stepref name='prompt'/>. See also the <stepref name='verifyNoDialogs'/> step."
025: */
026: public class ExpectDialogs extends AbstractStepContainer {
027: private static final Logger LOG = Logger
028: .getLogger(ExpectDialogs.class);
029:
030: public void doExecute() {
031: final Context context = getContext();
032: DialogHelper.clearExpectedDialogs(context);
033: final WebClient wc = context.getWebClient();
034:
035: for (final Iterator iter = getSteps().iterator(); iter
036: .hasNext();) {
037: final Step step = (Step) iter.next();
038: DialogHelper.addExpectedDialog(context,
039: (AbstractDialogStep) step);
040: executeContainedStep(step);
041: }
042: final CheckingDialogHandler handler = new CheckingDialogHandler(
043: context, this );
044:
045: wc.setAlertHandler(handler);
046: wc.setConfirmHandler(handler);
047: wc.setPromptHandler(handler);
048: LOG.debug("Dialog expectation saved - now expecting "
049: + DialogHelper.getExpectedDialogsCount(context)
050: + " dialog(s).");
051: }
052:
053: public void addTask(final Task newTask) {
054: final Task task = AntBoundary.maybeConfigure(newTask);
055: if (task instanceof AbstractDialogStep) {
056: super .addTask(task);
057: } else {
058: throw new StepFailedException("Not a dialog step: " + task);
059: }
060: }
061:
062: static class CheckingDialogHandler implements AlertHandler,
063: ConfirmHandler, PromptHandler {
064: private final Context fContext;
065: private final Step fOuter;
066:
067: CheckingDialogHandler(final Context context, final Step outer) {
068: this .fContext = context;
069: this .fOuter = outer;
070: }
071:
072: public void handleAlert(final Page page, final String message) {
073: checkContext();
074: checkDialog(message, "AlertDialog");
075: }
076:
077: /**
078: * Checks that the context information is available for this thread
079: * indeed dialog handler may be called back from HtmlUnit in a different thread
080: */
081: private void checkContext() {
082: if (WebtestTask.getThreadContext() == null) {
083: WebtestTask.setThreadContext(fContext);
084: }
085: }
086:
087: public boolean handleConfirm(final Page page,
088: final String message) {
089: checkContext();
090: final AbstractDialogStep this Dialog = checkDialog(message,
091: "ConfirmDialog");
092: return ConversionUtil.convertToBoolean(this Dialog
093: .getResponse(), true);
094: }
095:
096: public String handlePrompt(final Page page, final String message) {
097: checkContext();
098: final AbstractDialogStep this Dialog = checkDialog(message,
099: "PromptDialog");
100: return this Dialog.getResponse();
101: }
102:
103: private AbstractDialogStep checkDialog(final String message,
104: final String dialogType) {
105: checkExpectationsSet(fContext);
106: final AbstractDialogStep this Dialog = DialogHelper
107: .getNextExpectedDialog(fContext);
108: saveResponse(this Dialog, message);
109: checkResponseType(this Dialog, dialogType);
110: this Dialog.verify(message);
111: return this Dialog;
112: }
113:
114: private void checkExpectationsSet(final Context context) {
115: if (DialogHelper.getExpectedDialogsCount(context) == 0) {
116: throw new StepFailedException(
117: "Expected dialogs but none found!", fOuter);
118: }
119: }
120:
121: private void saveResponse(final AbstractDialogStep this Dialog,
122: final String message) {
123: if (this Dialog.getSaveProperty() != null) {
124: fOuter.setWebtestProperty(this Dialog.getSaveProperty(),
125: message, this Dialog.getSavePropertyType());
126: }
127: }
128:
129: private void checkResponseType(
130: final AbstractDialogStep this Dialog,
131: final String dialogType) {
132: final String name = ClassUtils.getShortClassName(this Dialog
133: .getClass());
134: final String prefix = name.substring(0, name.length() - 4);
135: if (!prefix.equals(dialogType)) {
136: throw new StepFailedException("Incorrect dialog type",
137: dialogType, prefix, fOuter);
138: }
139: }
140: }
141: }
|