guard-jasmine 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,22 @@
1
+ Redistribution and use in source and binary forms, with or without
2
+ modification, are permitted provided that the following conditions are met:
3
+
4
+ * Redistributions of source code must retain the above copyright
5
+ notice, this list of conditions and the following disclaimer.
6
+ * Redistributions in binary form must reproduce the above copyright
7
+ notice, this list of conditions and the following disclaimer in the
8
+ documentation and/or other materials provided with the distribution.
9
+ * Neither the name of the <organization> nor the
10
+ names of its contributors may be used to endorse or promote products
11
+ derived from this software without specific prior written permission.
12
+
13
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16
+ ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
17
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
File without changes
data/README.md CHANGED
@@ -38,21 +38,15 @@ Please be sure to have [Guard][] installed.
38
38
 
39
39
  Install the gem:
40
40
 
41
- ```bash
42
- $ gem install guard-jasmine
43
- ```
41
+ $ gem install guard-jasmine
44
42
 
45
43
  Add it to your `Gemfile`, preferably inside the development group:
46
44
 
47
- ```ruby
48
- gem 'guard-jasmine'
49
- ```
45
+ gem 'guard-jasmine'
50
46
 
51
47
  Add guard definition to your `Guardfile` by running this command:
52
48
 
53
- ```bash
54
- $ guard init jasmine
55
- ```
49
+ $ guard init jasmine
56
50
 
57
51
  ### Rails 3.1
58
52
 
@@ -63,26 +57,20 @@ Please read the detailed installation and configuration instructions at [Jasmine
63
57
 
64
58
  In short, you add it to your `Gemfile`:
65
59
 
66
- ```ruby
67
- group :development, :test do
68
- gem 'jasmine'
69
- end
70
- ```
60
+ group :development, :test do
61
+ gem 'jasmine'
62
+ end
71
63
 
72
64
  and add a route for the Jasmine Test Runner to `config/routes.rb`:
73
65
 
74
- ```ruby
75
- if ["development", "test"].include? Rails.env
76
- mount Jasminerice::Engine => "/jasmine"
77
- end
78
- ```
66
+ if ["development", "test"].include? Rails.env
67
+ mount Jasminerice::Engine => "/jasmine"
68
+ end
79
69
 
80
70
  Next you create the directory `spec/javascripts` where your CoffeeScript tests go into. You define the Rails 3.1
81
71
  asset pipeline manifest in `spec/javascripts/spec.js.coffee`:
82
72
 
83
- ```ruby
84
- #=require_tree ./
85
- ```
73
+ #=require_tree ./
86
74
 
87
75
  ### Rails 2 & 3
88
76
 
@@ -96,17 +84,13 @@ You need the PhantomJS browser installed on your system. You can download binari
96
84
 
97
85
  Alternatively you can install [Homebrew][] on Mac OS X and install it with:
98
86
 
99
- ```bash
100
- $ brew install phantomjs
101
- ```
87
+ $ brew install phantomjs
102
88
 
103
89
  If you are using Ubuntu 10.10, you can install it with apt:
104
90
 
105
- ```bash
106
- $ sudo add-apt-repository ppa:jerome-etienne/neoip
107
- $ sudo apt-get update
108
- $ sudo apt-get install phantomjs
109
- ```
91
+ $ sudo add-apt-repository ppa:jerome-etienne/neoip
92
+ $ sudo apt-get update
93
+ $ sudo apt-get install phantomjs
110
94
 
111
95
  You can also build it from source for several other operating systems, please consult the
112
96
  [PhantomJS build instructions][].
@@ -122,42 +106,41 @@ Guard::Jasmine can be adapted to all kind of projects. Please read the
122
106
 
123
107
  ### Rails 3.1 with Jasminerice
124
108
 
125
- ```ruby
126
- guard 'jasmine' do
127
- watch(%r{app/assets/javascripts/(.+)\.(js\.coffee|js)}) { |m| "spec/javascripts/#{m[1]}_spec.#{m[2]}" }
128
- watch(%r{spec/javascripts/(.+)_spec\.(js\.coffee|js)}) { |m| "spec/javascripts/#{m[1]}_spec.#{m[2]}" }
129
- watch(%r{spec/javascripts/spec\.(js\.coffee|js)}) { "spec/javascripts" }
130
- end
131
- ```
109
+ guard 'jasmine' do
110
+ watch(%r{app/assets/javascripts/(.+)\.(js\.coffee|js)}) { |m| "spec/javascripts/#{m[1]}_spec.#{m[2]}" }
111
+ watch(%r{spec/javascripts/(.+)_spec\.(js\.coffee|js)}) { |m| "spec/javascripts/#{m[1]}_spec.#{m[2]}" }
112
+ watch(%r{spec/javascripts/spec\.(js\.coffee|js)}) { "spec/javascripts" }
113
+ end
132
114
 
133
115
  ### Rails 2 & 3 with the Jasmine gem
134
116
 
135
- ```ruby
136
- guard 'jasmine', :url => 'http://127.0.0.1:8888' do
137
- watch(%r{public/javascripts/(.+)\.js}) { |m| "spec/javascripts/#{m[1]}_spec.js" }
138
- watch(%r{spec/javascripts/(.+)_spec\.js}) { |m| "spec/javascripts/#{m[1]}_spec.js" }
139
- watch(%r{spec/javascripts/support/jasmine\.yml}) { "spec/javascripts" }
140
- watch(%r{spec/javascripts/support/jasmine_config\.rb}) { "spec/javascripts" }
141
- end
142
- ```
117
+ guard 'jasmine', :url => 'http://127.0.0.1:8888' do
118
+ watch(%r{public/javascripts/(.+)\.js}) { |m| "spec/javascripts/#{m[1]}_spec.js" }
119
+ watch(%r{spec/javascripts/(.+)_spec\.js}) { |m| "spec/javascripts/#{m[1]}_spec.js" }
120
+ watch(%r{spec/javascripts/support/jasmine\.yml}) { "spec/javascripts" }
121
+ watch(%r{spec/javascripts/support/jasmine_config\.rb}) { "spec/javascripts" }
122
+ end
143
123
 
144
124
  ## Options
145
125
 
146
126
  There following options can be passed to Guard::Jasmine:
147
127
 
148
- ```ruby
149
- :jasmine_url => 'http://192.168.1.5/jasmine' # URL where Jasmine is served.
150
- # default: http://127.0.0.1/jasmine
151
128
 
152
- :phantomjs_bin => '~/bin/phantomjs' # Path to phantomjs.
153
- # default: '/usr/local/bin/phantomjs'
129
+ :jasmine_url => 'http://192.168.1.5/jasmine' # URL where Jasmine is served.
130
+ # default: http://127.0.0.1/jasmine
154
131
 
155
- :notifications => false # Show success and error messages.
156
- # default: true
132
+ :phantomjs_bin => '~/bin/phantomjs' # Path to phantomjs.
133
+ # default: '/usr/local/bin/phantomjs'
134
+
135
+ :all_on_start => false # Run all specs on start.
136
+ # default: true
137
+
138
+ :notifications => false # Show success and error messages.
139
+ # default: true
140
+
141
+ :hide_success => true # Disable successful compilation messages.
142
+ # default: false
157
143
 
158
- :hide_success => true # Disable successful compilation messages.
159
- # default: false
160
- ```
161
144
 
162
145
  ## Alternatives
163
146
 
@@ -169,6 +152,7 @@ featured browser environment.
169
152
 
170
153
  ## Development
171
154
 
155
+ - Documentation hosted at [RubyDoc](http://rubydoc.info/gems/guard-jasmine/file/README.md)
172
156
  - Source hosted at [GitHub](https://github.com/netzpirat/guard-Jasmine)
173
157
  - Report issues and feature requests to [GitHub Issues](https://github.com/netzpirat/guard-Jasmine/issues)
174
158
 
@@ -3,28 +3,65 @@ require 'guard/guard'
3
3
  require 'guard/watcher'
4
4
 
5
5
  module Guard
6
+
7
+ # The Jasmine guard that gets notifications about the following
8
+ # Guard events: `start`, `stop`, `reload`, `run_all` and `run_on_change`.
9
+ #
6
10
  class Jasmine < Guard
7
11
 
8
12
  autoload :Formatter, 'guard/jasmine/formatter'
9
13
  autoload :Inspector, 'guard/jasmine/inspector'
10
14
  autoload :Runner, 'guard/jasmine/runner'
11
15
 
16
+ # Initialize Guard::Jasmine.
17
+ #
18
+ # @param [Array<Guard::Watcher>] watchers the watchers in the Guard block
19
+ # @param [Hash] options the options for the Guard
20
+ # @option options [String] :jasmine_url the url of the Jasmine test runner
21
+ # @option options [String] :phantomjs_bin the location of the PhantomJS binary
22
+ # @option options [Boolean] :notification show notifications
23
+ # @option options [Boolean] :hide_success hide success message notification
24
+ # @option options [Boolean] :all_on_start run all suites on start
25
+ #
12
26
  def initialize(watchers = [], options = { })
13
27
  defaults = {
14
28
  :jasmine_url => 'http://localhost:3000/jasmine',
15
29
  :phantomjs_bin => '/usr/local/bin/phantomjs',
16
- :notification => true,
17
- :hide_success => false
30
+ :notification => true,
31
+ :hide_success => false,
32
+ :all_on_start => true
18
33
  }
34
+
19
35
  super(watchers, defaults.merge(options))
20
36
  end
21
37
 
38
+ # Gets called once when Guard starts.
39
+ #
40
+ # @return [Boolean] when the start was successful
41
+ #
42
+ def start
43
+ run_all if options[:all_on_start]
44
+
45
+ true
46
+ end
47
+
48
+ # Gets called when all specs should be run.
49
+ #
50
+ # @return [Boolean] when running all specs was successful
51
+ #
22
52
  def run_all
23
- run_on_change(Watcher.match_files(self, Dir.glob(File.join('spec', '**', '*.js(.coffee)?'))))
53
+ Runner.run(['spec/javascripts'], options)
24
54
  end
25
55
 
56
+ # Gets called when watched paths and files have changes.
57
+ #
58
+ # @param [Array<String>] paths the changed paths and files
59
+ # @return [Boolean] when running the changed specs was successful
60
+ #
26
61
  def run_on_change(paths)
27
62
  Runner.run(Inspector.clean(paths), options)
63
+
64
+ #TODO: Evaluate result
28
65
  end
29
66
 
30
67
  end
@@ -1,8 +1,18 @@
1
1
  module Guard
2
2
  class Jasmine
3
+
4
+ # The inspector verifies of the changed paths are valid
5
+ # for Guard::Jasmine.
6
+ #
3
7
  module Inspector
4
8
  class << self
5
9
 
10
+ # Clean the changed paths and return only valid
11
+ # Jasmine specs in either JavaScript or CoffeeScript.
12
+ #
13
+ # @param [Array<String>] paths the changed paths
14
+ # @return [Array<String>] the valid spec files
15
+ #
6
16
  def clean(paths)
7
17
  paths.uniq!
8
18
  paths.compact!
@@ -13,14 +23,28 @@ module Guard
13
23
 
14
24
  private
15
25
 
26
+ # Tests if the file is valid.
27
+ #
28
+ # @param [String] file the file
29
+ # @return [Boolean] when the file valid
30
+ #
16
31
  def jasmine_spec?(path)
17
32
  jasmine_specs.include?(path)
18
33
  end
19
34
 
35
+ # Scans the project and keeps a list of all
36
+ # JavaScript and CoffeeScript files in the `spec`
37
+ # directory.
38
+ #
39
+ # @see #clear_jasmine_specs
40
+ # @return [Array<String>] the valid files
41
+ #
20
42
  def jasmine_specs
21
43
  @jasmine_specs ||= Dir.glob('spec/**/*_spec.{js,js.coffee}')
22
44
  end
23
45
 
46
+ # Clears the list of Jasmine specs in this project.
47
+ #
24
48
  def clear_jasmine_specs
25
49
  @jasmine_specs = nil
26
50
  end
@@ -2,17 +2,32 @@ require 'multi_json'
2
2
 
3
3
  module Guard
4
4
  class Jasmine
5
+
6
+ # The Jasmine runner handles the execution of the spec through the PhantomJS binary,
7
+ # evaluates the JSON response from the PhantomJS Script `run_jasmine.coffee`,
8
+ # writes the result to the console and triggers optional system notifications.
9
+ #
5
10
  module Runner
6
11
  class << self
7
12
 
8
- def run(files, options = { })
9
- return false if files.empty?
10
-
11
- message = options[:message] || (files == ['spec/javascripts'] ? 'Run all specs' : "Run specs #{ files.join(' ') }")
13
+ # Run the supplied specs.
14
+ #
15
+ # @param [Array<String>] paths the spec files or directories
16
+ # @param [Hash] options the options for the execution
17
+ # @option options [String] :jasmine_url the url of the Jasmine test runner
18
+ # @option options [String] :phantomjs_bin the location of the PhantomJS binary
19
+ # @option options [Boolean] :notification show notifications
20
+ # @option options [Boolean] :hide_success hide success message notification
21
+ # @return [Array<Object>] the result for each suite
22
+ #
23
+ def run(paths, options = { })
24
+ return false if paths.empty?
25
+
26
+ message = options[:message] || (paths == ['spec/javascripts'] ? 'Run all specs' : "Run specs #{ paths.join(' ') }")
12
27
  UI.info message, :reset => true
13
28
 
14
- files.inject([]) do |results, file|
15
- results << notify_result(run_jasmine(file, options), options)
29
+ paths.inject([]) do |results, file|
30
+ results << evaluate_result(run_jasmine_spec(file, options), options)
16
31
 
17
32
  results
18
33
  end.compact
@@ -20,26 +35,55 @@ module Guard
20
35
 
21
36
  private
22
37
 
23
- def run_jasmine(file, options)
24
- suite = jasmine_suite(file, options)
25
- Formatter.info("Run Jasmine tests: #{ suite }")
26
- IO.popen(phantomjs_command(options) + ' ' + suite)
38
+ # Run the Jasmine spec by executing the PhantomJS script.
39
+ #
40
+ # @param [String] path the path of the spec
41
+ #
42
+ def run_jasmine_spec(file, options)
43
+ suite = jasmine_suite(file, options)
44
+ Formatter.info("Run Jasmine tests: #{ suite }")
45
+ IO.popen(phantomjs_command(options) + ' ' + suite)
27
46
  end
28
47
 
48
+ # Get the PhantomJS binary and script to execute.
49
+ #
50
+ # @param [Hash] options the options for the execution
51
+ # @return [String] the command
52
+ #
29
53
  def phantomjs_command(options)
30
- options[:phantomjs_bin] + ' ' + phantomjs_script
54
+ options[:phantomjs_bin] + ' ' + phantomjs_script
31
55
  end
32
56
 
57
+ # Get the Jasmine test runner URL with the appended suite name
58
+ # that acts as the spec filter.
59
+ #
60
+ # @param [Hash] options the options for the execution
61
+ # @return [String] the Jasmine url
62
+ #
33
63
  def jasmine_suite(file, options)
34
- options[:jasmine_url] + suite_query_for(file)
64
+ options[:jasmine_url] + suite_name_for(file)
35
65
  end
36
66
 
67
+ # Get the PhantomJS script that executes the spec and extracts
68
+ # the result from the headless DOM.
69
+ #
70
+ # @return [String] the path to the PhantomJS script
71
+ #
37
72
  def phantomjs_script
38
73
  File.expand_path(File.join(File.dirname(__FILE__), 'phantomjs', 'run-jasmine.coffee'))
39
74
  end
40
75
 
41
- def suite_query_for(file)
76
+ # The suite name must be extracted from the spec that
77
+ # will be run. This is done by parsing from the head of
78
+ # the spec file until the first `describe` function is
79
+ # found.
80
+ #
81
+ # @param [String] file the spec file
82
+ # @return [String] the suite name
83
+ #
84
+ def suite_name_for(file)
42
85
  return '' if file == 'spec/javascripts'
86
+
43
87
  query_string = ''
44
88
 
45
89
  File.foreach(file) do |line|
@@ -52,7 +96,15 @@ module Guard
52
96
  URI.encode(query_string)
53
97
  end
54
98
 
55
- def notify_result(output, options)
99
+ # Evaluates the JSON response that the PhantomJS script
100
+ # writes to stdout. The results triggers further notification
101
+ # actions.
102
+ #
103
+ # @param [String] output the JSON output the spec run
104
+ # @param [Hash] options the options for the execution
105
+ # @return [Hash] the suite result
106
+ #
107
+ def evaluate_result(output, options)
56
108
  result = MultiJson.decode(output.read)
57
109
  output.close
58
110
 
@@ -65,12 +117,27 @@ module Guard
65
117
  result
66
118
  end
67
119
 
120
+ # Notification when a system error happens that
121
+ # prohibits the execution of the Jasmine spec.
122
+ #
123
+ # @param [Hash] the suite result
124
+ # @param [Hash] options the options for the execution
125
+ # @option options [Boolean] :notification show notifications
126
+ #
68
127
  def notify_runtime_error(result, options)
69
128
  message = "An error occurred: #{ result['error'] }"
70
129
  Formatter.error(message)
71
130
  Formatter.notify(message, :title => 'Jasmine error', :image => :failed, :priority => 2) if options[:notification]
72
131
  end
73
132
 
133
+ # Notification about a spec run, success or failure,
134
+ # and some stats.
135
+ #
136
+ # @param [Hash] result the suite result
137
+ # @param [Hash] options the options for the execution
138
+ # @option options [Boolean] :notification show notifications
139
+ # @option options [Boolean] :hide_success hide success message notification
140
+ #
74
141
  def notify_spec_result(result, options)
75
142
  specs = result['stats']['specs']
76
143
  failures = result['stats']['failures']
@@ -87,6 +154,14 @@ module Guard
87
154
  end
88
155
  end
89
156
 
157
+ # Notification about spec failures. This combines the suite
158
+ # error messages into a single notification.
159
+ #
160
+ # @param [Hash] result the suite result
161
+ # @param [String] stats the status information
162
+ # @param [Hash] options the options for the execution
163
+ # @option options [Boolean] :notification show notifications
164
+ #
90
165
  def notify_spec_failures(result, stats, options)
91
166
  messages = result['suites'].inject('') do |messages, suite|
92
167
  suite['specs'].each do |spec|
@@ -1,5 +1,5 @@
1
1
  module Guard
2
2
  module JasmineVersion
3
- VERSION = '0.1.0'
3
+ VERSION = '0.2.0'
4
4
  end
5
5
  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: 27
4
+ hash: 23
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 1
8
+ - 2
9
9
  - 0
10
- version: 0.1.0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Michael Kessler
@@ -93,6 +93,22 @@ dependencies:
93
93
  version: "2.6"
94
94
  type: :development
95
95
  version_requirements: *id005
96
+ - !ruby/object:Gem::Dependency
97
+ name: yard
98
+ prerelease: false
99
+ requirement: &id006 !ruby/object:Gem::Requirement
100
+ none: false
101
+ requirements:
102
+ - - ~>
103
+ - !ruby/object:Gem::Version
104
+ hash: 7
105
+ segments:
106
+ - 0
107
+ - 7
108
+ - 2
109
+ version: 0.7.2
110
+ type: :development
111
+ version_requirements: *id006
96
112
  description: Guard::Jasmine automatically tests your Jasmine specs on PhantomJS
97
113
  email:
98
114
  - michi@netzpiraten.ch
@@ -110,7 +126,8 @@ files:
110
126
  - lib/guard/jasmine/templates/Guardfile
111
127
  - lib/guard/jasmine/version.rb
112
128
  - lib/guard/jasmine.rb
113
- - LICENSE
129
+ - LICENSE.MIT
130
+ - LICENSE.BSD
114
131
  - README.md
115
132
  homepage: http://github.com/netzpirat/guard-jasmine
116
133
  licenses: []