// Copyright � 2002-2005 Canoo Engineering AG, Switzerland.
package com.canoo.webtest.steps.request;
import java.util.Iterator;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import com.canoo.webtest.engine.Context;
import com.canoo.webtest.engine.StepFailedException;
import com.canoo.webtest.steps.Step;
import com.canoo.webtest.util.ConversionUtil;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.TopLevelWindow;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.WebWindow;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
/**
* Selects a top level window as the "current active" window.<p>
*
* @author Marc Guillemot
* @author Paul King
* @webtest.step category="Extension"
* name="selectWindow"
* description="Selects the content of a window as the current response.
* Useful when a test sequence causes many windows to open.
* Only one from 'name', 'title', or 'index' can be specified."
*/
public class SelectWindow extends Step {
private static final Logger LOG = Logger.getLogger(SelectWindow.class);
private String fName;
private String fIndex;
private String fTitle;
public String getTitle() {
return fTitle;
}
/**
* One of 'index', 'name', or 'title' must be set. Name takes precedence
* in case both 'index' and 'name' are specified.
*
* @webtest.parameter required="yes/no"
* description="The title of the html document contained in the window to select."
*/
public void setTitle(final String newTitle) {
fTitle = newTitle;
}
public String getName() {
return fName;
}
/**
* One of 'index' or 'name' must be set. Name takes precedence
* in case both 'index' and 'name' are specified.
*
* @webtest.parameter required="yes/no"
* description="The name of the window to select."
*/
public void setName(final String newName) {
fName = newName;
}
/**
* Selects the top level window with the requested index (starting with 0).
* One of 'index' or 'name' must be set. Name takes precedence
* in case both 'index' and 'name' are specified.
*
* @param newIndex the new value
* @webtest.parameter required="yes/no"
* description="The index (starting with 0) of the top level window to select. "
*/
public void setIndex(final String newIndex) {
fIndex = newIndex;
}
public String getIndex() {
return fIndex;
}
public void doExecute() throws Exception {
LOG.debug("Selecting window " + getName());
final Context context = getContext();
final WebClient webClient = context.getWebClient();
final WebWindow window = findTopLevelWindow(webClient);
if (window == null) {
final StepFailedException sfe = new StepFailedException("No window found");
sfe.addDetail("available windows", getAvailableWindowsMessage(webClient));
throw sfe;
}
context.saveResponseAsCurrent(window.getEnclosedPage());
}
/**
* Finds the top level window with the specified name.
*
* @param webClient
* @return <code>null</code> if not found
*/
WebWindow findTopLevelWindow(final WebClient webClient) {
final WebWindow result;
if (getName() != null) {
result = findTopLevelWindowByName(webClient);
}
else if (getTitle() != null) {
result = findTopLevelWindowByTitle(webClient);
}
else {
result = findTopLevelWindowByIndex(webClient);
}
return result;
}
WebWindow findTopLevelWindowByName(final WebClient webClient) {
for (final Iterator iter = webClient.getWebWindows().iterator(); iter.hasNext();) {
final WebWindow window = (WebWindow) iter.next();
if (window instanceof TopLevelWindow && window.getName().equals(getName())) {
return window;
}
}
return null;
}
WebWindow findTopLevelWindowByTitle(final WebClient webClient) {
for (final Iterator iter = webClient.getWebWindows().iterator(); iter.hasNext();) {
final WebWindow window = (WebWindow) iter.next();
if (window instanceof TopLevelWindow)
{
final Page containedPage = window.getEnclosedPage();
if (containedPage instanceof HtmlPage
&& getTitle().equals(((HtmlPage) containedPage).getTitleText())) {
return window;
}
}
}
return null;
}
WebWindow findTopLevelWindowByIndex(final WebClient webClient) {
int count = 0;
int index = ConversionUtil.convertToInt(getIndex(), 0);
for (final Iterator iter = webClient.getWebWindows().iterator(); iter.hasNext();) {
final WebWindow window = (WebWindow) iter.next();
if (window instanceof TopLevelWindow && (count++ == index)) {
return window;
}
}
return null;
}
static String getAvailableWindowsMessage(final WebClient webClient) {
final StringBuffer sb = new StringBuffer();
int i = 0;
for (Iterator iter = webClient.getWebWindows().iterator(); iter.hasNext();) {
final WebWindow curWindow = (WebWindow) iter.next();
if (curWindow instanceof TopLevelWindow) {
final Page page = curWindow.getEnclosedPage();
if (i > 0)
sb.append("\n");
sb.append("index: " + i + ", name: >" + curWindow.getName() + "<");
if (page instanceof HtmlPage) {
sb.append(", title: >" + ((HtmlPage) page).getTitleText() + "<");
}
else {
sb.append(", " + page.getWebResponse().getContentType());
}
sb.append(", url: " + page.getWebResponse().getRequestUrl());
++i;
}
}
return sb.toString();
}
protected void verifyParameters() {
super.verifyParameters();
nullResponseCheck();
paramCheck(getName() == null && getTitle() == null && StringUtils.isEmpty(getIndex()),
"Required parameter 'name', 'title' or 'index' must be set!");
optionalIntegerParamCheck(getIndex(), "index", true);
}
}