View Javadoc

1   /*
2    * Derivative Work
3    * Copyright 2010 SOFTEC sa. All rights reserved.
4    *
5    * Original Work
6    * Copyright 2010 Justin Searls
7    *
8    * Licensed under the Apache License, Version 2.0 (the "License");
9    * you may not use this file except in compliance with the License.
10   * You may obtain a copy of the License at
11   *
12   *      http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  
21  package searls.jasmine.runner;
22  
23  import java.io.IOException;
24  import java.net.MalformedURLException;
25  import java.net.URL;
26  import java.util.HashMap;
27  import java.util.Map;
28  
29  import com.gargoylesoftware.htmlunit.BrowserVersion;
30  import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
31  import com.gargoylesoftware.htmlunit.IncorrectnessListener;
32  import com.gargoylesoftware.htmlunit.NicelyResynchronizingAjaxController;
33  import com.gargoylesoftware.htmlunit.ScriptResult;
34  import com.gargoylesoftware.htmlunit.WebClient;
35  import com.gargoylesoftware.htmlunit.html.HtmlPage;
36  
37  import searls.jasmine.io.IOUtilsWrapper;
38  import searls.jasmine.model.JasmineResult;
39  
40  public class SpecRunnerExecutor {
41  
42      public static final Map Browsers = new HashMap();
43  
44  	public static final String BUILD_REPORT_JS = "/buildReport.js";
45  	public static final String BUILD_CONCLUSION_JS = "/buildConclusion.js";
46  
47  	private static final long MAX_EXECUTION_MILLIS = 300000; //5 minutes - TODO make this configurable
48  	
49  	private IOUtilsWrapper ioUtilsWrapper = new IOUtilsWrapper();
50  
51      public SpecRunnerExecutor() {
52          Browsers.put("FF3",   BrowserVersion.FIREFOX_3);
53          Browsers.put("FF3.6", BrowserVersion.FIREFOX_3_6);
54          Browsers.put("IE6", BrowserVersion.INTERNET_EXPLORER_6);
55          Browsers.put("IE7", BrowserVersion.INTERNET_EXPLORER_7);
56          Browsers.put("IE8", BrowserVersion.INTERNET_EXPLORER_8);
57      }
58  	
59      public JasmineResult execute(URL runnerUrl) throws FailingHttpStatusCodeException, MalformedURLException, IOException, InterruptedException {
60          return execute(runnerUrl, "IE7");
61      }
62  
63  	public JasmineResult execute(URL runnerUrl, String browser) throws FailingHttpStatusCodeException, MalformedURLException, IOException, InterruptedException {
64  		WebClient webClient = new WebClient((BrowserVersion) Browsers.get(browser));
65  		webClient.setJavaScriptEnabled(true);
66  		webClient.setAjaxController(new NicelyResynchronizingAjaxController());
67  		
68  		quietIncorrectnessListener(webClient);
69  		
70  	    HtmlPage page = webClient.getPage(runnerUrl);
71  	    waitForRunnerToFinish(page);
72  	    
73  	    JasmineResult jasmineResult = new JasmineResult();
74  	    jasmineResult.setDescription(buildRunnerDescription(page));
75  	    jasmineResult.setDetails(buildReport(page));
76  
77  	    webClient.closeAllWindows();
78  	    
79  	    return jasmineResult;
80  	}
81  
82  
83  	private String buildReport(HtmlPage page) throws IOException {
84  		ScriptResult report = page.executeJavaScript(ioUtilsWrapper.toString(getClass().getResourceAsStream(BUILD_REPORT_JS)));
85  		return report.getJavaScriptResult().toString();
86  	}
87  
88  	private String buildRunnerDescription(HtmlPage page) throws IOException {
89  		ScriptResult description = page.executeJavaScript(ioUtilsWrapper.toString(getClass().getResourceAsStream(BUILD_CONCLUSION_JS)));
90  		return description.getJavaScriptResult().toString();
91  	}
92  
93  
94  	private void waitForRunnerToFinish(HtmlPage page) throws InterruptedException {		
95  		page.getWebClient().waitForBackgroundJavaScript(5000);
96  		int waitInMillis = 500;
97  		for (int i = 0; i < MAX_EXECUTION_MILLIS/waitInMillis; i++) {
98  			if(executionFinished(page)) {
99  				return;
100 			} else {
101         		synchronized (page) {
102 					page.wait(waitInMillis);
103         		}
104             }
105         }
106 		if(!executionFinished(page)) {
107 			throw new IllegalStateException("Attempted to wait for the test to complete processing over the course of "+(MAX_EXECUTION_MILLIS/1000)+" seconds," +
108 					"but it still appears to be running. Aborting test execution.");
109 		}
110 	}
111 
112 	private Boolean executionFinished(HtmlPage page) {
113 		ScriptResult result = page.executeJavaScript("reporter.finished");
114 		return (Boolean) result .getJavaScriptResult();
115 	}
116 
117 	private void quietIncorrectnessListener(WebClient webClient) {
118 		//Disables stuff like this "com.gargoylesoftware.htmlunit.IncorrectnessListenerImpl notify WARNING: Obsolete content type encountered: 'text/javascript'."
119 		webClient.setIncorrectnessListener(new IncorrectnessListener() {
120 			public void notify(String arg0, Object arg1) {}
121 		});
122 	}
123 
124 
125 
126 }