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 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: * * 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: * * * 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 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 { } }