diff --git a/pom.xml b/pom.xml index 7b0149f..aeeea7b 100644 --- a/pom.xml +++ b/pom.xml @@ -10,9 +10,13 @@ 1.0-SNAPSHOT ${project.artifactId} : ${project.version} Htmlunit sandbox - - pom + jar + + UTF-8 + UTF-8 + UTF-8 + @@ -43,5 +47,12 @@ + + + bernard.labno.pl + MyCo Internal Repository + http://bernard.labno.pl/artifactory/libs-snapshot-local + + diff --git a/src/main/java/pl/labno/bernard/htmlunified/AlertLogger.java b/src/main/java/pl/labno/bernard/htmlunified/AlertLogger.java new file mode 100644 index 0000000..4e5423d --- /dev/null +++ b/src/main/java/pl/labno/bernard/htmlunified/AlertLogger.java @@ -0,0 +1,15 @@ +package pl.labno.bernard.htmlunified; + +import com.gargoylesoftware.htmlunit.AlertHandler; +import com.gargoylesoftware.htmlunit.Page; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public class AlertLogger implements AlertHandler { + + private static final Log LOG = LogFactory.getLog(AlertLogger.class); + + public void handleAlert(Page page, String message) { + LOG.info("Alert message:" + message); + } +} diff --git a/src/main/java/pl/labno/bernard/htmlunified/DomChangeLogger.java b/src/main/java/pl/labno/bernard/htmlunified/DomChangeLogger.java new file mode 100644 index 0000000..b809ca9 --- /dev/null +++ b/src/main/java/pl/labno/bernard/htmlunified/DomChangeLogger.java @@ -0,0 +1,43 @@ +package pl.labno.bernard.htmlunified; + +import com.gargoylesoftware.htmlunit.html.DomChangeEvent; +import com.gargoylesoftware.htmlunit.html.DomChangeListener; +import com.gargoylesoftware.htmlunit.html.DomNode; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.w3c.dom.Node; + +public class DomChangeLogger implements DomChangeListener { + + private static final Log LOG = LogFactory.getLog(DomChangeLogger.class); + + public void nodeAdded(DomChangeEvent event) { + logEvent(event, "added"); + } + + public void nodeDeleted(DomChangeEvent event) { + logEvent(event, "removed"); + } + + private void logEvent(DomChangeEvent event, String action) { + String changed; + final DomNode changedNode = event.getChangedNode(); + try { + changed = changedNode.toString(); + } catch (Exception e) { + changed = changedNode.getNodeName() + "[id=" + changedNode.getAttributes().getNamedItem("id") + ("#text".equals(changedNode.getNodeName()) ? ";value=" + changedNode.getTextContent() : "") + "]"; + } + String parent; + final DomNode parentNode = event.getParentNode(); + try { + parent = parentNode.toString(); + } catch (Exception e) { + parent = parentNode.getNodeName() + "[id=" + parentNode.getAttributes().getNamedItem("id") + ("#text".equals(parentNode.getNodeName()) ? ";value=" + parentNode.getTextContent() : "") + "]"; + } + LOG.info("DomChangeEvent[action=" + action + ";changedElement=" + changed + ";source=" + event.getSource() + ";parent=" + parent + "]"); + final Node id = event.getChangedNode().getAttributes().getNamedItem("id"); + if (id != null && "searchClass:searchStudent".equals(id.getTextContent())) { + LOG.info(event.getChangedNode().asXml()); + } + } +} diff --git a/src/main/java/pl/labno/bernard/htmlunified/HtmlAttributeChangeLogger.java b/src/main/java/pl/labno/bernard/htmlunified/HtmlAttributeChangeLogger.java new file mode 100644 index 0000000..0c0dcf0 --- /dev/null +++ b/src/main/java/pl/labno/bernard/htmlunified/HtmlAttributeChangeLogger.java @@ -0,0 +1,27 @@ +package pl.labno.bernard.htmlunified; + +import com.gargoylesoftware.htmlunit.html.HtmlAttributeChangeEvent; +import com.gargoylesoftware.htmlunit.html.HtmlAttributeChangeListener; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public class HtmlAttributeChangeLogger implements HtmlAttributeChangeListener { + + private static final Log LOG = LogFactory.getLog(HtmlAttributeChangeLogger.class); + + public void attributeAdded(HtmlAttributeChangeEvent event) { + log(event, "added"); + } + + public void attributeRemoved(HtmlAttributeChangeEvent event) { + log(event, "removed"); + } + + public void attributeReplaced(HtmlAttributeChangeEvent event) { + log(event, "replaced"); + } + + private void log(HtmlAttributeChangeEvent event, String action) { + LOG.info("HtmlAttributeChangeEvent[" + action + ":" + event.getName() + "=" + event.getValue() + ";source=" + event.getSource() + "]"); + } +} \ No newline at end of file diff --git a/src/main/java/pl/labno/bernard/htmlunified/RequestResponseLogger.java b/src/main/java/pl/labno/bernard/htmlunified/RequestResponseLogger.java new file mode 100644 index 0000000..d11b3c8 --- /dev/null +++ b/src/main/java/pl/labno/bernard/htmlunified/RequestResponseLogger.java @@ -0,0 +1,38 @@ +package pl.labno.bernard.htmlunified; + +import com.gargoylesoftware.htmlunit.WebClient; +import com.gargoylesoftware.htmlunit.WebRequest; +import com.gargoylesoftware.htmlunit.WebResponse; +import com.gargoylesoftware.htmlunit.util.WebConnectionWrapper; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.io.IOException; + +public class RequestResponseLogger extends WebConnectionWrapper { + + private static final Log LOG = LogFactory.getLog(RequestResponseLogger.class); + + private boolean active = true; + + public RequestResponseLogger(WebClient webClient) throws IllegalArgumentException { + super(webClient); + } + + @Override + public WebResponse getResponse(WebRequest request) throws IOException { + final WebResponse response = super.getResponse(request); + if (active) { + LOG.info("request=" + request.getRequestBody() + "\nresponse=" + response.getContentAsString()); + } + return response; + } + + public void off() { + active = false; + } + + public void on() { + active = true; + } +} diff --git a/src/test/java/pl/labno/bernard/htmlunified/WebClientUtils.java b/src/main/java/pl/labno/bernard/htmlunified/WebClientUtils.java index 0ff45b3..8c23130 100644 --- a/src/test/java/pl/labno/bernard/htmlunified/WebClientUtils.java +++ b/src/main/java/pl/labno/bernard/htmlunified/WebClientUtils.java @@ -30,24 +30,24 @@ public class WebClientUtils { } public static int waitForJSJob(WebClient webClient) { - return waitForJSJob(webClient, webClient.waitForBackgroundJavaScript(10) - 1, defaultCheckInterval, defaultTimeout); + return waitForJSJob(webClient, webClient.waitForBackgroundJavaScript(10) - 1); } public static int waitForJSJob(WebClient webClient, int initialJobCount) { - return waitForJSJob(webClient, initialJobCount, defaultCheckInterval, defaultTimeout); + return waitForJSJob(webClient, initialJobCount, defaultTimeout); } public static int waitForJSJob(WebClient webClient, int initialJobCount, long timeout) { - return waitForJSJob(webClient, initialJobCount, defaultCheckInterval, timeout); + return waitForJSJob(webClient, initialJobCount, timeout, defaultCheckInterval); } - public static int waitForJSJob(WebClient webClient, int initialJobCount, long checkInterval, long timeout) { + public static int waitForJSJob(WebClient webClient, int initialJobCount, long timeout, long checkInterval) { int jobs; long startTime = System.currentTimeMillis(); do { jobs = webClient.waitForBackgroundJavaScript(checkInterval); if (startTime + timeout < System.currentTimeMillis()) { - throw new RuntimeException("Number of JavaScript jobs doesn't drop to initial level for 10000 seconds. It's memory leak in your JavaScript rather then request taking so long!"); + throw new RuntimeException("Number of JavaScript jobs doesn't drop to initial level for " + timeout + " seconds. It's memory leak in your JavaScript rather then request taking so long!"); } } while (jobs > initialJobCount); System.out.println("Waiting took: " + (System.currentTimeMillis() - startTime) + "ms"); @@ -74,4 +74,18 @@ public class WebClientUtils { } return suggestions; } + + public static void forceWait(int timeout) { + final long startTime = System.currentTimeMillis(); + do { + try { + final long millis = startTime + timeout - System.currentTimeMillis(); + if (millis > 0) { + Thread.sleep(millis); + } + } catch (InterruptedException ignore) { + } catch (IllegalArgumentException ignore) { + } + } while (startTime + timeout > System.currentTimeMillis()); + } } diff --git a/src/test/java/pl/labno/bernard/htmlunified/SandboxTest.java b/src/test/java/pl/labno/bernard/htmlunified/SandboxTest.java new file mode 100644 index 0000000..22a4039 --- /dev/null +++ b/src/test/java/pl/labno/bernard/htmlunified/SandboxTest.java @@ -0,0 +1,23 @@ +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.HtmlPage; +import org.junit.Assert; +import org.junit.Test; + +import java.io.IOException; + +public class SandboxTest { + + @Test + public void test() throws IOException { + final WebClient client = new WebClient(BrowserVersion.FIREFOX_3_6); + client.setAjaxController(new NicelyResynchronizingAjaxController()); + HtmlPage page = (HtmlPage) client.getPage("file:./target/test-classes/sandbox.html"); + Assert.assertEquals("elementToHide", page.getElementById("elementToHide").asText()); + page.getElementById("close").click(); + Assert.assertEquals("", page.getElementById("elementToHide").asText()); + } +} diff --git a/src/test/java/pl/labno/bernard/htmlunified/ScheduleTest.java b/src/test/java/pl/labno/bernard/htmlunified/ScheduleTest.java index 395a95b..f906a31 100644 --- a/src/test/java/pl/labno/bernard/htmlunified/ScheduleTest.java +++ b/src/test/java/pl/labno/bernard/htmlunified/ScheduleTest.java @@ -1,7 +1,6 @@ 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.HtmlElement; import com.gargoylesoftware.htmlunit.html.HtmlInput; @@ -16,83 +15,137 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +/** + * NicelyResynchronizingAjaxController is EVIL! Don't use it! + */ public class ScheduleTest { - // @Test + @Test public void accessEventTitles() throws IOException { WebClient client = new WebClient(BrowserVersion.FIREFOX_3_6); - //login----------------------------------- - HtmlPage page = (HtmlPage) client.getPage("http://localhost:8080/schoolmanager/view/class/current.seam?networkId=salsafactory"); - ((HtmlInput) page.getElementById("loginForm:email")).setValueAttribute("s4237@pjwstk.edu.pl"); - ((HtmlInput) page.getElementById("loginForm:password")).setValueAttribute("aaaaa"); - HtmlPage oldPage = page; - page = page.getElementById("loginForm:submit").click(); -// This assert would fail (when page redidrects than you need to obtain new page) -// Assert.assertEquals(page,oldPage); - Assert.assertEquals(client.getCurrentWindow().getEnclosedPage(), page); - //---------------------------------------- - + HtmlPage page = login(client); + @SuppressWarnings("unchecked") final List titleElements = (List) page.getElementById("results:schedule").getByXPath(".//span[@class='fc-event-title']"); List titles = new ArrayList(titleElements.size()); for (HtmlSpan o : titleElements) { titles.add(o.asText()); } - Assert.assertEquals(2, titles.size()); + Assert.assertEquals(4, titles.size()); } @Test - public void clickSuggestionBox() throws IOException { + public void clickStudentSuggestionBox() throws IOException { WebClient client = new WebClient(BrowserVersion.FIREFOX_3_6); - client.setAjaxController(new NicelyResynchronizingAjaxController()); - //login----------------------------------- - HtmlPage page = (HtmlPage) client.getPage("http://localhost:8080/schoolmanager/view/class/current.seam?networkId=salsafactory"); - ((HtmlInput) page.getElementById("loginForm:email")).setValueAttribute("s4237@pjwstk.edu.pl"); - ((HtmlInput) page.getElementById("loginForm:password")).setValueAttribute("aaaaa"); - HtmlPage oldPage = page; - page = page.getElementById("loginForm:submit").click(); -// This assert would fail (when page redidrects than you need to obtain new page) -// Assert.assertEquals(page,oldPage); - Assert.assertEquals(client.getCurrentWindow().getEnclosedPage(), page); - //---------------------------------------- - final HtmlInput studentInput = (HtmlInput) page.getElementById("searchClass:student_i"); - int initialJobs = client.waitForBackgroundJavaScript(10); - + HtmlPage page = login(client); + page.addDomChangeListener(new DomChangeLogger()); + page.getElementById("searchClass:sS").addHtmlAttributeChangeListener(new HtmlAttributeChangeLogger()); + HtmlInput studentInput = (HtmlInput) page.getElementById("searchClass:student_i"); studentInput.type('w'); studentInput.type('i'); Assert.assertEquals(client.getCurrentWindow().getEnclosedPage(), page); // Here the suggestionBox is still hidden -// System.out.println(page.asXml()); - - int jobs = WebClientUtils.waitForJSJob(client, 0, 30000); + WebClientUtils.waitForJSJob(client, 0, 30000); // Here suggestionBox is visible -// System.out.println(page.asXml()); - System.out.println(page.getElementById("searchClass:sS").asXml()); - System.out.println("initialJobs:" + initialJobs); - System.out.println("jobs:" + jobs); Assert.assertEquals(client.getCurrentWindow().getEnclosedPage(), page); - synchronized (page) { - try { - page.wait(1000); - } catch (InterruptedException e) { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } - } Map suggestions = WebClientUtils.getSuggestions(page.getElementById("searchClass:sS"), 0); Assert.assertEquals(1, suggestions.size()); System.out.println(suggestions); HtmlTableCell cell = suggestions.get("Willis Bruce"); Assert.assertNotNull(cell); - initialJobs = client.waitForBackgroundJavaScript(10); - System.out.println("initial jobs:"+initialJobs); cell.click(); - System.out.println("Starting jobs:"+client.waitForBackgroundJavaScriptStartingBefore(3000)); - System.out.println("Running jobs:"+client.waitForBackgroundJavaScript(10)); -// studentInput.type('\t'); - jobs = WebClientUtils.waitForJSJob(client,initialJobs, 30000); - System.out.println("initialJobs:" + initialJobs); - System.out.println("jobs:" + jobs); - System.out.println(page.asXml()); - Assert.assertEquals("Willis Bruce",((HtmlElement)page.getByXPath("//*[@id='searchClass:searchStudent']").get(0)).asText()); + WebClientUtils.waitForJSJob(client, 0, 30000); + Assert.assertEquals("Willis Bruce", ((HtmlElement) page.getByXPath("//*[@id='searchClass:searchStudent']").get(0)).asText()); + System.out.println("Success!"); + + +// page = (HtmlPage) client.getPage("http://localhost:8080/schoolmanager/view/class/current.seam?networkId=salsafactory"); + WebClientUtils.waitForJSJob(client, 0, 30000); + Assert.assertEquals(client.getCurrentWindow().getEnclosedPage(), page); + studentInput = (HtmlInput) page.getElementById("searchClass:student_i"); + studentInput.setValueAttribute(""); + studentInput.type('l'); + studentInput.type('i'); + Assert.assertEquals(client.getCurrentWindow().getEnclosedPage(), page); +// WebClientUtils.forceWait(2000); +// Here the suggestionBox is still hidden + WebClientUtils.waitForJSJob(client, 0, 30000); +// Here suggestionBox is visible + Assert.assertEquals(client.getCurrentWindow().getEnclosedPage(), page); + suggestions = WebClientUtils.getSuggestions(page.getElementById("searchClass:sS"), 0); + Assert.assertEquals(1, suggestions.size()); + System.out.println(suggestions); + cell = suggestions.get("Linda Bogusław"); + Assert.assertNotNull(cell); + cell.click(); + WebClientUtils.waitForJSJob(client, 0, 30000); + Assert.assertEquals("Linda Bogusław", ((HtmlElement) page.getByXPath("//*[@id='searchClass:searchStudent']").get(0)).asText()); + System.out.println("Success2!"); + } + + @Test + public void switchBetwenScheduleAndTableMode() throws IOException { + WebClient client = new WebClient(BrowserVersion.FIREFOX_3_6); + HtmlPage page = login(client); + page.getElementById("j_id2118:j_id2119:0").click(); + page.getElementById("j_id2118:j_id2119:0").blur(); + WebClientUtils.waitForJSJob(client, 0, 30000); +// System.out.println(page.getElementById("results").asXml()); + Assert.assertNotNull(page.getElementById("results:table")); + page.getElementById("j_id2118:j_id2119:1").click(); + page.getElementById("j_id2118:j_id2119:1").blur(); + WebClientUtils.waitForJSJob(client, 0, 30000); +// System.out.println(page.getElementById("results").asXml()); + Assert.assertNotNull(page.getElementById("results:schedule")); + page.getElementById("j_id2118:j_id2119:0").click(); + page.getElementById("j_id2118:j_id2119:0").blur(); + WebClientUtils.waitForJSJob(client, 0, 30000); +// System.out.println(page.getElementById("results").asXml()); + Assert.assertNotNull(page.getElementById("results:table")); + } + + @Test + public void selectStudentSuggestionByTab() throws IOException { + final WebClient client = new WebClient(BrowserVersion.FIREFOX_3_6); + final RequestResponseLogger requestResponseLogger = new RequestResponseLogger(client); + requestResponseLogger.off(); + HtmlPage page = login(client); + final HtmlInput studentInput = (HtmlInput) page.getElementById("searchClass:student_i"); + studentInput.type('w'); + studentInput.type('i'); + Assert.assertEquals(client.getCurrentWindow().getEnclosedPage(), page); +// Here the suggestionBox is still hidden + WebClientUtils.waitForJSJob(client, 0, 30000); +// Here suggestionBox is visible + Map suggestions = WebClientUtils.getSuggestions(page.getElementById("searchClass:sS"), 0); + Assert.assertEquals(1, suggestions.size()); +// System.out.println(suggestions); + HtmlTableCell cell = suggestions.get("Willis Bruce"); + Assert.assertNotNull(cell); + studentInput.type('\t'); + WebClientUtils.waitForJSJob(client, 0, 30000); + Assert.assertEquals("Willis Bruce", page.getElementById("searchClass:searchStudent").asText()); + +// requestResponseLogger.on(); +// client.setAlertHandler(new AlertLogger()); +// page.addDomChangeListener(new DomChangeLogger()); + final HtmlElement element = page.getElementById("searchClass:searchStudent").getElementsByTagName("img").get(0); + element.click(); + WebClientUtils.waitForJSJob(client, 0, 30000); + Assert.assertEquals(client.getCurrentWindow().getEnclosedPage(), page); + Assert.assertEquals("", page.getElementById("searchClass:searchStudent").asText()); + + } + + private HtmlPage login(WebClient client) throws IOException { + HtmlPage page = (HtmlPage) client.getPage("http://localhost:8080/schoolmanager/view/class/current.seam?networkId=salsafactory"); + ((HtmlInput) page.getElementById("loginForm:email")).setValueAttribute("s4237@pjwstk.edu.pl"); + ((HtmlInput) page.getElementById("loginForm:password")).setValueAttribute("aaaaa"); + HtmlPage oldPage = page; + page = page.getElementById("loginForm:submit").click(); +// This assert would fail (when page redidrects than you need to obtain new page) +// Assert.assertEquals(page,oldPage); + Assert.assertEquals(client.getCurrentWindow().getEnclosedPage(), page); + return page; } } diff --git a/src/test/resources/sandbox.html b/src/test/resources/sandbox.html new file mode 100644 index 0000000..52e19db --- /dev/null +++ b/src/test/resources/sandbox.html @@ -0,0 +1,12 @@ + + + + + + +close + +
elementToHide
+ + \ No newline at end of file