beholder 0.0.1 → 3.0.0
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/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
|