1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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;
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
119 webClient.setIncorrectnessListener(new IncorrectnessListener() {
120 public void notify(String arg0, Object arg1) {}
121 });
122 }
123
124
125
126 }