guard-mocha-node 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ *~
2
+ *.gem
3
+ .bundle
4
+ Gemfile.lock
5
+ pkg/*
6
+ /.rvmrc
data/CHANGELOG.md ADDED
File without changes
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in guard-mocha-node.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,6 @@
1
+ guard 'rspec', :version => 2 do
2
+ watch(%r{^spec/.+_spec\.rb$})
3
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
4
+ watch('spec/spec_helper.rb') { "spec" }
5
+ end
6
+
data/README.md ADDED
@@ -0,0 +1,135 @@
1
+ Guard::MochaNode
2
+ ==================
3
+
4
+ This is a fork of the Great work from [Dave Nolan](https://github.com/textgoeshere)
5
+ with his gem [Guard::JasmineNode](https://github.com/guard/guard-jasmine-node).
6
+ Only modified to work with mocha
7
+
8
+ ... and then I stole it from [[https://github.com/kanzeon/guard-mocha-node|kanzeon]], and I'd welcome them taking it back at any point :)
9
+
10
+ MochaNode guard automatically & intelligently executes mocha node specs when files are modified.
11
+
12
+ * Tested against Node 0.8.14, mocha 1.6.0
13
+
14
+ Requirements
15
+ ------------
16
+
17
+ * [Node](http://nodejs.org/)
18
+ * Mocha
19
+ * [Ruby](http://ruby-lang.org) and rubygems
20
+
21
+ Install
22
+ -------
23
+
24
+ Install the gem:
25
+
26
+ $ gem install guard-mocha-node
27
+
28
+ Add guard definition to your Guardfile by running this command:
29
+
30
+ $ guard init mocha-node
31
+
32
+ Usage
33
+ -----
34
+
35
+ $ guard
36
+
37
+ This will watch your project and execute your specs when files
38
+ change. It's worth checking out [the docs](https://github.com/guard/guard#readme).
39
+
40
+ Options
41
+ -------
42
+
43
+ * `:all_on_start # default => true`
44
+
45
+ Run all the specs as soon as Guard is started.
46
+
47
+ * `:all_after_pass # default => true`
48
+
49
+ When files are modified and the specs covering the modified files
50
+ pass, run all the specs automatically.
51
+
52
+ * `:keep_failed # default => true`
53
+
54
+ When files are modified, run failing specs as well as specs covering
55
+ the modified files.
56
+
57
+ * `:notify # default => true`
58
+
59
+ Display growl/libnotify notifications.
60
+
61
+ * `:coffeescript # default => true`
62
+
63
+ Load coffeescript and all execution of .coffee files.
64
+
65
+ * `:livescript # default => false`
66
+
67
+ Load livescript and all execution of .ls files.
68
+
69
+ * `:reporter # default => "spec"`
70
+
71
+ To select a mocha reporter
72
+
73
+ * `:require # default => nil`
74
+
75
+ Make mocha require the given modules, it should be a string or a array
76
+ of strings if multiple modules are to be required
77
+
78
+ * `:color # default => true`
79
+
80
+ Enable or disable the mocha color output
81
+
82
+ * `:recursive # default => true`
83
+
84
+ Enable or disable the recursive directory mocha option
85
+
86
+ * `:paths_for_all_specs # default => ['spec']`
87
+
88
+ Paths for run all specs
89
+
90
+ * `:globals # default => []`
91
+
92
+ Globals to ignore when performing global leak detection
93
+
94
+ * `:mocha_bin`
95
+
96
+ Specify the path to the jasmine-node binary that will execute your specs.
97
+
98
+ The default `:mocha_bin` in the Guardfile assumes:
99
+
100
+ * you are running guard from the root of the project
101
+ * you installed mocha using npm
102
+ * you installed mocha locally to node_modules
103
+
104
+ If you delete the option completely from the Guardfile, it assumes the
105
+ mocha binary is already in your `$PATH`.
106
+
107
+ So if you have installed jasmine-node globally using e.g. `npm install
108
+ -g mocha`, remove the `:mocha_bin` option from the Guardfile.
109
+
110
+ Guardfile
111
+ ---------
112
+
113
+ Please read the [guard docs](https://github.com/guard/guard#readme) for
114
+ more information about the Guardfile DSL.
115
+
116
+ It's powerful stuff.
117
+
118
+
119
+ TODO
120
+ ----
121
+
122
+ * write a JsonFormatter for jasmine-node so we have finer-grained
123
+ control over rendering output
124
+ * write an RSpec-style progress formatter (aka lots of green dots)
125
+ * patch Guard to locate CamelCased modules correctly
126
+
127
+ Testing
128
+ -------
129
+
130
+ $ rake
131
+
132
+ Author
133
+ ------
134
+
135
+ [Roberto Huelga Díaz](https://github.com/kanzeon)
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "guard/mocha_node/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "guard-mocha-node"
7
+ s.version = Guard::MochaNodeVersion::VERSION
8
+ s.authors = ["dave@kapoq.com", "David Schoen <dave@lyte.id.au>"]
9
+ s.email = ["dave@kapoq.com", "dave@lyte.id.au"]
10
+ s.homepage = "https://github.com/kanzeon/guard-mocha-node"
11
+ s.summary = %q{Guard::MochaNode automatically runs your Mocha Node specs when files are modified}
12
+ s.description = %q{}
13
+
14
+ s.rubyforge_project = "guard-mocha-node"
15
+
16
+ s.add_dependency "guard", ">= 0.4"
17
+
18
+ s.add_development_dependency "rspec"
19
+ s.add_development_dependency "guard-rspec"
20
+ s.add_development_dependency "rake"
21
+ if RUBY_PLATFORM =~ /linux/
22
+ s.add_development_dependency "rb-inotify"
23
+ s.add_development_dependency "libnotify"
24
+ end
25
+
26
+ s.files = `git ls-files`.split("\n")
27
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
28
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
29
+ s.require_paths = ["lib"]
30
+ end
@@ -0,0 +1,25 @@
1
+ require 'guard/mocha_node'
2
+
3
+ Guard::Mochanode = Guard::MochaNode
4
+
5
+ module Guard
6
+ class Mochanode < Guard
7
+ GEM_NAME = "mocha-node"
8
+
9
+ # Guardfile template needed inside guard gem
10
+ def self.init(name)
11
+ if ::Guard::Dsl.guardfile_include?(GEM_NAME)
12
+ ::Guard::UI.info "Guardfile already includes #{GEM_NAME} guard"
13
+ else
14
+ content = File.read('Guardfile')
15
+ guard = File.read("#{::Guard.locate_guard(GEM_NAME)}/lib/guard/mocha_node/templates/Guardfile")
16
+ File.open('Guardfile', 'wb') do |f|
17
+ f.puts(content)
18
+ f.puts("")
19
+ f.puts(guard)
20
+ end
21
+ ::Guard::UI.info "#{name} guard added to Guardfile, feel free to edit it"
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,90 @@
1
+ require 'open3'
2
+ require 'guard/ui'
3
+
4
+ module Guard
5
+ class MochaNode
6
+ module Runner
7
+ def self.run(paths = [], options = {})
8
+ return false if paths.empty?
9
+
10
+ @paths = paths
11
+ @options = options
12
+
13
+ print_message
14
+ execute_mocha_node_command
15
+ end
16
+
17
+ private
18
+
19
+ def self.print_message
20
+ message = @options[:message]
21
+ is_all_specs = @paths.sort == @options[:paths_for_all_specs].sort
22
+ message ||= is_all_specs ? "Running all specs" : "Running: #{@paths.join(' ')}"
23
+ ::Guard::UI.info(message, :reset => true)
24
+ end
25
+
26
+ def self.execute_mocha_node_command
27
+ ::Open3.popen3(*mocha_node_command)
28
+ end
29
+
30
+ def self.mocha_node_command
31
+ argvs = [ @options[:mocha_bin] ]
32
+ argvs += command_line_options
33
+ argvs += @paths
34
+ argvs.map(&:to_s)
35
+ end
36
+
37
+ def self.command_line_options
38
+ options = []
39
+ compilers = []
40
+
41
+ if @options[:coffeescript]
42
+ compilers << "coffee:coffee-script"
43
+ end
44
+
45
+ if @options[:livescript]
46
+ compilers << "ls:LiveScript"
47
+ end
48
+
49
+ if not compilers.empty?
50
+ options << "--compilers"
51
+ options << compilers.join(",")
52
+ end
53
+
54
+ if @options[:recursive]
55
+ options << "--recursive"
56
+ end
57
+
58
+ if @options[:require]
59
+ r = @options[:require]
60
+ r = [r] if not r.instance_of? Array
61
+
62
+ r.each { |e|
63
+ options << "-r"
64
+ options << e
65
+ }
66
+ end
67
+
68
+ if @options[:color]
69
+ options << "-c"
70
+ else
71
+ options << "-C"
72
+ end
73
+
74
+ if @options[:globals] and not @options[:globals].empty?
75
+ options << "--globals"
76
+ options << @options[:globals].join(',')
77
+ end
78
+
79
+ if @options[:reporter]
80
+ options << "--reporter"
81
+ options << @options[:reporter]
82
+ end
83
+
84
+ # puts "---- printing the options"
85
+ # puts options
86
+ options
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,73 @@
1
+ module Guard
2
+ class MochaNode
3
+ class SpecState
4
+ STDIN = 0
5
+ STDOUT = 1
6
+ STDERR = 2
7
+ THREAD = 3
8
+
9
+ SUCCESS_CODE = 0
10
+ ERROR_CODE = 1
11
+
12
+ attr_accessor :failing_paths
13
+
14
+ def initialize
15
+ clear!
16
+ end
17
+
18
+ def update(run_paths = [], options = {})
19
+ @run_paths = run_paths
20
+ @io = Runner.run(@run_paths, options)
21
+ @stdout = @io[STDOUT]
22
+ @stderr = @io[STDERR]
23
+ # stream stdout immediately
24
+ until @stdout.eof?
25
+ line = @stdout.gets
26
+ print line if !line.strip.empty?
27
+ end
28
+ @stderr.lines { |line| print line }
29
+ @exitstatus = @io[THREAD].value rescue ERROR_CODE
30
+ close_io
31
+ update_passed_and_fixed
32
+ update_failing_paths
33
+ passing?
34
+ end
35
+
36
+ def passing?
37
+ @passed
38
+ end
39
+
40
+ def fixed?
41
+ @fixed
42
+ end
43
+
44
+ def clear!
45
+ @passed = true
46
+ @fixed = false
47
+ @failing_paths = []
48
+ end
49
+
50
+ private
51
+
52
+ def close_io
53
+ @io[STDIN..STDERR].each { |s| s.close }
54
+ end
55
+
56
+ def update_passed_and_fixed
57
+ previously_failed = !passing?
58
+ @passed = @exitstatus == SUCCESS_CODE
59
+ @fixed = @passed && previously_failed
60
+ end
61
+
62
+ def update_failing_paths
63
+ if @run_paths.any?
64
+ @failing_paths = if passing?
65
+ @failing_paths - @run_paths
66
+ else
67
+ @failing_paths + @run_paths
68
+ end.uniq
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,17 @@
1
+ # Installed by guard-mocha-node
2
+
3
+ # JavaScript/CoffeeScript watchers
4
+
5
+ guard 'mocha-node', :mocha_bin => File.expand_path(File.dirname(__FILE__) + "/node_modules/mocha/bin/mocha") do
6
+ watch(%r{^spec/(.+)_spec\.(js\.coffee|js|coffee)}) { |m| "spec/#{m[1]}_spec.#{m[2]}" }
7
+ watch(%r{^lib/(.+)\.(js\.coffee|js|coffee)}) { |m| "spec/lib/#{m[1]}_spec.#{m[2]}" }
8
+ watch(%r{spec/spec_helper\.(js\.coffee|js|coffee)}) { "spec" }
9
+ end
10
+
11
+ # JavaScript only watchers
12
+ #
13
+ # guard "mocha-node", :mocha_bin => File.expand_path(File.dirname(__FILE__) + "/node_modules/mocha/bin/mocha") do
14
+ # watch(%r{^spec/.+_spec\.js$})
15
+ # watch(%r{^lib/(.+)\.js$}) { |m| "spec/lib/#{m[1]}_spec.js" }
16
+ # watch('spec/spec_helper.js')
17
+ # end
@@ -0,0 +1,5 @@
1
+ module Guard
2
+ module MochaNodeVersion
3
+ VERSION = "0.0.3"
4
+ end
5
+ end
@@ -0,0 +1,88 @@
1
+ require 'guard'
2
+ require 'guard/guard'
3
+
4
+ module Guard
5
+ class MochaNode < Guard
6
+ DEFAULT_OPTIONS = {
7
+ :mocha_bin => "mocha",
8
+ :all_after_pass => true,
9
+ :all_on_start => true,
10
+ :keep_failed => true,
11
+ :notify => true,
12
+ :coffeescript => true,
13
+ :livescript => false,
14
+ :verbose => true,
15
+ :reporter => "spec",
16
+ :color => true,
17
+ :recursive => true,
18
+ :require => nil,
19
+ :paths_for_all_specs => %w(spec),
20
+ :globals => []
21
+ }
22
+
23
+ autoload :Runner, "guard/mocha_node/runner"
24
+ autoload :SpecState, "guard/mocha_node/spec_state"
25
+
26
+ def initialize(watchers = [], options = {})
27
+ super(watchers, DEFAULT_OPTIONS.merge(options))
28
+ @state = SpecState.new
29
+ end
30
+
31
+ def start
32
+ run_all if options[:all_on_start]
33
+ end
34
+
35
+ def run_all
36
+ run( options[:paths_for_all_specs])
37
+ notify(:all)
38
+ end
39
+
40
+ def run_on_change(changed_paths = [])
41
+ run_paths = if options[:keep_failed]
42
+ failing_paths + changed_paths
43
+ else
44
+ changed_paths
45
+ end
46
+
47
+ run(run_paths)
48
+ notify(:some)
49
+
50
+ run_all if passing? and options[:all_after_pass]
51
+ end
52
+
53
+ def failing_paths
54
+ @state.failing_paths
55
+ end
56
+
57
+ def passing?
58
+ @state.passing?
59
+ end
60
+
61
+ def fixed?
62
+ @state.fixed?
63
+ end
64
+
65
+ private
66
+
67
+ def run(run_paths = [], runner_options = {}, notifications = {})
68
+ ::Guard::Notifier.notify "Guard mocha runs for #{run_paths.join(', ')}"
69
+ @state.update(run_paths, options.merge(runner_options))
70
+ end
71
+
72
+ def notify(scope = :all)
73
+ return unless options[:notify]
74
+
75
+ message = if passing?
76
+ if fixed?
77
+ scope == :all ? "All fixed" : "Specs fixed"
78
+ else
79
+ scope == :all ? "All specs pass" : "Specs pass"
80
+ end
81
+ else
82
+ "Some specs failing"
83
+ end
84
+ image = passing? ? :success : :failed
85
+ ::Guard::Notifier.notify(message, :image => image, :title => "mocha-node")
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,268 @@
1
+ require 'spec_helper'
2
+
3
+ describe Guard::MochaNode do
4
+ let(:state) { Guard::MochaNode::SpecState.new }
5
+ let(:guard) { Guard::MochaNode.new }
6
+
7
+ before do
8
+ Guard::MochaNode::SpecState.stub(:new => state)
9
+ Guard::Notifier.stub(:notify)
10
+ state.stub(:update => true)
11
+ end
12
+
13
+ describe "#initialize" do
14
+ context "when no options are given" do
15
+ it "sets a default path to mocha-node bin" do
16
+ guard.options[:mocha_bin].should eql "mocha"
17
+ end
18
+
19
+ it "sets :notify option to true" do
20
+ guard.options[:notify].should eql true
21
+ end
22
+
23
+ it "sets :all_after_pass option to true" do
24
+ guard.options[:all_after_pass].should be_true
25
+ end
26
+
27
+ it "sets :all_on_start option to true" do
28
+ guard.options[:all_on_start].should be_true
29
+ end
30
+
31
+ it "sets :keep_failed option to true" do
32
+ guard.options[:keep_failed].should be_true
33
+ end
34
+
35
+ it "sets :coffescript option to true" do
36
+ guard.options[:coffeescript].should be_true
37
+ end
38
+
39
+ it "sets :livescript option to true" do
40
+ guard.options[:livescript].should be_false
41
+ end
42
+
43
+ it "sets :verbose option to true" do
44
+ guard.options[:verbose].should be_true
45
+ end
46
+
47
+ it "sets :reporter option to 'spec'" do
48
+ guard.options[:reporter].should eql "spec"
49
+ end
50
+
51
+ it "sets :color option to true" do
52
+ guard.options[:color].should eql true
53
+ end
54
+
55
+ it "sets :recursive option to true" do
56
+ guard.options[:recursive].should eql true
57
+ end
58
+
59
+ it "sets :require option to nil" do
60
+ guard.options[:require].should_not be
61
+ end
62
+
63
+ it "sets :paths_for_all_specs option to ['spec']" do
64
+ guard.options[:paths_for_all_specs].should eql ['spec']
65
+ end
66
+
67
+ it "sets :globals option to []" do
68
+ guard.options[:globals].should eql []
69
+ end
70
+
71
+ it "is passing" do
72
+ guard.should be_passing
73
+ end
74
+
75
+ it "has no failing paths" do
76
+ guard.failing_paths.should be_empty
77
+ end
78
+ end
79
+
80
+ context "when options are given" do
81
+ let(:a_path) { "/foo/bar/mocha-node" }
82
+ let(:guard) { Guard::MochaNode.new([], {
83
+ :mocha_bin => a_path,
84
+ :all_on_start => false,
85
+ :all_after_pass => false,
86
+ :keep_failed => false,
87
+ :notify => false,
88
+ :coffeescript => false,
89
+ :livescript => true,
90
+ :reporter => 'spec',
91
+ :color => false,
92
+ :recursive => false,
93
+ :require => "should",
94
+ :paths_for_all_specs => %w(test),
95
+ :globals => ['Foo']
96
+ }) }
97
+
98
+ it "sets the path to mocha bin" do
99
+ guard.options[:mocha_bin].should eql a_path
100
+ end
101
+
102
+ it "sets the :notify option" do
103
+ guard.options[:notify].should be_false
104
+ end
105
+
106
+ it "sets the :all_after_pass option" do
107
+ guard.options[:all_after_pass].should be_false
108
+ end
109
+
110
+ it "sets the :all_on_start option" do
111
+ guard.options[:all_on_start].should be_false
112
+ end
113
+
114
+ it "sets the :keep_failed option" do
115
+ guard.options[:keep_failed].should be_false
116
+ end
117
+
118
+ it "sets the :coffeescript option" do
119
+ guard.options[:coffeescript].should be_false
120
+ end
121
+
122
+ it "sets the :livescript option" do
123
+ guard.options[:livescript].should be_true
124
+ end
125
+
126
+ it "sets the :reporter option" do
127
+ guard.options[:reporter].should eql 'spec'
128
+ end
129
+ it "sets the :color option" do
130
+ guard.options[:color].should be_false
131
+ end
132
+ it "sets the :recursive option" do
133
+ guard.options[:recursive].should be_false
134
+ end
135
+ it "sets the :require option" do
136
+ guard.options[:require].should eql "should"
137
+ end
138
+ it "sets the :paths_for_all_specs option" do
139
+ guard.options[:paths_for_all_specs].should eql ['test']
140
+ end
141
+ it "sets the :globals option" do
142
+ guard.options[:globals].should eql ['Foo']
143
+ end
144
+ end
145
+ end
146
+
147
+ describe "#start" do
148
+ context "when :all_on_start is true" do
149
+ it "runs all" do
150
+ guard.should_receive(:run_all)
151
+ guard.start
152
+ end
153
+ end
154
+
155
+ context "when :all_on_start is false" do
156
+ let(:guard) { Guard::MochaNode.new([], { :all_on_start => false }) }
157
+
158
+ it "does not run all" do
159
+ guard.should_not_receive(:run_all)
160
+ guard.start
161
+ end
162
+ end
163
+ end
164
+
165
+ describe "#run_all" do
166
+ it "updates the state with the specs in the spec dir" do
167
+ state.should_receive(:update).with(["spec"], anything)
168
+ guard.run_all
169
+ end
170
+
171
+ it "passes the options through to the state" do
172
+ an_option = { :option => "value" }
173
+ guard.options.update(an_option)
174
+ state.should_receive(:update).with(anything, hash_including(an_option))
175
+ guard.run_all
176
+ end
177
+
178
+ it "notifies the user with the outcome of running all specs" do
179
+ guard.should_receive(:notify).with(:all)
180
+ guard.run_all
181
+ end
182
+ end
183
+
184
+ describe "#run_on_change" do
185
+ before do
186
+ guard.options[:all_after_pass] = false
187
+ end
188
+
189
+ it "updates the state with paths" do
190
+ state.should_receive(:update).with(["/a/path"], anything)
191
+ guard.run_on_change(["/a/path"])
192
+ end
193
+
194
+ it "passes options through to the state" do
195
+ an_option = { :option => "value" }
196
+ guard.options.update(an_option)
197
+ state.should_receive(:update).with(anything, hash_including(an_option))
198
+ guard.run_on_change
199
+ end
200
+
201
+ it "notifies the user with the outcome of running the specs" do
202
+ guard.should_receive(:notify).with(:some)
203
+ guard.run_on_change
204
+ end
205
+
206
+ context "when specs pass" do
207
+ before do
208
+ guard.stub(:passing? => true)
209
+ end
210
+
211
+ context "and :all_after_pass is true" do
212
+ before do
213
+ guard.options[:all_after_pass] = true
214
+ end
215
+
216
+ it "runs all" do
217
+ guard.should_receive(:run_all)
218
+ guard.run_on_change
219
+ end
220
+ end
221
+
222
+ context "and :all_after_pass is false" do
223
+ before do
224
+ guard.options[:all_after_pass] = false
225
+ end
226
+
227
+ context "if :all_after_pass is true" do
228
+ it "does not run all" do
229
+ guard.should_not_receive(:run_all)
230
+ guard.run_on_change
231
+ end
232
+ end
233
+ end
234
+ end
235
+
236
+ context "when there are failing paths" do
237
+ let(:failing_paths) { %w(foo/bar zip/zap) }
238
+ let(:changed_paths) { %w(aaa/bbb ccc/ddd) }
239
+ let(:all_paths) { failing_paths + changed_paths }
240
+
241
+ before do
242
+ guard.stub(:failing_paths => failing_paths)
243
+ end
244
+
245
+ context "and :keep_failed is true" do
246
+ before do
247
+ guard.options[:keep_failed] = true
248
+ end
249
+
250
+ it "updates state with failing paths and the changed paths" do
251
+ state.should_receive(:update).with(all_paths, anything)
252
+ guard.run_on_change(changed_paths)
253
+ end
254
+ end
255
+
256
+ context "and :keep_failed is false" do
257
+ before do
258
+ guard.options[:keep_failed] = false
259
+ end
260
+
261
+ it "updates state with only the changed paths" do
262
+ state.should_receive(:update).with(changed_paths, anything)
263
+ guard.run_on_change(changed_paths)
264
+ end
265
+ end
266
+ end
267
+ end
268
+ end
@@ -0,0 +1,231 @@
1
+ require 'spec_helper'
2
+
3
+ describe Guard::MochaNode::Runner do
4
+ let(:runner) { Guard::MochaNode::Runner }
5
+
6
+ before do
7
+ Open3.stub(:popen3 => "response")
8
+ end
9
+
10
+ describe ".run" do
11
+ let(:options) { { :paths_for_all_specs => %w(spec)} }
12
+ context "when passed no paths" do
13
+ it "returns false" do
14
+ runner.run.should be_false
15
+ end
16
+ end
17
+
18
+ context "when passed paths" do
19
+ let(:some_paths) { %w(/foo/bar /zip/zap) }
20
+
21
+ it "executes mocha node" do
22
+ Open3.should_receive(:popen3) do |*args|
23
+ args[0].should eq "__EXECUTABLE__"
24
+ end
25
+ runner.run(some_paths, options.merge({ :mocha_bin => "__EXECUTABLE__"}))
26
+ end
27
+
28
+ it "passes the paths to the executable" do
29
+ Open3.should_receive(:popen3) do |*args|
30
+ last_args = args[(some_paths.length * -1)..(-1)]
31
+ last_args.should eql some_paths
32
+ end
33
+ runner.run(some_paths, options)
34
+ end
35
+
36
+ context "and coffeescript option is true" do
37
+ it "passes the --compilers coffee:coffee-script option to mocha node" do
38
+ Open3.should_receive(:popen3) do |*args|
39
+ index_compilers = args.find_index "--compilers"
40
+ index_compilers.should_not be nil
41
+ args[index_compilers +1].should eql "coffee:coffee-script"
42
+ end
43
+ runner.run(some_paths, options.merge({ :coffeescript => true}))
44
+ end
45
+ end
46
+
47
+ context "and coffeescript option is false" do
48
+ it "does not pass the --compilers coffee:coffee-script option to mocha node" do
49
+ Open3.should_receive(:popen3) do |*args|
50
+ index_compilers = args.find_index "--compilers"
51
+ if index_compilers != nil
52
+ args[index_compilers +1].should_not match /coffee:coffee-script/
53
+ end
54
+ end
55
+ runner.run(some_paths, options.merge({ :coffeescript => false}))
56
+ end
57
+ end
58
+
59
+ context "and livescript option is true" do
60
+ it "passes the --compilers ls:LiveScript option to mocha node" do
61
+ Open3.should_receive(:popen3) do |*args|
62
+ index_compilers = args.find_index "--compilers"
63
+ index_compilers.should_not be nil
64
+ args[index_compilers +1].should eql "ls:LiveScript"
65
+ end
66
+ runner.run(some_paths, options.merge({ :livescript => true}))
67
+ end
68
+ end
69
+
70
+ context "and livescript option is false" do
71
+ it "does not pass the --compilers ls:LiveScript option to mocha node" do
72
+ Open3.should_receive(:popen3) do |*args|
73
+ index_compilers = args.find_index "--compilers"
74
+ if index_compilers != nil
75
+ args[index_compilers +1].should_not match /ls:LiveScript/
76
+ end
77
+ end
78
+ runner.run(some_paths, options.merge({ :livescript => false}))
79
+ end
80
+ end
81
+
82
+ context "and both coffeescript and livescript option are true" do
83
+ it "passes the --compilers coffee:coffee-script,ls:LiveScript option to mocha node" do
84
+ Open3.should_receive(:popen3) do |*args|
85
+ index_compilers = args.find_index "--compilers"
86
+ index_compilers.should_not be nil
87
+ args[index_compilers +1].should eql "coffee:coffee-script,ls:LiveScript"
88
+ end
89
+ runner.run(some_paths, options.merge({ :livescript => true, :coffeescript => true }))
90
+ end
91
+ end
92
+
93
+ context "and color option is true" do
94
+ it "passes the -c option to mocha node" do
95
+ Open3.should_receive(:popen3) do |*args|
96
+ args.should include "-c"
97
+ end
98
+ runner.run(some_paths, options.merge({ :color => true}))
99
+ end
100
+ end
101
+
102
+ context "and color option is false" do
103
+ it "passes the -C option to mocha node" do
104
+ Open3.should_receive(:popen3) do |*args|
105
+ args.should include "-C"
106
+ end
107
+ runner.run(some_paths, options.merge({ :color => false}))
108
+ end
109
+ end
110
+
111
+ context "and globals option is set" do
112
+ it "passes the --globals option to mocha node" do
113
+ Open3.should_receive(:popen3) do |*args|
114
+ args.should include("--globals", "Foo")
115
+ # ensure ordering
116
+ args[args.index("--globals") + 1].should eql("Foo")
117
+ end
118
+ runner.run(some_paths, options.merge({ :globals => ['Foo']}))
119
+ end
120
+ end
121
+
122
+ context "and globals option is empty" do
123
+ it "does not pass the --globals option to mocha node" do
124
+ Open3.should_receive(:popen3) do |*args|
125
+ args.should_not include "--globals"
126
+ end
127
+ runner.run(some_paths, options.merge({ :globals => []}))
128
+ end
129
+ end
130
+
131
+ context "and reporter option is set" do
132
+ it "passes the --reporter option to mocha node" do
133
+ Open3.should_receive(:popen3) do |*args|
134
+ args.should include("--reporter", "Foo")
135
+ # ensure ordering
136
+ args[args.index("--reporter") + 1].should eql("Foo")
137
+ end
138
+ runner.run(some_paths, options.merge({ :reporter => 'Foo' }))
139
+ end
140
+ end
141
+
142
+ context "and reporter option is not set" do
143
+ it "does not pass the --reporter option to mocha node" do
144
+ Open3.should_receive(:popen3) do |*args|
145
+ args.should_not include "--reporter"
146
+ end
147
+ runner.run(some_paths, options)
148
+ end
149
+ end
150
+
151
+ context "and recursive option is true" do
152
+ it "passes the --recursive option to mocha node" do
153
+ Open3.should_receive(:popen3) do |*args|
154
+ args.should include "--recursive"
155
+ end
156
+ runner.run(some_paths, options.merge({ :recursive => true}))
157
+ end
158
+ end
159
+
160
+ context "and recursive option is false" do
161
+ it "does not pass the --recursive option to mocha node" do
162
+ Open3.should_receive(:popen3) do |*args|
163
+ args.should_not include "--recursive"
164
+ end
165
+ runner.run(some_paths, options.merge({ :recursive => false}))
166
+ end
167
+ end
168
+
169
+ context "and require option is 'should'" do
170
+ it "passes the '-r should' option to mocha node" do
171
+ Open3.should_receive(:popen3) do |*args|
172
+ require_index = args.find_index '-r'
173
+ require_index.should_not eq nil
174
+ args[require_index+1].should eql "should"
175
+ end
176
+ runner.run(some_paths, options.merge({ :require => 'should'}))
177
+ end
178
+ end
179
+
180
+ context "and require option is ['should', 'chai']" do
181
+ it "passes the '-r should -r chai' option to mocha node" do
182
+ Open3.should_receive(:popen3) do |*args|
183
+ args.each_with_index.
184
+ reject{ |e,i| e != '-r' }.
185
+ map{ |e,i| args[i+1] }.should eql ["should", "chai"]
186
+
187
+ end
188
+ runner.run(some_paths, options.merge({ :require => ['should', 'chai'] }))
189
+ end
190
+ end
191
+
192
+ context "and require option is nil" do
193
+ it "does not pass the -r option to mocha node" do
194
+ Open3.should_receive(:popen3) do |*args|
195
+ args.should_not include "-r"
196
+ end
197
+ runner.run(some_paths, options.merge({ :require => nil}))
198
+ end
199
+ end
200
+
201
+ it "returns IO object" do
202
+ io_obj = double("io obj")
203
+ Open3.stub(:popen3 => io_obj)
204
+ runner.run(some_paths, options).should eql io_obj
205
+ end
206
+
207
+ context "when message option is given" do
208
+ it "outputs message" do
209
+ Guard::UI.should_receive(:info).with("hello", anything)
210
+ runner.run(some_paths, options.merge({ :message => "hello"}))
211
+ end
212
+ end
213
+
214
+ context "when no message option is given" do
215
+ context "and running all specs" do
216
+ it "outputs message confirming all specs are being run" do
217
+ Guard::UI.should_receive(:info).with("Running all specs", anything)
218
+ runner.run(%w(spec), options )
219
+ end
220
+ end
221
+
222
+ context "and running some specs" do
223
+ it "outputs paths of specs being run" do
224
+ Guard::UI.should_receive(:info).with("Running: /foo/bar /zip/zap", anything)
225
+ runner.run(some_paths, options)
226
+ end
227
+ end
228
+ end
229
+ end
230
+ end
231
+ end
@@ -0,0 +1,127 @@
1
+ require 'spec_helper'
2
+
3
+ describe Guard::MochaNode::SpecState do
4
+ let(:state) { Guard::MochaNode::SpecState.new }
5
+ let(:runner) { Guard::MochaNode::Runner }
6
+
7
+ describe "#initialize" do
8
+ it "is passing" do
9
+ state.should be_passing
10
+ end
11
+
12
+ it "has no failing paths" do
13
+ state.failing_paths.should be_empty
14
+ end
15
+
16
+ it "is has not been fixed" do
17
+ state.should_not be_fixed
18
+ end
19
+ end
20
+
21
+ describe "#update" do
22
+ let(:io) { [
23
+ double("stdin", :close => true),
24
+ double("stdout", :close => true, :lines => [], :eof? => true),
25
+ double("stderr", :close => true, :lines => []),
26
+ double("thread", :value => 0)
27
+ ] }
28
+ let(:some_paths) { %w(some paths) }
29
+ let(:some_options) { double("some options") }
30
+
31
+ before do
32
+ runner.stub(:run => io)
33
+ end
34
+
35
+ it "runs the runner with the paths and options" do
36
+ runner.should_receive(:run).with(some_paths, some_options).and_return(io)
37
+ state.update(some_paths, some_options)
38
+ end
39
+
40
+ it "closes stdin, stdout, and stderr of the subprocess" do
41
+ io[0..2].each { |i| i.should_receive(:close) }
42
+ state.update
43
+ end
44
+
45
+ context "when the runner process exit value is zero" do
46
+ before do
47
+ io[3].stub(:value => 0)
48
+ state.update
49
+ end
50
+
51
+ it "is passing" do
52
+ state.should be_passing
53
+ end
54
+
55
+ context "and there are run paths" do
56
+ it "removes the run paths from the failing paths" do
57
+ state.failing_paths = %w(/keep /remove)
58
+ state.update(%w(/remove))
59
+ state.failing_paths.should eql %w(/keep)
60
+ end
61
+ end
62
+
63
+ context "and there are no run paths" do
64
+ it "does not change the current failing paths" do
65
+ original_failing_paths = %w(/keep1 /keep2)
66
+ state.failing_paths = original_failing_paths
67
+ state.update
68
+ state.failing_paths.should eql original_failing_paths
69
+ end
70
+ end
71
+
72
+ context "and the previous spec failed" do
73
+ before do
74
+ state.stub(:passing? => false)
75
+ state.update
76
+ end
77
+
78
+ it "is fixed" do
79
+ state.should be_fixed
80
+ end
81
+ end
82
+
83
+ context "and the previous spec passed" do
84
+ before do
85
+ state.stub(:passing? => true)
86
+ state.update
87
+ end
88
+
89
+ it "is not fixed" do
90
+ state.should_not be_fixed
91
+ end
92
+ end
93
+ end
94
+
95
+ context "when the runner process exit value is not zero" do
96
+ before do
97
+ io[3].stub(:value => 1)
98
+ state.update(some_paths, some_options)
99
+ end
100
+
101
+ it "is not passing" do
102
+ state.should_not be_passing
103
+ end
104
+
105
+ it "is not fixed" do
106
+ state.should_not be_fixed
107
+ end
108
+
109
+ context "and there are run paths" do
110
+ it "updates the failing paths with the union of the failing paths and the run paths" do
111
+ state.failing_paths = %w(/dupe /other)
112
+ state.update(%w(/dupe /another))
113
+ state.failing_paths.should =~ %w(/dupe /other /another)
114
+ end
115
+ end
116
+
117
+ context "and there are no run paths" do
118
+ it "does not change the current failing paths" do
119
+ original_failing_paths = %w(/keep1 /keep2)
120
+ state.failing_paths = original_failing_paths
121
+ state.update
122
+ state.failing_paths.should eql original_failing_paths
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,17 @@
1
+ require 'rspec'
2
+ require 'guard/mocha_node'
3
+
4
+ RSpec.configure do |config|
5
+ config.color_enabled = true
6
+ config.filter_run :focus => true
7
+ config.run_all_when_everything_filtered = true
8
+
9
+ config.before do
10
+ ENV["GUARD_ENV"] = "test"
11
+ @project_path = Pathname.new(File.expand_path("../../", __FILE__))
12
+ end
13
+
14
+ config.after do
15
+ ENV["GUARD_ENV"] = nil
16
+ end
17
+ end
metadata ADDED
@@ -0,0 +1,161 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: guard-mocha-node
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - dave@kapoq.com
9
+ - David Schoen <dave@lyte.id.au>
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2013-04-21 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: guard
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0.4'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ! '>='
29
+ - !ruby/object:Gem::Version
30
+ version: '0.4'
31
+ - !ruby/object:Gem::Dependency
32
+ name: rspec
33
+ requirement: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ! '>='
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ type: :development
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: guard-rspec
49
+ requirement: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ - !ruby/object:Gem::Dependency
64
+ name: rake
65
+ requirement: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ! '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ type: :development
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ - !ruby/object:Gem::Dependency
80
+ name: rb-inotify
81
+ requirement: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ! '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ type: :development
88
+ prerelease: false
89
+ version_requirements: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ! '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ - !ruby/object:Gem::Dependency
96
+ name: libnotify
97
+ requirement: !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - ! '>='
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: ''
112
+ email:
113
+ - dave@kapoq.com
114
+ - dave@lyte.id.au
115
+ executables: []
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - .gitignore
120
+ - CHANGELOG.md
121
+ - Gemfile
122
+ - Guardfile
123
+ - README.md
124
+ - Rakefile
125
+ - guard-mocha-node.gemspec
126
+ - lib/guard/mocha-node.rb
127
+ - lib/guard/mocha_node.rb
128
+ - lib/guard/mocha_node/runner.rb
129
+ - lib/guard/mocha_node/spec_state.rb
130
+ - lib/guard/mocha_node/templates/Guardfile
131
+ - lib/guard/mocha_node/version.rb
132
+ - spec/lib/mocha_node_spec.rb
133
+ - spec/lib/runner_spec.rb
134
+ - spec/lib/spec_state_spec.rb
135
+ - spec/spec_helper.rb
136
+ homepage: https://github.com/kanzeon/guard-mocha-node
137
+ licenses: []
138
+ post_install_message:
139
+ rdoc_options: []
140
+ require_paths:
141
+ - lib
142
+ required_ruby_version: !ruby/object:Gem::Requirement
143
+ none: false
144
+ requirements:
145
+ - - ! '>='
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ required_rubygems_version: !ruby/object:Gem::Requirement
149
+ none: false
150
+ requirements:
151
+ - - ! '>='
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ requirements: []
155
+ rubyforge_project: guard-mocha-node
156
+ rubygems_version: 1.8.23
157
+ signing_key:
158
+ specification_version: 3
159
+ summary: Guard::MochaNode automatically runs your Mocha Node specs when files are
160
+ modified
161
+ test_files: []