开发者

HtmlUnit's HtmlPage.getElementById seems to reinitialize JavaScript after many calls

I have a simple HTML page (ratings.html) that I'm trying to test using HtmlUnit. The action that I'm testing works when I load it up in a browser and do it by hand. However, when I try to test it with HtmlUnit, it seems like too many calls to getElementById (or getInputByName) cause the JavaScript on the page to be reinitialized.

In the AddRating.scala test, the first two calls to page.addRating work, but the third fails because it can't find the 'rating3' element on the page. After lots of debugging, I've discovered that the ratingCount gets reset back to 0 for some reason.

See my comments below (between the // ****** sections) to see where the problem areas are.

Has anyone else experience this behavior or have any advice on how to deal with it? Thanks!

ratings.html (HTML Page to add "ratings"):

<html>
  <head>
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
      <script src="http://ajax.microsoft.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js"></script>
  </head>
  <body>
    <form name="new-rating" method="post" action="/add-rating">
      <table>
        <tr>
          <td valign="top">Ratings:</td>
          <td>
            Should be ordered from best to worst.<br>
            <a id="add-rating" href="#">add rating</a></td>
        </tr>
        <tr>
          <td></td>
          <td>
            <button name="submit-button" type="submit">Add Rating</button>
          </td>
        </tr>
      </table>
    </form>
    <h2>All Ratings</h2>

    <ul id="ratings">
    </ul>

    <script>
      $(window).load(function(){   
          // display ratings
          $.getJSON("/ratings", function(data)
          {
              var items = $.map(data, function(el) {
                var ratingsTable = "";
                if (el.ratings.length > 0)
                {
                  $.tmpl("<li><table><tr><th>Rating</th></tr>{{each ratings }}<tr><td>${$value.label}</td></tr>{{/each}}</table></li>", el).appendTo("#ratings");
                }
              });
          });

          // add rating action
          // ***********
          var ratingCount = 0; // THIS GETS RE-INITIALIZED TO 0 AFTER TOO MANY getElementById or getElementByName calls.
          // ***********
          $('#add-rating').click(function()
          {
              ratingCount += 1;
              $('#remove-rating').show();
              $.tmpl("<span id='rating${ratingId}'><input name='rating${ratingId}'><br></span>",
                     {ratingId: ratingCount}).insertBefore('#add-rating');
              if(ratingCount >= 5) { $('#add-rating').hide(); }
          });
      });
    </script>
  </body>
</html>

RatingsPage.scala (Scala interface to HTML page):

package portal

import com.gargoylesoftware.htmlunit.WebClient
import com.gargoylesoftware.htmlunit.html._

import infrastructure.SuperHtmlUnitConversions._

import infrastructure.WaitFo开发者_运维百科r

class RatingsPage(page: HtmlPage)
{
    val newRatingForm: HtmlForm = page.getFormByName("new-rating")

    var ratingCount = 0

    def submit(): RatingsPage =
    {
        val page = newRatingForm.getButtonByName("submit-button").click[HtmlPage]()
        ratingCount = 0
        new RatingsPage(page)
    }

    def addRating(rating: String)
    {
        page.getElementById("add-rating").click()
        ratingCount += 1
        newRatingForm.getInputByName("rating" + ratingCount).asInstanceOf[HtmlInput].setValueAttribute(rating)
    }

    def asText(): String = page.asText
    def asXml():  String = page.asXml
}

AddRating.scala (Scala HtmlUnit test that fails):

package portal

import java.util.Date
import org.scalatest.FunSuite
import org.scalatest.junit.JUnitRunner
import org.junit.runner.RunWith
import org.scalatest.matchers.ShouldMatchers
import com.gargoylesoftware.htmlunit.WebClient
import com.gargoylesoftware.htmlunit.html._
import infrastructure.WaitFor

@RunWith(classOf[JUnitRunner])
class AddRating extends FunSuite with ShouldMatchers
{
    test("add ratings")
    {
        val client = new WebClient()
        val index = new PortalIndexPage(client)
        var page = index.goToRatingsPage()

        page.addRating("Buy") // WORKS
        page.addRating("Sell") // WORKS
        // *********
        page.addRating("Sell") // FAILS! Can't find element with "rating3" name!
        // *********
        page = page.submit()
        WaitFor("rating to show up", ()=>page.asXml.contains("Sell"))

        page.asText should include ("Buy")

        client.closeAllWindows()
    }
}


My guess is that you need to have your anchor click handler to "return false".

This should prevent the browser behavior of reloading the page.


Turn your <a href... link into button and it should work. Use <button type="button" or else it will be considered a submit button.

Button (provided it is not submit) will not cause the page to reload. <a href='#' causes reload in HtmlUnit

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜