beholder 0.0.1 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +48 -58
- data/bin/beholder +1 -1
- data/lib/beholder.rb +225 -54
- data/spec/beholder_spec.rb +168 -0
- data/spec/setup.rb +2 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +11 -0
- metadata +51 -20
- data/README.textile +0 -13
- data/TODO +0 -1
- data/examples/example_helper.rb +0 -19
- data/examples/lib/beholder_example.rb +0 -89
data/Rakefile
CHANGED
@@ -1,68 +1,58 @@
|
|
1
|
-
|
2
|
-
require '
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
s.homepage = HOMEPAGE
|
25
|
-
|
26
|
-
# Uncomment this to add a dependency
|
27
|
-
s.add_dependency "fsevents"
|
28
|
-
s.bindir = 'bin'
|
29
|
-
s.default_executable = 'beholder'
|
30
|
-
s.executables = ["beholder"]
|
31
|
-
s.require_path = 'lib'
|
32
|
-
s.autorequire = GEM
|
33
|
-
s.files = %w(LICENSE README.textile Rakefile TODO) + Dir.glob("{lib,examples}/**/*")
|
1
|
+
begin
|
2
|
+
require 'jeweler'
|
3
|
+
Jeweler::Tasks.new do |gem|
|
4
|
+
gem.name = "beholder"
|
5
|
+
gem.summary = "An ancient beholder that watches your treasure, and deals with thiefs"
|
6
|
+
gem.email = "chad@spicycode.com, rsanheim@gmail.com"
|
7
|
+
gem.homepage = "http://github.com/rsanheim/beholder"
|
8
|
+
gem.description = "beholder"
|
9
|
+
gem.authors = "Chad Humphries, Rob Sanheim"
|
10
|
+
gem.has_rdoc = true
|
11
|
+
gem.extra_rdoc_files = ["README.md", "LICENSE"]
|
12
|
+
gem.bindir = 'bin'
|
13
|
+
gem.default_executable = 'beholder'
|
14
|
+
gem.executables = ["beholder"]
|
15
|
+
gem.require_path = 'lib'
|
16
|
+
gem.files = %w(LICENSE README.md Rakefile) + Dir.glob("{lib,spec}/**/*")
|
17
|
+
gem.add_dependency "fsevents"
|
18
|
+
gem.add_development_dependency "rspec"
|
19
|
+
gem.add_development_dependency "yard"
|
20
|
+
gem.add_development_dependency "rr", ">= 0.7.0"
|
21
|
+
end
|
22
|
+
rescue LoadError
|
23
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
34
24
|
end
|
35
25
|
|
36
|
-
|
37
|
-
|
38
|
-
end
|
26
|
+
begin
|
27
|
+
require 'spec/rake/spectask'
|
39
28
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
29
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
30
|
+
spec.libs << 'lib' << 'spec'
|
31
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
32
|
+
spec.spec_opts = ['-c', '-fn']
|
33
|
+
end
|
44
34
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
35
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
36
|
+
spec.libs << 'lib' << 'spec'
|
37
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
38
|
+
spec.rcov = true
|
39
|
+
spec.spec_opts = ['-c', '-fn']
|
49
40
|
end
|
50
|
-
end
|
51
41
|
|
52
|
-
|
53
|
-
Micronaut::RakeTask.new :examples do |t|
|
54
|
-
t.pattern = "examples/**/*_example.rb"
|
55
|
-
end
|
42
|
+
task :spec => :check_dependencies
|
56
43
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
t.pattern = "examples/**/*_example.rb"
|
62
|
-
t.rcov = true
|
63
|
-
t.rcov_opts = "--exclude \"examples/*,gems/*,db/*,/Library/Frameworks/*,/Library/Ruby/*,config/*\" --text-summary --sort coverage --no-validator-links"
|
44
|
+
task :default => :spec
|
45
|
+
rescue LoadError
|
46
|
+
task :default do
|
47
|
+
abort "Rspec is not available."
|
64
48
|
end
|
65
|
-
|
66
49
|
end
|
67
50
|
|
68
|
-
|
51
|
+
begin
|
52
|
+
require 'yard'
|
53
|
+
YARD::Rake::YardocTask.new
|
54
|
+
rescue LoadError
|
55
|
+
task :yardoc do
|
56
|
+
abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
|
57
|
+
end
|
58
|
+
end
|
data/bin/beholder
CHANGED
data/lib/beholder.rb
CHANGED
@@ -1,89 +1,260 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
gem :fsevents
|
3
2
|
require 'fsevents'
|
4
3
|
|
5
4
|
class Beholder
|
5
|
+
DEFAULT_RUNNER = 'ruby'
|
6
|
+
|
7
|
+
class << self
|
8
|
+
attr_writer :test_types, :possible_treasure_map_locations
|
9
|
+
attr_accessor :on_success, :on_failure
|
10
|
+
|
11
|
+
def runner
|
12
|
+
@runner ||= ::Beholder::DEFAULT_RUNNER
|
13
|
+
end
|
14
|
+
|
15
|
+
def runner=(new_runner)
|
16
|
+
@runner = new_runner
|
17
|
+
end
|
18
|
+
|
19
|
+
def possible_treasure_map_locations
|
20
|
+
@possible_treasure_map_locations ||= ["#{Dir.pwd}/.treasure_map.rb", "#{Dir.pwd}/treasure_map.rb", "#{Dir.pwd}/config/treasure_map.rb"]
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_types
|
24
|
+
@test_types ||= %w{spec examples test}
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_extensions
|
28
|
+
@test_extensions ||= %w{spec example test}
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_directories
|
32
|
+
return @test_directories if @test_directories
|
33
|
+
@test_directories = []
|
34
|
+
test_types.each do |test_type|
|
35
|
+
@test_directories << test_type if File.exist?(test_type)
|
36
|
+
end
|
37
|
+
@test_directories
|
38
|
+
end
|
39
|
+
|
40
|
+
def all_tests
|
41
|
+
lambda {
|
42
|
+
dirs = []
|
43
|
+
test_directories.each do |dir|
|
44
|
+
test_extensions.each do |test_ext|
|
45
|
+
files = Dir["#{dir}/**/*_#{test_ext}.rb"]
|
46
|
+
# Ignore tarantula tests for now until we add a cleaner way
|
47
|
+
files.reject! { |file| file.include?('tarantula/') }
|
48
|
+
next if files.empty?
|
49
|
+
dirs << files
|
50
|
+
end
|
51
|
+
end
|
52
|
+
dirs.flatten!
|
53
|
+
}.call
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
attr_reader :paths_to_watch, :sent_an_int, :mappings, :be_verbose
|
58
|
+
attr_reader :watcher, :treasure_maps
|
6
59
|
|
7
|
-
attr_reader :paths_to_watch, :sent_an_int, :mappings, :working_directory, :be_verbose, :the_eye
|
8
|
-
|
9
60
|
def initialize
|
10
|
-
@paths_to_watch = [
|
61
|
+
@paths_to_watch = []
|
62
|
+
@mappings, @treasure_maps = {}, {}
|
11
63
|
@sent_an_int = false
|
12
|
-
@mappings = {}
|
13
|
-
@working_directory = Dir.pwd
|
14
64
|
@be_verbose = ARGV.include?("-v") || ARGV.include?("--verbose")
|
15
65
|
end
|
16
|
-
|
17
|
-
def
|
18
|
-
|
19
|
-
|
20
|
-
|
66
|
+
|
67
|
+
def run
|
68
|
+
read_all_maps
|
69
|
+
prepare
|
70
|
+
start
|
21
71
|
end
|
22
|
-
|
23
|
-
def
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
blink
|
28
|
-
puts "\n\nWaiting to hear from the disk since #{Time.now}"
|
29
|
-
end
|
30
|
-
@the_eye.run
|
72
|
+
|
73
|
+
def self.run
|
74
|
+
beholder = new
|
75
|
+
beholder.run
|
76
|
+
self
|
31
77
|
end
|
32
|
-
|
33
|
-
def
|
34
|
-
@
|
78
|
+
|
79
|
+
def map_for(map_name)
|
80
|
+
@treasure_maps[map_name] ||= []
|
81
|
+
@current_map = @treasure_maps[map_name]
|
82
|
+
yield self if block_given?
|
83
|
+
ensure
|
84
|
+
@current_map = nil
|
35
85
|
end
|
36
86
|
|
37
|
-
def
|
38
|
-
|
87
|
+
def prepare_spell_for(pattern, options = {}, &blk)
|
88
|
+
@current_map << [pattern, options, blk]
|
89
|
+
end
|
90
|
+
|
91
|
+
def keep_a_watchful_eye_for(*paths)
|
92
|
+
@paths_to_watch.concat(paths)
|
93
|
+
@paths_to_watch.uniq!
|
94
|
+
@paths_to_watch.sort!
|
95
|
+
end
|
96
|
+
|
97
|
+
alias :watch :keep_a_watchful_eye_for
|
98
|
+
alias :add_mapping :prepare_spell_for
|
99
|
+
|
100
|
+
def shutdown
|
101
|
+
watcher.shutdown
|
39
102
|
exit
|
40
103
|
end
|
41
|
-
|
42
|
-
def
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
104
|
+
|
105
|
+
def on_change(paths)
|
106
|
+
say "#{paths} changed" unless paths.nil? || paths.empty?
|
107
|
+
|
108
|
+
paths.reject! { |path| ::Beholder.possible_treasure_map_locations.include?(path) }
|
109
|
+
runners_with_paths = {}
|
110
|
+
|
111
|
+
paths.each do |path|
|
112
|
+
runner, tests = *find_and_populate_matches(path)
|
113
|
+
next if tests.nil? || tests.empty?
|
114
|
+
|
115
|
+
tests.uniq!
|
116
|
+
tests.compact!
|
117
|
+
|
118
|
+
if tests.any?
|
119
|
+
runners_with_paths[runner] = tests
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
run_tests runners_with_paths
|
57
124
|
end
|
58
125
|
|
59
|
-
def
|
60
|
-
|
61
|
-
|
62
|
-
system "ruby #{coordinates.map { |f| Dir.glob(f) }.join(' ')}"
|
126
|
+
def tests_matching(name)
|
127
|
+
regex = %r%.*#{name}.*\.rb$%
|
128
|
+
::Beholder.all_tests.find_all { |ex| ex =~ regex }
|
63
129
|
end
|
64
130
|
|
65
|
-
def
|
66
|
-
|
67
|
-
|
68
|
-
|
131
|
+
def build_cmd(runner, paths)
|
132
|
+
puts "\nRunning #{paths.join(', ').inspect} with #{runner}"
|
133
|
+
cmd = "#{runner} #{paths.join(' ')}"
|
134
|
+
say cmd
|
135
|
+
cmd
|
69
136
|
end
|
70
|
-
|
71
|
-
def
|
137
|
+
|
138
|
+
def read_all_maps
|
139
|
+
read_default_map
|
140
|
+
::Beholder::possible_treasure_map_locations.each { |path| read_map_at(path) }
|
141
|
+
end
|
142
|
+
|
143
|
+
def read_map_at(path)
|
144
|
+
return unless File.exist?(path)
|
145
|
+
say "Found a map at #{path}"
|
146
|
+
begin
|
147
|
+
instance_eval(File.readlines(path).join("\n"))
|
148
|
+
rescue Object => e
|
149
|
+
puts "Exception caught trying to load map at #{path}"
|
150
|
+
puts e
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
protected
|
155
|
+
|
156
|
+
def prepare
|
72
157
|
trap 'INT' do
|
73
158
|
if @sent_an_int then
|
74
159
|
puts " A second INT? Ok, I get the message. Shutting down now."
|
75
|
-
|
160
|
+
shutdown
|
76
161
|
else
|
77
162
|
puts " Did you just send me an INT? Ugh. I'll quit for real if you do it again."
|
78
163
|
@sent_an_int = true
|
79
164
|
Kernel.sleep 1.5
|
165
|
+
run_tests nil => ::Beholder.all_tests
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def start
|
171
|
+
startup_msg
|
172
|
+
@watcher = FSEvents::Stream.watch(paths_to_watch) do |event|
|
173
|
+
on_change(event.modified_files)
|
174
|
+
puts "\n\nWaiting for changes since #{Time.now}"
|
175
|
+
end
|
176
|
+
@watcher.run
|
177
|
+
end
|
178
|
+
|
179
|
+
def startup_msg
|
180
|
+
puts %[Beholder has loaded - CTRL-C once to reset, twice to quit.]
|
181
|
+
puts %[Watching the following paths: #{paths_to_watch.join(", ")}]
|
182
|
+
end
|
183
|
+
|
184
|
+
def read_default_map
|
185
|
+
map_for(:and_lo_for_i_am_the_default_treasure_map) do |m|
|
186
|
+
|
187
|
+
m.watch 'lib', *::Beholder.test_directories
|
188
|
+
|
189
|
+
m.prepare_spell_for %r%lib/(.*)\.rb% do |match|
|
190
|
+
tests_matching match[1]
|
191
|
+
end
|
192
|
+
|
193
|
+
m.prepare_spell_for %r%.*#{::Beholder.test_extensions.join('|')}\.rb% do |match|
|
194
|
+
tests_matching match[1]
|
195
|
+
end
|
196
|
+
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def clear_maps
|
201
|
+
@treasure_maps = {}
|
202
|
+
end
|
203
|
+
|
204
|
+
def blink
|
205
|
+
@sent_an_int = false
|
206
|
+
end
|
207
|
+
|
208
|
+
def find_and_populate_matches(path)
|
209
|
+
treasure_maps.each do |name, map|
|
210
|
+
map.each do |pattern, options, blk|
|
211
|
+
if match = path.match(pattern)
|
212
|
+
say "Found the match for #{path} using the #{name} map "
|
213
|
+
return [options[:command], blk.call(match)]
|
214
|
+
end
|
80
215
|
end
|
81
216
|
end
|
217
|
+
|
218
|
+
puts "Unknown file: #{path}"
|
82
219
|
end
|
220
|
+
|
221
|
+
def run_tests(runners_with_paths)
|
222
|
+
remove_runners_with_no_valid_files_to_run(runners_with_paths)
|
223
|
+
|
224
|
+
return if runners_with_paths.empty?
|
225
|
+
|
226
|
+
runners_with_paths.each do |runner, paths|
|
227
|
+
runner ||= ::Beholder.runner
|
228
|
+
result = %x{#{build_cmd(runner, paths)}}
|
229
|
+
puts result
|
230
|
+
if $?.exitstatus.zero?
|
231
|
+
::Beholder.on_success && ::Beholder.on_success.call(result)
|
232
|
+
else
|
233
|
+
::Beholder.on_failure && ::Beholder.on_failure.call(result)
|
234
|
+
end
|
235
|
+
end
|
83
236
|
|
237
|
+
blink
|
238
|
+
end
|
239
|
+
|
84
240
|
private
|
241
|
+
|
242
|
+
def remove_runners_with_no_valid_files_to_run(runners_with_paths)
|
243
|
+
return [] if runners_with_paths.nil?
|
244
|
+
require 'pp'
|
245
|
+
pp runners_with_paths
|
246
|
+
runners_with_paths.each do |runner, paths|
|
247
|
+
paths.reject! do |path|
|
248
|
+
found_treasure = File.exist?(path)
|
249
|
+
say "#{path} does not exist." unless found_treasure
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
runners_with_paths.reject! { |runner, paths| paths.empty? }
|
254
|
+
end
|
255
|
+
|
85
256
|
def say(this_message_please)
|
86
257
|
puts this_message_please if be_verbose
|
87
258
|
end
|
88
|
-
|
89
|
-
end
|
259
|
+
|
260
|
+
end
|
@@ -0,0 +1,168 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/spec_helper")
|
2
|
+
|
3
|
+
describe Beholder do
|
4
|
+
|
5
|
+
describe "runner" do
|
6
|
+
it "should be 'ruby'" do
|
7
|
+
Beholder.runner.should == 'ruby'
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "test types" do
|
12
|
+
it "should include 'spec', 'examples', and 'test' by default" do
|
13
|
+
Beholder.test_types.should include('spec')
|
14
|
+
Beholder.test_types.should include('examples')
|
15
|
+
Beholder.test_types.should include('test')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "when run is called" do
|
20
|
+
it "should create a new beholder" do
|
21
|
+
beholder = stub(Beholder.new) { prepare; start }
|
22
|
+
mock(Beholder).new { beholder }
|
23
|
+
|
24
|
+
Beholder.run
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should prepare" do
|
28
|
+
beholder = Beholder.new
|
29
|
+
stub(beholder).start
|
30
|
+
mock(beholder).prepare
|
31
|
+
stub(Beholder).new { beholder }
|
32
|
+
|
33
|
+
Beholder.run
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should start" do
|
37
|
+
beholder = Beholder.new
|
38
|
+
mock(beholder).start
|
39
|
+
stub(beholder).prepare
|
40
|
+
stub(Beholder).new { beholder }
|
41
|
+
|
42
|
+
Beholder.run
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "when it notices file(s) changed" do
|
47
|
+
it "should identify what was changed" do
|
48
|
+
files = ['widgets']
|
49
|
+
beholder = Beholder.new
|
50
|
+
mock(beholder).find_and_populate_matches('widgets') { nil }
|
51
|
+
beholder.on_change files
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "build_cmd" do
|
56
|
+
it "contructs build cmd for a single file" do
|
57
|
+
beholder = Beholder.new
|
58
|
+
beholder.build_cmd("ruby", ["test/foo_test.rb"]).should == "ruby test/foo_test.rb"
|
59
|
+
end
|
60
|
+
|
61
|
+
it "contructs build cmd for a multiple files" do
|
62
|
+
beholder = Beholder.new
|
63
|
+
beholder.build_cmd("ruby", ["test/foo_test.rb", "test/functionals/foo_test.rb"]).should == %[ruby test/foo_test.rb test/functionals/foo_test.rb]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "blink" do
|
68
|
+
it "should forget about any interlopers" do
|
69
|
+
beholder = Beholder.new
|
70
|
+
beholder.instance_variable_set("@sent_an_int", true) # Not so hot, but I'm tired
|
71
|
+
|
72
|
+
beholder.sent_an_int.should be_true
|
73
|
+
beholder.__send__ :blink
|
74
|
+
beholder.sent_an_int.should be_false
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "when shutting down" do
|
79
|
+
it "should stop watching for changes" do
|
80
|
+
beholder = Beholder.new
|
81
|
+
stub(beholder).exit
|
82
|
+
stub(beholder).watcher { mock!.shutdown }
|
83
|
+
beholder.shutdown
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should exit" do
|
87
|
+
beholder = Beholder.new
|
88
|
+
stub(beholder).watcher { stub!.shutdown }
|
89
|
+
mock(beholder).exit
|
90
|
+
beholder.shutdown
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe "watch" do
|
95
|
+
it "adds paths to watch" do
|
96
|
+
beholder = Beholder.new
|
97
|
+
beholder.watch "bar", "foo"
|
98
|
+
beholder.paths_to_watch.should == ["bar", "foo"]
|
99
|
+
end
|
100
|
+
|
101
|
+
it "aliases keep_a_watchful_eye_for to watch" do
|
102
|
+
beholder = Beholder.new
|
103
|
+
beholder.keep_a_watchful_eye_for "bar", "foo"
|
104
|
+
beholder.paths_to_watch.should == ["bar", "foo"]
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should uniq and sort the paths" do
|
108
|
+
beholder = Beholder.new
|
109
|
+
beholder.watch "foo", "bar", "specs", "foo", "bar", "bar2"
|
110
|
+
beholder.paths_to_watch.should == ["bar", "bar2", "foo", "specs"]
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
describe "prepare spell for" do
|
115
|
+
def generate_map(beholder, blk)
|
116
|
+
beholder.map_for(:example) { |m| m.prepare_spell_for(%r%example_helper\.rb%, &blk) }
|
117
|
+
end
|
118
|
+
|
119
|
+
it "adds pattern and block to current_map" do
|
120
|
+
beholder = Beholder.new
|
121
|
+
blk = lambda { "something" }
|
122
|
+
generate_map(beholder, blk)
|
123
|
+
# This is not ideal
|
124
|
+
# currently returns array, array
|
125
|
+
beholder.treasure_maps[:example].first.first.should == %r%example_helper\.rb%
|
126
|
+
1.should == 3
|
127
|
+
end
|
128
|
+
|
129
|
+
# it "adds mapping using default command of ruby" do
|
130
|
+
# beholder = Beholder.new
|
131
|
+
# blk = lambda { "something" }
|
132
|
+
# generate_map(beholder, blk)
|
133
|
+
# beholder.treasure_maps[:example].should == [[ %r%example_helper\.rb%, {:command => "ruby"}, blk ]]
|
134
|
+
# end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe "tests_matching" do
|
138
|
+
it "finds a fuzzy match from all tests" do
|
139
|
+
beholder = Beholder.new
|
140
|
+
stub(Beholder).all_tests { ["spec/unit/bar_example.rb", "src/foo_system_example.rb", "spec/some/deeper/dir/foo_example.rb"] }
|
141
|
+
beholder.tests_matching("foo").should == ["src/foo_system_example.rb", "spec/some/deeper/dir/foo_example.rb"]
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
describe "read_map_at" do
|
146
|
+
it "rescues exceptions from instance_eval'ing the map, and carries on" do
|
147
|
+
beholder = Beholder.new
|
148
|
+
stub(File).exist? { true }
|
149
|
+
mock(File).readlines("my_map.rb") { ["!and this is invalid Ruby;end\nand more"] }
|
150
|
+
stub(beholder).puts
|
151
|
+
lambda { beholder.read_map_at("my_map.rb") }.should_not raise_error
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
describe "say" do
|
156
|
+
it "puts to stdout if verbose is true" do
|
157
|
+
begin
|
158
|
+
ARGV.push("-v")
|
159
|
+
beholder = Beholder.new
|
160
|
+
mock(beholder).puts("yo dawg")
|
161
|
+
beholder.__send__ :say, "yo dawg"
|
162
|
+
ensure
|
163
|
+
ARGV.pop
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
data/spec/setup.rb
ADDED
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
|
4
|
+
require 'beholder'
|
5
|
+
require 'spec'
|
6
|
+
require 'spec/autorun'
|
7
|
+
require 'rr'
|
8
|
+
|
9
|
+
Spec::Runner.configure do |config|
|
10
|
+
config.mock_with :rr
|
11
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: beholder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
- Chad Humphries
|
8
|
-
autorequire:
|
7
|
+
- Chad Humphries, Rob Sanheim
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-08-23 00:00:00 -04:00
|
13
13
|
default_executable: beholder
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -22,30 +22,59 @@ dependencies:
|
|
22
22
|
- !ruby/object:Gem::Version
|
23
23
|
version: "0"
|
24
24
|
version:
|
25
|
-
|
26
|
-
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rspec
|
27
|
+
type: :development
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0"
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: yard
|
37
|
+
type: :development
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: "0"
|
44
|
+
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: rr
|
47
|
+
type: :development
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 0.7.0
|
54
|
+
version:
|
55
|
+
description: beholder
|
56
|
+
email: chad@spicycode.com, rsanheim@gmail.com
|
27
57
|
executables:
|
28
58
|
- beholder
|
29
59
|
extensions: []
|
30
60
|
|
31
61
|
extra_rdoc_files:
|
32
|
-
- README.textile
|
33
62
|
- LICENSE
|
34
|
-
- TODO
|
35
63
|
files:
|
36
64
|
- LICENSE
|
37
|
-
- README.textile
|
38
65
|
- Rakefile
|
39
|
-
- TODO
|
40
66
|
- lib/beholder.rb
|
41
|
-
-
|
42
|
-
-
|
43
|
-
-
|
67
|
+
- spec/beholder_spec.rb
|
68
|
+
- spec/setup.rb
|
69
|
+
- spec/spec.opts
|
70
|
+
- spec/spec_helper.rb
|
44
71
|
has_rdoc: true
|
45
|
-
homepage: http://github.com/
|
46
|
-
|
47
|
-
rdoc_options: []
|
72
|
+
homepage: http://github.com/rsanheim/beholder
|
73
|
+
licenses: []
|
48
74
|
|
75
|
+
post_install_message:
|
76
|
+
rdoc_options:
|
77
|
+
- --charset=UTF-8
|
49
78
|
require_paths:
|
50
79
|
- lib
|
51
80
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -63,9 +92,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
63
92
|
requirements: []
|
64
93
|
|
65
94
|
rubyforge_project:
|
66
|
-
rubygems_version: 1.3.
|
95
|
+
rubygems_version: 1.3.5
|
67
96
|
signing_key:
|
68
|
-
specification_version:
|
97
|
+
specification_version: 3
|
69
98
|
summary: An ancient beholder that watches your treasure, and deals with thiefs
|
70
|
-
test_files:
|
71
|
-
|
99
|
+
test_files:
|
100
|
+
- spec/beholder_spec.rb
|
101
|
+
- spec/setup.rb
|
102
|
+
- spec/spec_helper.rb
|
data/README.textile
DELETED
data/examples/example_helper.rb
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
lib_path = File.expand_path(File.dirname(__FILE__) + "/../lib")
|
2
|
-
$LOAD_PATH.unshift lib_path unless $LOAD_PATH.include?(lib_path)
|
3
|
-
|
4
|
-
require 'beholder'
|
5
|
-
require 'rubygems'
|
6
|
-
require 'micronaut'
|
7
|
-
gem :rr, '=0.7.0'
|
8
|
-
|
9
|
-
|
10
|
-
def not_in_editor?
|
11
|
-
['TM_MODE', 'EMACS', 'VIM'].all? { |k| !ENV.has_key?(k) }
|
12
|
-
end
|
13
|
-
|
14
|
-
Micronaut.configure do |c|
|
15
|
-
c.formatter = :documentation
|
16
|
-
c.mock_with :rr
|
17
|
-
c.color_enabled = not_in_editor?
|
18
|
-
|
19
|
-
end
|
@@ -1,89 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + "/../example_helper")
|
2
|
-
|
3
|
-
describe Beholder do
|
4
|
-
|
5
|
-
describe "when casting it's gaze" do
|
6
|
-
|
7
|
-
it "should begat a new beholder" do
|
8
|
-
beholder = stub(Beholder.new) { prepare_for_interlopers; open_your_eye }
|
9
|
-
mock(Beholder).new { beholder }
|
10
|
-
Beholder.cast_thy_gaze
|
11
|
-
end
|
12
|
-
|
13
|
-
it "should prepare the child for interlopers" do
|
14
|
-
beholder = Beholder.new
|
15
|
-
stub(beholder).open_your_eye
|
16
|
-
mock(beholder).prepare_for_interlopers
|
17
|
-
stub(Beholder).new { beholder }
|
18
|
-
|
19
|
-
Beholder.cast_thy_gaze
|
20
|
-
end
|
21
|
-
|
22
|
-
it "should open the child's eyes" do
|
23
|
-
beholder = Beholder.new
|
24
|
-
mock(beholder).open_your_eye
|
25
|
-
stub(beholder).prepare_for_interlopers
|
26
|
-
stub(Beholder).new { beholder }
|
27
|
-
|
28
|
-
Beholder.cast_thy_gaze
|
29
|
-
end
|
30
|
-
|
31
|
-
end
|
32
|
-
|
33
|
-
describe "when it notices a thief taking treasure" do
|
34
|
-
|
35
|
-
it "should howl about the theft" do
|
36
|
-
beholder = Beholder.new
|
37
|
-
mock(beholder).say "#{[]} changed"
|
38
|
-
beholder.notice_thief_taking []
|
39
|
-
end
|
40
|
-
|
41
|
-
it "should identify what was stolen" do
|
42
|
-
treasures = ['pot_o_gold']
|
43
|
-
beholder = Beholder.new
|
44
|
-
mock(beholder).identify_stolen_treasure('pot_o_gold') { nil }
|
45
|
-
beholder.notice_thief_taking treasures
|
46
|
-
end
|
47
|
-
|
48
|
-
it "should reclaim the stolen treasures" do
|
49
|
-
treasures = ['pot_o_gold']
|
50
|
-
beholder = Beholder.new
|
51
|
-
stub(beholder).identify_stolen_treasure('pot_o_gold') { 'x marks the spot' }
|
52
|
-
mock(beholder).reclaim_stolen_treasure_at(['x marks the spot'])
|
53
|
-
beholder.notice_thief_taking treasures
|
54
|
-
end
|
55
|
-
|
56
|
-
end
|
57
|
-
|
58
|
-
describe "when blinking it's eye" do
|
59
|
-
|
60
|
-
it "should forget about any interlopers" do
|
61
|
-
beholder = Beholder.new
|
62
|
-
beholder.instance_variable_set("@sent_an_int", true) # Not so hot, but I'm tired
|
63
|
-
|
64
|
-
beholder.sent_an_int.should be_true
|
65
|
-
beholder.blink
|
66
|
-
beholder.sent_an_int.should be_false
|
67
|
-
end
|
68
|
-
|
69
|
-
end
|
70
|
-
|
71
|
-
describe "when closing it's eye" do
|
72
|
-
|
73
|
-
it "should stop watching for interlopers" do
|
74
|
-
beholder = Beholder.new
|
75
|
-
stub(beholder).exit
|
76
|
-
stub(beholder).the_eye { mock!.shutdown }
|
77
|
-
beholder.close_your_eye
|
78
|
-
end
|
79
|
-
|
80
|
-
it "should leave the dungeon" do
|
81
|
-
beholder = Beholder.new
|
82
|
-
stub(beholder).the_eye { stub!.shutdown }
|
83
|
-
mock(beholder).exit
|
84
|
-
beholder.close_your_eye
|
85
|
-
end
|
86
|
-
|
87
|
-
end
|
88
|
-
|
89
|
-
end
|