/*
* $Id$
* JBoss, Home of Professional Open Source
* Copyright 2010, Red Hat, Inc. and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.test.qunit;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import org.junit.rules.MethodRule;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;
import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.MockWebConnection;
import com.gargoylesoftware.htmlunit.NicelyResynchronizingAjaxController;
import com.gargoylesoftware.htmlunit.ScriptResult;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
/**
* <p class="changed_added_4_0">This class represents qunit test environment ( html page, java script libraries ... ) </p>
* @author asmirnov@exadel.com
*
*/
public class Qunit implements MethodRule {
/**
* <p class="changed_added_4_0"></p>
* @author asmirnov@exadel.com
*
*/
public static final class Builder {
private final Qunit rule = new Qunit();
public Builder content(String content) {
rule.setHtmlContent(new ContentRef(content));
return this;
}
public Builder contentResource(String src){
rule.setHtmlContent(new ResourceRef(src));
return this;
}
public Builder load(URL src) {
rule.addScript(new URLRef(src));
return this;
}
public Builder loadResource(String src) {
rule.addScript(new ResourceRef(src));
return this;
}
public Builder loadJsfResource(String name) {
rule.addScript(new ResourceRef("/META-INF/resources/"+name));
return this;
}
public Builder loadJsfResource(String name,String library) {
rule.addScript(new ResourceRef("/META-INF/resources/"+library+"/"+name));
return this;
}
public Builder loadExternal(String src) {
rule.addScript(new ExternalRef(src));
return this;
}
public Builder loadContent(String foo) {
rule.addScript(new ContentRef(foo));
return this;
}
public Builder emulate(BrowserVersion browser){
rule.browser = browser;
return this;
}
public Qunit build(){
return rule;
}
}
/**
* <p class="changed_added_4_0">Html content for JavaScript tests.</p>
*
*/
private ScriptRef htmlContent = new ContentRef("");
private BrowserVersion browser = BrowserVersion.getDefault();
private List<ScriptRef> scripts = new ArrayList<ScriptRef>();
private WebClient webClient;
private HtmlPage page;
private MockWebConnection mockConnection;
public static final String DEFAULT_URL = "http://localhost";
protected Qunit(){
;
}
public Statement apply(final Statement base, final FrameworkMethod method, final Object target) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
try {
System.out.println("Run Statement "+base.getClass().getName()+" for method "+method.getName());
setupQunit(method,target);
base.evaluate();
} finally {
thearDownQunit(method,target);
}
}
};
}
protected void thearDownQunit(FrameworkMethod method, Object target) {
if(null != page){
webClient.closeAllWindows();
}
}
protected void setupQunit(FrameworkMethod method, Object target) throws FailingHttpStatusCodeException, IOException {
URL URL = new URL(DEFAULT_URL+"/");
setupWebClient();
String content = buildContent(method,target);
mockConnection.setResponse(URL, content);
page = webClient.getPage(URL);
webClient.waitForBackgroundJavaScriptStartingBefore(4 * 60 * 1000);
}
private void setupWebClient() {
webClient = new WebClient(browser);
mockConnection = new MockWebConnection();
webClient.setWebConnection(mockConnection);
webClient.setAjaxController(new NicelyResynchronizingAjaxController());
}
private String buildContent(FrameworkMethod method, Object target) {
StringBuilder content = new StringBuilder();
content.append("<html><head><title>").append(method.getName()).append("</title>");
appendScripts(content,target);
content.append("</head><body>").append(getHtmlContent(target)).append("</body></html>");
return content.toString();
}
private void appendScripts(StringBuilder content, Object target) {
for (ScriptRef script : this.scripts) {
content.append("<script type=\"text/javascript\" src=\"");
URL url = script.getScript(target);
content.append(url.toExternalForm());
content.append("\" ></script>\n");
mockConnection.setResponse(url, script.getContent(target), "application/javascript");
}
}
private URL calculateDefaultURL(Object target){
Class<? extends Object> targetClass = target.getClass();
String resourceName = targetClass.getSimpleName()+".class";
return targetClass.getResource(resourceName);
}
/**
* <p class="changed_added_4_0"></p>
* @param target
* @return the htmlContent
*/
protected String getHtmlContent(Object target) {
return this.htmlContent.getContent(target);
}
/**
* <p class="changed_added_4_0"></p>
* @param htmlContent the htmlContent to set
*/
private void setHtmlContent(ScriptRef htmlContent) {
this.htmlContent = htmlContent;
}
/**
* <p class="changed_added_4_0">Append script to page libraries by URL</p>
* @param src
*/
private void addScript(ScriptRef src){
scripts.add(src);
}
/**
* <p class="changed_added_4_0">Run JavaScript expression in page context and returns result</p>
* @param script
* @return
*/
public Object runScript(String script){
ScriptResult scriptResult = page.executeJavaScript(script);
page = (HtmlPage) scriptResult.getNewPage();
return scriptResult.getJavaScriptResult();
}
/**
* <p class="changed_added_4_0"></p>
* @return the page
*/
public HtmlPage getPage() {
return this.page;
}
public static Builder builder(){
return new Builder();
}
}