ReRenderedJavaScriptTest.java 7.96 KB
package pl.labno.bernard.htmlunified;

import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.NicelyResynchronizingAjaxController;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.DomNodeList;
import com.gargoylesoftware.htmlunit.html.HtmlElement;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import junit.framework.Assert;
import junit.framework.AssertionFailedError;
import org.junit.Test;

import java.io.IOException;

public class ReRenderedJavaScriptTest {

    /**
     * This test checks if results can be paginated properly.
     * On first page there are 6 people and datascroller.
     * After clicking page 2 the results should be re-rendered with
     * response from ajax request. Datascroller should also be re-rendered.
     * In order for datascroller to work the javascript that is rendered below it
     * should be evaluated.
     * This test fails cause HtmlUnit has problems with script elements from XHttpRequest
     */
    @Test(expected = AssertionFailureCaughtException.class)
    public void testPagination() throws IOException {
        final WebClient client = new WebClient(BrowserVersion.FIREFOX_3_6);
        client.setAjaxController(new NicelyResynchronizingAjaxController());
        HtmlPage page = client.getPage("http://mamywladze.pl/ludzie");
        HtmlElement table = page.getElementById("filterForm:j_id101:j_id113_table");
        Assert.assertNotNull(table);
        DomNodeList<HtmlElement> cells = table.getElementsByTagName("td");
        Assert.assertNotNull(cells);
        Assert.assertEquals(5, cells.size());
        /**
         * Current page has rich-datascr-act style class.
         */
        String styleClass = cells.get(0).getAttribute("class");
        Assert.assertNotNull(styleClass);
        Assert.assertTrue("Page 1 is not the current page", styleClass.contains("rich-datascr-act"));
        final HtmlElement cell2 = cells.get(1);
        Assert.assertNotNull(cell2);
        new RequestResponseLogger(client);
        /**
         * Now this click will trigger ajax request which response will be used to update results and datascroller.
         */
        cell2.click();
        /**
         * Notice that output of following line should contain this:
         * <script type="text/javascript">
         * //<![CDATA[
         * //
         * //]]>
         * </script>
         * Its cause HtmlScript contains 3 children in stead of 1 and HtmlScript class uses only first child
         * Child 1:
         * //
         * Child 2:
         * Event.observe('filterForm:j_id101:j_id113', 'rich:datascroller:onscroll', function(event){A4J.AJAX.Submit('_viewRoot','filterForm',event,{'ignoreDupResponses':true,'parameters':{'filterForm:j_id101:j_id113':event.memo.page} ,'eventsQueue':'filterForm:j_id101:j_id113','actionUrl':'/ludzie'} ); return false;});
         *
         * Child 3:
         * //
         *
         * And actual part of Xhttp response was:
         * <script type="text/javascript">//<![CDATA[
         * Event.observe('filterForm:j_id101:j_id113', 'rich:datascroller:onscroll', function(event){A4J.AJAX.Submit('_viewRoot','filterForm',event,{'ignoreDupResponses':true,'parameters':{'filterForm:j_id101:j_id113':event.memo.page} ,'eventsQueue':'filterForm:j_id101:j_id113','actionUrl':'/ludzie'} ); return false;});
         * //]]>
         * </script>
         *
         * It is fault of the parser that splits script's contents into 3 child nodes. It happends both in HtmlUnit and in FireFox. So i guess it is the nature
         * of parser.
         */
        System.out.println(page.getElementById("filterForm:personList").asXml());
        table = page.getElementById("filterForm:j_id101:j_id113_table");
        Assert.assertNotNull(table);
        cells = table.getElementsByTagName("td");
        Assert.assertNotNull(cells);
        Assert.assertEquals(6, cells.size());
        styleClass = cells.get(2).getAttribute("class"); //If you wonder why 2 in stead of 1, it's cause there is extra cell that navigates to the start
        Assert.assertNotNull(styleClass);
        Assert.assertTrue("Page 2 is not the current page", styleClass.contains("rich-datascr-act"));

        /**
         * This click however will not trigger ajax request cause script that was binding appropriate event listeners was not executed.
         * (it came from previous ajax request)
         */
        cells.get(1).click();

        System.out.println(page.getElementById("filterForm:personList").asXml());
        table = page.getElementById("filterForm:j_id101:j_id113_table");
        Assert.assertNotNull(table);
        cells = table.getElementsByTagName("td");
        Assert.assertNotNull(cells);
        /**
         * This assertion should fail.
         */
        try {
            Assert.assertEquals(5, cells.size());
        } catch (AssertionFailedError e) {
            throw new AssertionFailureCaughtException();
        }
        styleClass = cells.get(0).getAttribute("class");
        Assert.assertNotNull(styleClass);
        Assert.assertTrue("Page 2 is not the current page", styleClass.contains("rich-datascr-act"));
    }

    /**
     * This test is the same as testPagination but should pass cause it uses my nice hack.
     */
    @Test
    public void testPaginationSuccessfully() throws IOException {
        final WebClient client = new WebClient(BrowserVersion.FIREFOX_3_6);
        client.setAjaxController(new NicelyResynchronizingAjaxController());
        HtmlPage page = client.getPage("http://mamywladze.pl/ludzie");
        HtmlElement table = page.getElementById("filterForm:j_id101:j_id113_table");
        Assert.assertNotNull(table);
        DomNodeList<HtmlElement> cells = table.getElementsByTagName("td");
        Assert.assertNotNull(cells);
        Assert.assertEquals(5, cells.size());
        /**
         * Current page has rich-datascr-act style class.
         */
        String styleClass = cells.get(0).getAttribute("class");
        Assert.assertNotNull(styleClass);
        Assert.assertTrue("Page 1 is not the current page", styleClass.contains("rich-datascr-act"));
        final HtmlElement cell2 = cells.get(1);
        Assert.assertNotNull(cell2);
        new RequestResponseLogger(client);
        /**
         * Now this click will trigger ajax request which response will be used to update results and datascroller.
         */
        cell2.click();

        System.out.println(page.getElementById("filterForm:personList").asXml());
        table = page.getElementById("filterForm:j_id101:j_id113_table");
        Assert.assertNotNull(table);
        cells = table.getElementsByTagName("td");
        Assert.assertNotNull(cells);
        Assert.assertEquals(6, cells.size());
        styleClass = cells.get(2).getAttribute("class"); //If you wonder why 2 in stead of 1, it's cause there is extra cell that navigates to the start
        Assert.assertNotNull(styleClass);
        Assert.assertTrue("Page 2 is not the current page", styleClass.contains("rich-datascr-act"));

        /**
         * This click however will not trigger ajax request cause script that was binding appropriate event listeners was not executed.
         * (it came from previous ajax request)
         */
        cells.get(1).click();

        /**
         * Here is the hack.
         */
        WebClientUtils.executeAjaxReRenderedScripts(page);

        System.out.println(page.getElementById("filterForm:personList").asXml());
        table = page.getElementById("filterForm:j_id101:j_id113_table");
        Assert.assertNotNull(table);
        cells = table.getElementsByTagName("td");
        Assert.assertNotNull(cells);
        /**
         * This time the assertion should be ok
         */
        Assert.assertEquals(5, cells.size());
        styleClass = cells.get(0).getAttribute("class");
        Assert.assertNotNull(styleClass);
        Assert.assertTrue("Page 2 is not the current page", styleClass.contains("rich-datascr-act"));
    }

    public class AssertionFailureCaughtException extends RuntimeException {
    }
}