001: // Copyright © 2002-2005 Canoo Engineering AG, Switzerland.
002: package com.canoo.webtest.steps.request;
003:
004: import java.util.Iterator;
005:
006: import org.apache.commons.lang.StringUtils;
007: import org.apache.log4j.Logger;
008:
009: import com.canoo.webtest.engine.Context;
010: import com.canoo.webtest.engine.StepFailedException;
011: import com.canoo.webtest.steps.Step;
012: import com.canoo.webtest.util.ConversionUtil;
013: import com.gargoylesoftware.htmlunit.Page;
014: import com.gargoylesoftware.htmlunit.TopLevelWindow;
015: import com.gargoylesoftware.htmlunit.WebClient;
016: import com.gargoylesoftware.htmlunit.WebWindow;
017: import com.gargoylesoftware.htmlunit.html.HtmlPage;
018:
019: /**
020: * Selects a top level window as the "current active" window.<p>
021: *
022: * @author Marc Guillemot
023: * @author Paul King
024: * @webtest.step category="Extension"
025: * name="selectWindow"
026: * description="Selects the content of a window as the current response.
027: * Useful when a test sequence causes many windows to open.
028: * Only one from 'name', 'title', or 'index' can be specified."
029: */
030: public class SelectWindow extends Step {
031: private static final Logger LOG = Logger
032: .getLogger(SelectWindow.class);
033: private String fName;
034: private String fIndex;
035: private String fTitle;
036:
037: public String getTitle() {
038: return fTitle;
039: }
040:
041: /**
042: * One of 'index', 'name', or 'title' must be set. Name takes precedence
043: * in case both 'index' and 'name' are specified.
044: *
045: * @webtest.parameter required="yes/no"
046: * description="The title of the html document contained in the window to select."
047: */
048: public void setTitle(final String newTitle) {
049: fTitle = newTitle;
050: }
051:
052: public String getName() {
053: return fName;
054: }
055:
056: /**
057: * One of 'index' or 'name' must be set. Name takes precedence
058: * in case both 'index' and 'name' are specified.
059: *
060: * @webtest.parameter required="yes/no"
061: * description="The name of the window to select."
062: */
063: public void setName(final String newName) {
064: fName = newName;
065: }
066:
067: /**
068: * Selects the top level window with the requested index (starting with 0).
069: * One of 'index' or 'name' must be set. Name takes precedence
070: * in case both 'index' and 'name' are specified.
071: *
072: * @param newIndex the new value
073: * @webtest.parameter required="yes/no"
074: * description="The index (starting with 0) of the top level window to select. "
075: */
076: public void setIndex(final String newIndex) {
077: fIndex = newIndex;
078: }
079:
080: public String getIndex() {
081: return fIndex;
082: }
083:
084: public void doExecute() throws Exception {
085: LOG.debug("Selecting window " + getName());
086: final Context context = getContext();
087: final WebClient webClient = context.getWebClient();
088: final WebWindow window = findTopLevelWindow(webClient);
089: if (window == null) {
090: final StepFailedException sfe = new StepFailedException(
091: "No window found");
092: sfe.addDetail("available windows",
093: getAvailableWindowsMessage(webClient));
094: throw sfe;
095: }
096:
097: context.saveResponseAsCurrent(window.getEnclosedPage());
098: }
099:
100: /**
101: * Finds the top level window with the specified name.
102: *
103: * @param webClient
104: * @return <code>null</code> if not found
105: */
106: WebWindow findTopLevelWindow(final WebClient webClient) {
107: final WebWindow result;
108: if (getName() != null) {
109: result = findTopLevelWindowByName(webClient);
110: } else if (getTitle() != null) {
111: result = findTopLevelWindowByTitle(webClient);
112: } else {
113: result = findTopLevelWindowByIndex(webClient);
114: }
115: return result;
116: }
117:
118: WebWindow findTopLevelWindowByName(final WebClient webClient) {
119: for (final Iterator iter = webClient.getWebWindows().iterator(); iter
120: .hasNext();) {
121: final WebWindow window = (WebWindow) iter.next();
122: if (window instanceof TopLevelWindow
123: && window.getName().equals(getName())) {
124: return window;
125: }
126: }
127: return null;
128: }
129:
130: WebWindow findTopLevelWindowByTitle(final WebClient webClient) {
131: for (final Iterator iter = webClient.getWebWindows().iterator(); iter
132: .hasNext();) {
133: final WebWindow window = (WebWindow) iter.next();
134: if (window instanceof TopLevelWindow) {
135: final Page containedPage = window.getEnclosedPage();
136: if (containedPage instanceof HtmlPage
137: && getTitle().equals(
138: ((HtmlPage) containedPage)
139: .getTitleText())) {
140: return window;
141: }
142: }
143: }
144: return null;
145: }
146:
147: WebWindow findTopLevelWindowByIndex(final WebClient webClient) {
148: int count = 0;
149: int index = ConversionUtil.convertToInt(getIndex(), 0);
150: for (final Iterator iter = webClient.getWebWindows().iterator(); iter
151: .hasNext();) {
152: final WebWindow window = (WebWindow) iter.next();
153: if (window instanceof TopLevelWindow && (count++ == index)) {
154: return window;
155: }
156: }
157:
158: return null;
159: }
160:
161: static String getAvailableWindowsMessage(final WebClient webClient) {
162: final StringBuffer sb = new StringBuffer();
163: int i = 0;
164: for (Iterator iter = webClient.getWebWindows().iterator(); iter
165: .hasNext();) {
166: final WebWindow curWindow = (WebWindow) iter.next();
167: if (curWindow instanceof TopLevelWindow) {
168: final Page page = curWindow.getEnclosedPage();
169: if (i > 0)
170: sb.append("\n");
171: sb.append("index: " + i + ", name: >"
172: + curWindow.getName() + "<");
173: if (page instanceof HtmlPage) {
174: sb.append(", title: >"
175: + ((HtmlPage) page).getTitleText() + "<");
176: } else {
177: sb.append(", "
178: + page.getWebResponse().getContentType());
179: }
180: sb.append(", url: " + page.getWebResponse().getUrl());
181: ++i;
182: }
183: }
184: return sb.toString();
185: }
186:
187: protected void verifyParameters() {
188: super .verifyParameters();
189: nullResponseCheck();
190: paramCheck(getName() == null && getTitle() == null
191: && StringUtils.isEmpty(getIndex()),
192: "Required parameter 'name', 'title' or 'index' must be set!");
193: optionalIntegerParamCheck(getIndex(), "index", true);
194: }
195: }
|