|
1 |
| -# This file is the script that runs within PhantomJS, requests the Jasmine specs |
2 |
| -# and waits until they are ready. |
3 |
| -phantom.injectJs 'lib/result.js' |
4 |
| - |
5 | 1 | # Set default values
|
6 | 2 | options =
|
7 | 3 | url: phantom.args[0] || 'http://127.0.0.1:3000/jasmine'
|
8 | 4 | timeout: parseInt(phantom.args[1] || 10000)
|
9 |
| - specdoc: phantom.args[2] || 'failure' |
10 |
| - focus: /true/i.test phantom.args[3] |
11 |
| - console: phantom.args[4] || 'failure' |
12 |
| - errors: phantom.args[5] || 'failure' |
13 |
| - junit: /true/i.test phantom.args[6] |
14 |
| - junit_consolidate: /true/i.test phantom.args[7] |
15 |
| - junit_save_path: phantom.args[8] || '' |
16 | 5 |
|
17 | 6 | # Create the web page.
|
18 |
| -# |
19 | 7 | page = require('webpage').create()
|
20 | 8 |
|
21 |
| -# Used to collect log messages for later assignment to the spec |
22 |
| -# |
23 |
| -currentSpecId = -1 |
24 |
| -logs = {} |
25 |
| -errors = {} |
26 |
| -resultsKey = "__jr" + Math.ceil(Math.random() * 1000000) |
27 |
| -fs = require("fs") |
28 |
| - |
29 | 9 | # Catch JavaScript errors
|
30 |
| -# |
31 |
| -page.onError = (msg, trace) -> |
32 |
| - if currentSpecId |
33 |
| - errors[currentSpecId] ||= [] |
34 |
| - errors[currentSpecId].push({ msg: msg, trace: trace }) |
35 |
| - |
36 |
| -# Capture console.log output to add it to |
37 |
| -# the result when specs have finished. |
38 |
| -# |
39 |
| -page.onConsoleMessage = (msg, line, source) -> |
40 |
| - if /^RUNNER_END$/.test(msg) |
41 |
| - result = page.evaluate -> window.reporter.runnerResult |
42 |
| - console.log JSON.stringify(new Result(result, logs, errors, options).process()) |
43 |
| - page.evaluate -> window.resultReceived = true |
44 |
| - |
45 |
| - else if /^SPEC_START: (\d+)$/.test(msg) |
46 |
| - currentSpecId = Number(RegExp.$1) |
| 10 | +# abort the request and return the error |
| 11 | +page.onError = (message, trace) -> |
| 12 | + reportError "Javascript error encountered on Jasmine test page: #{ message }", trace |
47 | 13 |
|
48 |
| - else |
49 |
| - logs[currentSpecId] ||= [] |
50 |
| - logs[currentSpecId].push(msg) |
51 |
| - |
52 |
| -# Initialize the page before the JavaScript is run. |
53 |
| -# |
| 14 | +# Once the page is initialized, setup the script for |
| 15 | +# the GuardReporter class |
54 | 16 | page.onInitialized = ->
|
55 |
| - overloadPageEvaluate(page) |
56 |
| - setupWriteFileFunction(page, resultsKey, fs.separator) |
57 |
| - |
58 |
| - page.injectJs 'lib/console.js' |
59 |
| - page.injectJs 'lib/reporter.js' |
60 |
| - page.injectJs 'lib/junit_reporter.js' |
61 |
| - |
62 |
| - setupReporters = -> |
63 |
| - # Attach the console reporter when the document is ready. |
64 |
| - window.onload = -> |
65 |
| - window.onload = null |
66 |
| - window.resultReceived = false |
67 |
| - window.reporter = new ConsoleReporter() |
68 |
| - if window.jasmine |
69 |
| - jasmine.getEnv().addReporter(new JUnitXmlReporter("%save_path%", "%consolidate%")) |
70 |
| - jasmine.getEnv().addReporter(window.reporter) |
71 |
| - |
72 |
| - page.evaluate(setupReporters, {save_path: options.junit_save_path, consolidate: options.junit_consolidate}) |
73 |
| - |
74 |
| - |
75 |
| -getXmlResults = (page, key) -> |
76 |
| - getWindowObj = -> |
77 |
| - window["%resultsObj%"] || {} |
78 |
| - page.evaluate getWindowObj, {resultsObj: key} |
79 |
| - |
80 |
| -replaceFunctionPlaceholders= (fn, replacements) -> |
81 |
| - if replacements && typeof replacements == 'object' |
82 |
| - fn = fn.toString() |
83 |
| - for p of replacements |
84 |
| - if replacements.hasOwnProperty(p) |
85 |
| - match = new RegExp("%" + p + "%", "g") |
86 |
| - loop |
87 |
| - fn = fn.replace(match, replacements[p]) |
88 |
| - break unless fn.indexOf(match) != -1 |
89 |
| - fn |
90 |
| - |
91 |
| -overloadPageEvaluate = (page) -> |
92 |
| - page._evaluate = page.evaluate |
93 |
| - page.evaluate = (fn, replacements) -> |
94 |
| - page._evaluate(replaceFunctionPlaceholders(fn, replacements)) |
95 |
| - page |
96 |
| - |
97 |
| -setupWriteFileFunction= (page,key, path_separator) -> |
98 |
| - saveData = () -> |
99 |
| - window["%resultsObj%"] = {} |
100 |
| - window.fs_path_separator = "%fs_path_separator%" |
101 |
| - window.__phantom_writeFile = (filename, text) -> |
102 |
| - window["%resultsObj%"][filename] = text; |
103 |
| - |
104 |
| - page.evaluate saveData, {resultsObj: key, fs_path_separator: path_separator} |
105 |
| - |
106 |
| -# Open web page and run the Jasmine test runner |
107 |
| -# |
108 |
| -page.open options.url, (status) -> |
109 |
| - # Avoid that a failed iframe load breaks the runner, see https://github.com/netzpirat/guard-jasmine/pull/19 |
110 |
| - page.onLoadFinished = -> |
111 |
| - if status isnt 'success' |
112 |
| - console.log JSON.stringify({ error: "Unable to access Jasmine specs at #{ options.url }" }) |
113 |
| - phantom.exit() |
114 |
| - else |
115 |
| - waitFor jasmineReady, jasmineAvailable, options.timeout, jasmineMissing |
| 17 | + page.injectJs 'guard-reporter.js' |
| 18 | + page.evaluate -> |
| 19 | + window.onload = -> |
| 20 | + window.reporter = new GuardReporter() |
| 21 | + window.jasmine.getEnv().addReporter(window.reporter) |
| 22 | + |
| 23 | +# Once the page is finished loading |
| 24 | +page.onLoadFinished = (status)-> |
| 25 | + if status isnt 'success' |
| 26 | + reportError "Unable to access Jasmine specs at #{ options.url }, page returned status: #{status}" |
| 27 | + else |
| 28 | + waitFor reporterReady, jasmineAvailable, options.timeout, reporterMissing |
116 | 29 |
|
117 |
| -# Test if the jasmine has been loaded |
118 |
| -# |
119 |
| -jasmineReady = -> |
120 |
| - page.evaluate -> window.jasmine |
| 30 | +# Open web page, which will kick off the Jasmine test runner |
| 31 | +page.open options.url |
| 32 | + |
| 33 | +# Test if Jasmine and guard has been loaded |
| 34 | +reporterReady = -> |
| 35 | + page.evaluate -> |
| 36 | + window.jasmine && window.reporter |
121 | 37 |
|
122 | 38 | # Start specs after they are have been loaded
|
123 |
| -# |
124 | 39 | jasmineAvailable = ->
|
125 |
| - waitFor specsReady, specsDone, options.timeout, specsTimedout |
| 40 | + waitFor specsDone, exitSuccessfully, options.timeout, specsTimedout |
126 | 41 |
|
127 | 42 | # Error message for when jasmine never loaded asynchronously
|
128 |
| -# |
129 |
| -jasmineMissing = -> |
| 43 | +reporterMissing = -> |
130 | 44 | text = page.evaluate -> document.getElementsByTagName('body')[0]?.innerText
|
131 |
| - |
132 |
| - if text |
133 |
| - error = """ |
134 |
| - The Jasmine reporter is not available! |
| 45 | + reportError """ |
| 46 | + The reporter is not available! |
| 47 | + Perhaps the url ( #{ options.url } ) is incorrect? |
135 | 48 |
|
136 | 49 | #{ text }
|
137 | 50 | """
|
138 |
| - console.log JSON.stringify({ error: error }) |
139 |
| - else |
140 |
| - console.log JSON.stringify({ error: 'The Jasmine reporter is not available!' }) |
141 | 51 |
|
142 |
| -# Test if the specs have finished. |
143 |
| -# |
144 |
| -specsReady = -> |
145 |
| - page.evaluate -> window.resultReceived |
| 52 | +# tests if the resultComplete flag is set on the reporter |
| 53 | +specsDone = -> |
| 54 | + result = page.evaluate -> |
| 55 | + window.reporter.resultComplete |
| 56 | + |
| 57 | +# We should end up here. Logs the results as JSON and exits |
| 58 | +exitSuccessfully = -> |
| 59 | + results = page.evaluate -> window.reporter.results() |
| 60 | + console.log JSON.stringify( results ) |
| 61 | + phantom.exit() |
| 62 | + |
146 | 63 |
|
147 | 64 | # Error message for when specs time out
|
148 |
| -# |
149 | 65 | specsTimedout = ->
|
150 | 66 | text = page.evaluate -> document.getElementsByTagName('body')[0]?.innerText
|
151 |
| - if text |
152 |
| - error = """ |
| 67 | + reportError """ |
153 | 68 | Timeout waiting for the Jasmine test results!
|
154 | 69 |
|
155 | 70 | #{ text }
|
156 | 71 | """
|
157 |
| - console.log JSON.stringify({ error: error }) |
158 |
| - else |
159 |
| - console.log JSON.stringify({ error: 'Timeout for the Jasmine test results!' }) |
160 |
| - |
161 |
| -specsDone = -> |
162 |
| - if options.junit == true |
163 |
| - xml_results = getXmlResults(page, resultsKey) |
164 |
| - for filename of xml_results |
165 |
| - if xml_results.hasOwnProperty(filename) && (output = xml_results[filename]) && typeof(output) == 'string' |
166 |
| - fs.write(filename, output, 'w') |
167 |
| - |
168 |
| - phantom.exit() |
169 | 72 |
|
170 | 73 | # Wait until the test condition is true or a timeout occurs.
|
171 | 74 | #
|
172 | 75 | # @param [Function] test the test that returns true if condition is met
|
173 | 76 | # @param [Function] ready the action when the condition is fulfilled
|
174 | 77 | # @param [Number] timeout the max amount of time to wait in milliseconds
|
175 | 78 | #
|
176 |
| -waitFor = (test, ready, timeout = 10000, timeoutFunction) -> |
177 |
| - start = Date.now() |
178 |
| - condition = false |
179 |
| - interval = undefined |
180 |
| - |
181 |
| - wait = -> |
182 |
| - if (Date.now() - start < timeout) and not condition |
183 |
| - condition = test() |
184 |
| - else |
185 |
| - clearInterval interval |
186 |
| - |
187 |
| - if condition |
188 |
| - ready() |
189 |
| - else |
190 |
| - timeoutFunction() |
191 |
| - phantom.exit(1) |
192 |
| - |
193 |
| - interval = setInterval wait, 250 |
| 79 | +waitFor = (test, ready, timeout = 10000, timeoutFunction)-> |
| 80 | + condition = false |
| 81 | + interval = undefined |
| 82 | + start = Date.now(0) |
| 83 | + wait = -> |
| 84 | + if !condition && (Date.now() - start < timeout) |
| 85 | + condition = test() |
| 86 | + else |
| 87 | + clearInterval interval |
| 88 | + if condition |
| 89 | + ready() |
| 90 | + else |
| 91 | + timeoutFunction() |
| 92 | + interval = setInterval( wait, 250 ) |
| 93 | + |
| 94 | +# Logs the error to the console as JSON and exits with status '1' |
| 95 | +reportError = (msg, trace=[])-> |
| 96 | + if 0 == trace.length |
| 97 | + err = new Error(); |
| 98 | + trace = err.stack |
| 99 | + console.log JSON.stringify({ error: msg, trace: trace }) |
| 100 | + phantom.exit(1) |
0 commit comments