Package com.canoo.webtest.steps.request

Source Code of com.canoo.webtest.steps.request.FollowFrame

// Copyright � 2002-2007 Canoo Engineering AG, Switzerland.
package com.canoo.webtest.steps.request;

import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import javax.xml.xpath.XPathException;

import org.apache.log4j.Logger;
import org.xml.sax.SAXException;

import com.canoo.webtest.engine.Context;
import com.canoo.webtest.engine.StepExecutionException;
import com.canoo.webtest.engine.StepFailedException;
import com.canoo.webtest.steps.AbstractBrowserAction;
import com.canoo.webtest.util.ConversionUtil;
import com.gargoylesoftware.htmlunit.ElementNotFoundException;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.WebWindow;
import com.gargoylesoftware.htmlunit.html.BaseFrame;
import com.gargoylesoftware.htmlunit.html.FrameWindow;
import com.gargoylesoftware.htmlunit.html.HtmlElement;
import com.gargoylesoftware.htmlunit.html.HtmlPage;

/**
* Selects a frame as the "current active" response.
*
* @author <a href="torben@tretau.net">Torben Tretau</a>
* @author Marc Guillemot
* @webtest.step category="Core"
* name="followFrame"
* description="Locates a frame by its name (e.g. <em><FRAME NAME='myFrame' SRC='myPage.jsp'></em>)
* and defines it as the \"current\" response for the next steps."
* alias="followframe"
*/
public class FollowFrame extends AbstractBrowserAction {
  private static final Logger LOG = Logger.getLogger(FollowFrame.class);
  private String fName;
  private String fHtmlId;
  private String fRelative;
  private boolean fIsRelative;

  /**
   * @param htmlId the new value.
   * @webtest.parameter required="yes/no"
   * description="The id of the frame to select.
   * One of 'name' or 'htmlid' must be set."
   */
  public void setHtmlId(final String htmlId) {
    fHtmlId = htmlId;
  }

  public String getHtmlId() {
    return fHtmlId;
  }

  public String getName() {
    return fName;
  }

  /**
   * @param newName
   * @webtest.parameter
   *   required="yes/no"
   *   description="The name of the frame to follow, specified in the frameset.
   *   For nested frames use the name of the frame your are after, e.g. it may be the name
   *   in the nested frameset.
   *   NOTE: if nested frames bear the same name (e.g. foo inside foo), it is not specified
   *   which of the frames will be selected.
   *   It is possible to select the top window using the special name '_top'.
   *   One of 'name' or 'htmlid' must be set."
   */
  public void setName(final String newName) {
    fName = newName;
  }

  /**
   * Indicates if the given frame name is relative to the current response (versus to the main window)
   *
   * @webtest.parameter
   *   required="no"
   *   default="false"
   *   description="Indicates that the frame with the given name should be searched
   *   in the current response (rather than in the top window).
   *   In the case of nested frames this allows you to follow a first frame,
   *   perform some actions and later to follow the nested frame."
   */
  public String getRelative() {
    return fRelative;
  }

  public void setRelative(final String relative) {
    fRelative = relative;
  }

    protected void verifyParameters() {
    super.verifyParameters();
      fIsRelative = ConversionUtil.convertToBoolean(fRelative, false);
    nullResponseCheck();

    if (getHtmlId() != null && getName() != null)
    {
      throw new StepExecutionException("\"name\" and \"htmlId\" can't be combined!", this);
    }
    else if (getName() == null && getHtmlId() == null)
    {
      throw new StepExecutionException("\"name\" or \"htmlId\" must be set!", this);
    }
    }

  protected Page findTarget(final Context context) throws XPathException, IOException, SAXException {
    final HtmlPage page;
    if (fIsRelative) {
      page = (HtmlPage) context.getCurrentResponse();
    } else { // start from the page in the top window
      page = (HtmlPage) context.getCurrentResponse().getEnclosingWindow().getTopWindow().getEnclosedPage();
    }

    final WebWindow frameWindow = getFrame(page, fName, fHtmlId);

    if (frameWindow == null) {
      throw new StepFailedException(getStepLabel() + " Frame not found with name: " + fName + " available: "
         + page.getFrames(),
         this);
    }
    return frameWindow.getEnclosedPage();
  }

  /**
   * Search for the frame with the given name inside an html page and its nested frames.
   *
   * @param htmlPage the page to search in
   * @param name the name of the searched frame, <code>null</code> if searched by htmlId
   * @param htmlId the id of the searched frame, <code>null</code> if searched by name
   * @return <code>null</code> if not found
   */
  static WebWindow getFrame(final HtmlPage htmlPage, final String name, final String htmlId) {
    LOG.info("Looking for frame (name: \"" + name
        + "\", htmlId: \"" + htmlId + "\") in " + htmlPage.getWebResponse().getRequestUrl());

    if ("_top".equals(name))
    {
      LOG.debug("Asked for frame with special name \"_top\", returning the top window for the current page");
      return htmlPage.getEnclosingWindow().getTopWindow();
    }
   
    final WebWindow theFrame;
   
    // first look at the frames directly contained in the page
    if (htmlId != null)
    {
      theFrame = getFrameById(htmlPage, htmlId);
    }
    else // by name
    {
      theFrame = getFrameByName(htmlPage, name);
    }
   
    if (theFrame != null)
    {
      return theFrame;
    }

    // if not a top level frame, perhaps is it a nested frame
    for (final Iterator iter = htmlPage.getFrames().iterator(); iter.hasNext();) {
      final WebWindow elt = (WebWindow) iter.next();
      if (elt.getEnclosedPage() instanceof HtmlPage) {
        LOG.debug("looking at subframes of \"" + elt.getName() + "\": " + elt);
        final WebWindow frame = getFrame((HtmlPage) elt.getEnclosedPage(), name, htmlId);
        if (frame != null) {
          return frame;
        }
      }
    }

    LOG.debug("frame not found");
    return null;
  }

  /**
   * Gets the frame with the given html id directly in the page
   * @param htmlPage the page
   * @param htmlId the id
   * @return <code>null</code> if no frame found with this id
   */
  private static WebWindow getFrameById(final HtmlPage htmlPage, final String htmlId) {
    LOG.debug("Looking for element with id \"" + htmlId + "\"");
    HtmlElement elt;
    try
    {
      elt = htmlPage.getHtmlElementById(htmlId);
      if (elt instanceof BaseFrame)
      {
        LOG.debug("it's the right one");
        return ((BaseFrame) elt).getEnclosedWindow();
      }
    }
    catch (final ElementNotFoundException e)
    {
      LOG.debug("No element with id \"" + htmlId + "\"");
    }
    return null;
  }

  /**
   * Gets the frame with the given name directly in the page
   * @param htmlPage the page
   * @param name the name
   * @return <code>null</code> if no frame found with this id
   */
  private static WebWindow getFrameByName(final HtmlPage htmlPage, final String name) {
    final List subFrames = htmlPage.getFrames();
    for (final Iterator iter = subFrames.iterator(); iter.hasNext();) {
      final FrameWindow elt = (FrameWindow) iter.next();
      LOG.debug("looking at frame \"" + elt.getName() + "\": " + elt);
      if (elt.getName().equals(name)) {
        LOG.debug("it's the right one");
        return elt;
      }
    }
    return null;
  }

  public void doExecute() throws Exception {
        final Context context = getContext();
        context.saveResponseAsCurrent(findTarget(context));
  }

    /**
     * Called by Ant to set the text nested between opening and closing tags.
     * @param text the text to set
     * @webtest.nested.parameter
     *    required="no"
     *    description="Alternative way to set the 'name' attribute."
     */
    public void addText(final String text) {
      if (getName() == null)
        setName(getProject().replaceProperties(text));
   }
}
TOP

Related Classes of com.canoo.webtest.steps.request.FollowFrame

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.