guard-jasmine 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -53,7 +53,7 @@ Add guard definition to your `Guardfile` by running this command:
53
53
 
54
54
  $ guard init jasmine
55
55
 
56
- ### Rails 3.1
56
+ ### Jasminerice
57
57
 
58
58
  With Rails 3.1 you can write your Jasmine specs in addition to JavaScript with CoffeeScript, fully integrated into the
59
59
  Rails 3.1 asset pipeline with Jasminerice.
@@ -104,8 +104,6 @@ Please read the [Guard usage documentation](https://github.com/guard/guard#readm
104
104
  Guard::Jasmine can be adapted to all kind of projects. Please read the
105
105
  [Guard documentation](https://github.com/guard/guard#readme) for more information about the Guardfile DSL.
106
106
 
107
- ### Rails 3.1 with Jasminerice
108
-
109
107
  guard 'jasmine' do
110
108
  watch(%r{app/assets/javascripts/(.+)\.(js\.coffee|js)}) { |m| "spec/javascripts/#{m[1]}_spec.#{m[2]}" }
111
109
  watch(%r{spec/javascripts/(.+)_spec\.(js\.coffee|js)}) { |m| "spec/javascripts/#{m[1]}_spec.#{m[2]}" }
@@ -144,8 +142,9 @@ than running a whole suite.
144
142
 
145
143
  ### A note on Rails 2 and 3
146
144
 
147
- This readme describes the use of Guard::Jasmine with Jasminerice through the asset pipeline. But as long as you
148
- serve the Jasmine test runner under a certain url, it's freely up to you how to prepare and serve the runner.
145
+ This readme describes the use of Guard::Jasmine with Jasminerice through the asset pipeline, but it is not really
146
+ a requirement for Guard::Jasmine. As long as you serve the Jasmine test runner under a certain url,
147
+ it's freely up to you how you'll prepare the assets and serve the Jasmine runner.
149
148
 
150
149
  You can use [the Jasmine Gem][], configure the test suite in `jasmine.yml` and start the Jasmine test runner with
151
150
  the supplied Rake task:
@@ -164,8 +163,8 @@ Next follows an example on how to configure your `Guardfile` with the Jasmine ge
164
163
  It is also possible to use CoffeeScript in this setup, by using [Guard::CoffeeScript][] to compile your code and even
165
164
  specs. Just add something like this *before* Guard::Jasmine:
166
165
 
167
- guard 'coffeescript', :input => 'app/coffeescripts', :output => 'public/javascripts'
168
- guard 'coffeescript', :input => 'spec/coffeescripts', :output => 'spec/javascripts'
166
+ guard 'coffeescript', :input => 'app/coffeescripts', :output => 'public/javascripts'
167
+ guard 'coffeescript', :input => 'spec/coffeescripts', :output => 'spec/javascripts'
169
168
 
170
169
  ## Alternatives
171
170
 
@@ -177,7 +176,7 @@ featured browser environment.
177
176
 
178
177
  ## Development
179
178
 
180
- - Documentation hosted at [RubyDoc](http://rubydoc.info/gems/guard-jasmine/file/README.md).
179
+ - Documentation hosted at [RubyDoc](http://rubydoc.info/github/guard/guard-jasmine/master/frames).
181
180
  - Source hosted at [GitHub](https://github.com/netzpirat/guard-jasmine).
182
181
  - Report issues and feature requests to [GitHub Issues](https://github.com/netzpirat/guard-jasmine/issues).
183
182
 
@@ -37,38 +37,39 @@ specsReady = ->
37
37
  #
38
38
  extractResult = ->
39
39
  page.evaluate ->
40
- stats = /(\d+) specs, (\d+) failures? in (\d+.\d+)s/.exec document.body.querySelector('.description').innerText
40
+ stats = /(\d+) specs?, (\d+) failures? in (\d+.\d+)s/.exec(document.body.querySelector('.description').innerText)
41
+ specs = parseInt stats[1]
42
+ failures = parseInt stats[2]
43
+ time = parseFloat stats[3]
44
+ passed = failures is 0
41
45
 
42
46
  result = {
43
- passed: true
47
+ passed: passed
44
48
  stats: {
45
- specs: parseInt stats[1]
46
- failures: parseInt stats[2]
47
- time: parseFloat stats[3]
49
+ specs: specs
50
+ failures: failures
51
+ time: time
48
52
  }
49
53
  suites: []
50
54
  }
51
55
 
52
56
  for suite in document.body.querySelectorAll('div.jasmine_reporter > div.suite')
53
57
  description = suite.querySelector('a.description')
54
-
55
58
  suite_ = {
56
59
  description: description.innerText
57
60
  specs: []
58
61
  }
59
62
 
60
63
  for spec in suite.querySelectorAll('div.spec')
61
- passed = spec.getAttribute('class').indexOf('passed') isnt -1
62
- result['passed'] = false if not passed
63
-
64
- spec_ = {
65
- description: spec.querySelector('a.description').getAttribute 'title'
66
- passed: passed
67
- }
68
-
69
- spec_['error_message'] = spec.querySelector('div.resultMessage').innerText if not passed
70
-
71
- suite_['specs'].push spec_
64
+ status = spec.getAttribute('class').substring(5)
65
+ if status isnt 'skipped'
66
+ passed = status is 'passed'
67
+ spec_ = {
68
+ description: spec.querySelector('a.description').getAttribute 'title'
69
+ passed: passed
70
+ }
71
+ spec_['error_message'] = spec.querySelector('div.resultMessage').innerText if not passed
72
+ suite_['specs'].push spec_
72
73
 
73
74
  result['suites'].push suite_
74
75
 
@@ -25,8 +25,7 @@ module Guard
25
25
  def run(paths, options = { })
26
26
  return [false, []] if paths.empty?
27
27
 
28
- message = options[:message] || (paths == ['spec/javascripts'] ? 'Run all specs' : "Run specs #{ paths.join(' ') }")
29
- UI.info message, :reset => true
28
+ notify_start_message(paths)
30
29
 
31
30
  results = paths.inject([]) do |results, file|
32
31
  results << evaluate_result(run_jasmine_spec(file, options), file, options)
@@ -39,13 +38,27 @@ module Guard
39
38
 
40
39
  private
41
40
 
41
+ # Shows a notification in the console that the runner starts.
42
+ #
43
+ # @param [Array<String>] paths the spec files or directories
44
+ #
45
+ def notify_start_message(paths)
46
+ message = if paths == ['spec/javascripts']
47
+ 'Run all Jasmine suites'
48
+ else
49
+ "Run Jasmine suite#{ paths.size == 1 ? '' : 's' } #{ paths.join(' ') }"
50
+ end
51
+
52
+ Formatter.info(message, :reset => true)
53
+ end
54
+
42
55
  # Returns the failed spec file names.
43
56
  #
44
57
  # @param [Array<Object>] results the spec runner results
45
58
  # @return [Array<String>] the list of failed spec files
46
59
  #
47
60
  def failed_paths_from(results)
48
- results.map { |r| !r['passed'] ? r['file']: nil }.compact
61
+ results.map { |r| !r['passed'] ? r['file'] : nil }.compact
49
62
  end
50
63
 
51
64
  # Returns the response status for the given result set.
@@ -63,7 +76,7 @@ module Guard
63
76
  #
64
77
  def run_jasmine_spec(file, options)
65
78
  suite = jasmine_suite(file, options)
66
- Formatter.info("Run Jasmine tests at #{ suite }")
79
+ Formatter.info("Run Jasmine suite at #{ suite }")
67
80
  IO.popen(phantomjs_command(options) + ' ' + suite)
68
81
  end
69
82
 
@@ -83,7 +96,7 @@ module Guard
83
96
  # @return [String] the Jasmine url
84
97
  #
85
98
  def jasmine_suite(file, options)
86
- options[:jasmine_url] + suite_name_for(file)
99
+ options[:jasmine_url] + query_string_for_suite(file)
87
100
  end
88
101
 
89
102
  # Get the PhantomJS script that executes the spec and extracts
@@ -103,14 +116,14 @@ module Guard
103
116
  # @param [String] file the spec file
104
117
  # @return [String] the suite name
105
118
  #
106
- def suite_name_for(file)
119
+ def query_string_for_suite(file)
107
120
  return '' if file == 'spec/javascripts'
108
121
 
109
122
  query_string = ''
110
123
 
111
124
  File.foreach(file) do |line|
112
125
  if line =~ /describe\s*[("']+(.*?)["')]+/
113
- query_string = "?#{ $1 }"
126
+ query_string = "?spec=#{ $1 }"
114
127
  break
115
128
  end
116
129
  end
@@ -128,17 +141,26 @@ module Guard
128
141
  # @return [Hash] the suite result
129
142
  #
130
143
  def evaluate_result(output, file, options)
131
- result = MultiJson.decode(output.read)
132
- output.close
144
+ json = output.read
133
145
 
134
- if result['error']
135
- notify_runtime_error(result, options)
136
- else
137
- result['file'] = file
138
- notify_spec_result(result, options)
139
- end
146
+ begin
147
+ result = MultiJson.decode(json)
148
+ output.close
149
+
150
+ if result['error']
151
+ notify_runtime_error(result, options)
152
+ else
153
+ result['file'] = file
154
+ notify_spec_result(result, options)
155
+ end
156
+
157
+ result
140
158
 
141
- result
159
+ rescue Exception => e
160
+ Formatter.error("Cannot decode JSON from PhantomJS runner: #{ e.message }")
161
+ Formatter.error('Please report an issue at: https://github.com/netzpirat/guard-jasmine/issues')
162
+ Formatter.error(json)
163
+ end
142
164
  end
143
165
 
144
166
  # Notification when a system error happens that
@@ -172,9 +194,10 @@ module Guard
172
194
 
173
195
  if failures != 0
174
196
  notify_specdoc(result, message, options)
197
+ Formatter.notify(message, :title => 'Jasmine suite failed', :image => :failed, :priority => 2) if options[:notification]
175
198
  else
176
199
  Formatter.success(message)
177
- Formatter.notify(message, :title => 'Jasmine specs passed') if options[:notification] && !options[:hide_success]
200
+ Formatter.notify(message, :title => 'Jasmine suite passed') if options[:notification] && !options[:hide_success]
178
201
  end
179
202
  end
180
203
 
@@ -192,14 +215,37 @@ module Guard
192
215
  if spec['passed']
193
216
  Formatter.success(" ✔ #{ spec['description'] }") if !options[:hide_success]
194
217
  else
195
- Formatter.spec_failed(" ✘ #{ spec['description'] } ➤ #{ spec['error_message'] }")
196
- Formatter.notify(stats, :title => "#{ spec['description'] }: #{ spec['error_message'] }", :image => :failed, :priority => 2) if options[:notification]
218
+ Formatter.spec_failed(" ✘ #{ spec['description'] }")
219
+ Formatter.spec_failed(" #{ format_error_message(spec['error_message'], false) }")
220
+ Formatter.notify("#{ spec['description'] }: #{ format_error_message(spec['error_message'], true) }",
221
+ :title => 'Jasmine spec failed',
222
+ :image => :failed,
223
+ :priority => 2) if options[:notification]
197
224
  end
198
225
  end
199
226
  end
200
227
 
201
228
  Formatter.info(stats)
202
229
  end
230
+
231
+ # Formats the error message.
232
+ #
233
+ # Known message styles:
234
+ #
235
+ # - {message} in http.*assets/{spec}?body=\d ({line})
236
+ #
237
+ # @param [String] message the error message
238
+ # @param [Boolean] short show a short version of the message
239
+ # @return [String] the cleaned error message
240
+ #
241
+ def format_error_message(message, short)
242
+ if message =~ /(.*?) in http.+?assets\/(.*)\?body=\d+\s\((line\s\d+)/
243
+ short ? $1 : "#{ $1 } in #{ $2 } on #{ $3 }"
244
+ else
245
+ message
246
+ end
247
+ end
248
+
203
249
  end
204
250
  end
205
251
  end
@@ -1,6 +1,6 @@
1
1
  module Guard
2
2
  module JasmineVersion
3
3
  # Guard::Jasmine version that is used for the Gem specification
4
- VERSION = '0.3.1'
4
+ VERSION = '0.3.2'
5
5
  end
6
6
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: guard-jasmine
3
3
  version: !ruby/object:Gem::Version
4
- hash: 17
4
+ hash: 23
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 3
9
- - 1
10
- version: 0.3.1
9
+ - 2
10
+ version: 0.3.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Michael Kessler