puppetlabs_spec_helper 4.0.1 → 5.0.1

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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +481 -116
  3. data/README.md +5 -19
  4. data/lib/puppetlabs_spec_helper/module_spec_helper.rb +8 -10
  5. data/lib/puppetlabs_spec_helper/puppet_spec_helper.rb +2 -86
  6. data/lib/puppetlabs_spec_helper/puppetlabs_spec/files.rb +3 -1
  7. data/lib/puppetlabs_spec_helper/puppetlabs_spec/fixtures.rb +3 -3
  8. data/lib/puppetlabs_spec_helper/puppetlabs_spec/matchers.rb +0 -17
  9. data/lib/puppetlabs_spec_helper/puppetlabs_spec/puppet_internals.rb +35 -68
  10. data/lib/puppetlabs_spec_helper/rake_tasks.rb +44 -63
  11. data/lib/puppetlabs_spec_helper/tasks/check_symlinks.rb +1 -3
  12. data/lib/puppetlabs_spec_helper/tasks/fixtures.rb +14 -12
  13. data/lib/puppetlabs_spec_helper/version.rb +1 -6
  14. data/spec/acceptance/fixtures/Rakefile +3 -0
  15. data/spec/acceptance/smoke_spec.rb +14 -0
  16. data/spec/spec_helper.rb +53 -0
  17. data/spec/unit/puppetlabs_spec_helper/puppetlabs_spec/puppet_internals_spec.rb +71 -0
  18. data/spec/unit/puppetlabs_spec_helper/tasks/check_symlinks_spec.rb +162 -0
  19. data/spec/unit/puppetlabs_spec_helper/tasks/check_test_file_spec.rb +45 -0
  20. data/spec/unit/puppetlabs_spec_helper/tasks/fixtures_spec.rb +262 -0
  21. data/spec/watchr.rb +81 -0
  22. metadata +32 -146
  23. data/.github/dependabot.yml +0 -15
  24. data/.gitignore +0 -9
  25. data/.noexec.yaml +0 -4
  26. data/.rspec +0 -2
  27. data/.rubocop_todo.yml +0 -119
  28. data/.travis.yml +0 -23
  29. data/CHANGELOG.md +0 -727
  30. data/CODEOWNERS +0 -2
  31. data/CONTRIBUTING.md +0 -14
  32. data/Gemfile +0 -42
  33. data/HISTORY.md +0 -498
  34. data/Rakefile +0 -45
  35. data/puppet_spec_helper.rb +0 -7
  36. data/puppetlabs_spec_helper.gemspec +0 -38
  37. data/puppetlabs_spec_helper.rb +0 -7
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'rspec-puppet'
5
+
6
+ describe PuppetlabsSpec::PuppetInternals do
7
+ before(:all) do # this is only needed once # rubocop:disable RSpec/BeforeAfterAll
8
+ Puppet.initialize_settings
9
+ end
10
+
11
+ describe '.resource' do
12
+ subject(:resource) { described_class.resource }
13
+
14
+ it 'can have a defined type' do
15
+ expect(described_class.resource(type: :node).type).to eq(:node)
16
+ end
17
+
18
+ it 'defaults to a type of hostclass' do
19
+ expect(resource.type).to eq(:hostclass)
20
+ end
21
+
22
+ it 'can have a defined name' do
23
+ expect(described_class.resource(name: 'testingrsrc').name).to eq('testingrsrc')
24
+ end
25
+
26
+ it 'defaults to a name of testing' do
27
+ expect(resource.name).to eq('testing')
28
+ end
29
+ end
30
+
31
+ describe '.compiler' do
32
+ let(:node) { described_class.node }
33
+
34
+ it 'can have a defined node' do
35
+ expect(described_class.compiler(node: node).node).to be node
36
+ end
37
+ end
38
+
39
+ describe '.node' do
40
+ it 'can have a defined name' do
41
+ expect(described_class.node(name: 'mine').name).to eq('mine')
42
+ end
43
+
44
+ it 'can have a defined environment' do
45
+ expect(described_class.node(environment: 'mine').environment.name).to eq(:mine)
46
+ end
47
+
48
+ it 'defaults to a name of testinghost' do
49
+ expect(described_class.node.name).to eq('testinghost')
50
+ end
51
+
52
+ it 'accepts facts via options for rspec-puppet' do
53
+ fact_values = { 'fqdn' => 'jeff.puppetlabs.com' }
54
+ node = described_class.node(options: { parameters: fact_values })
55
+ expect(node.parameters).to eq(fact_values)
56
+ end
57
+ end
58
+
59
+ describe '.function_method', type: :puppet_function do
60
+ it 'accepts an injected scope' do
61
+ expect(Puppet::Parser::Functions).to receive(:function).with('my_func').and_return(true)
62
+ expect(scope).to receive(:method).with(:function_my_func).and_return(:fake_method)
63
+ expect(described_class.function_method('my_func', scope: scope)).to eq(:fake_method)
64
+ end
65
+
66
+ it "returns nil if the function doesn't exist" do
67
+ expect(Puppet::Parser::Functions).to receive(:function).with('my_func').and_return(false)
68
+ expect(described_class.function_method('my_func', scope: scope)).to be_nil
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,162 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'rake check:symlinks', type: :task do
6
+ before(:each) do
7
+ test_files.each do |f|
8
+ FileUtils.mkdir_p(File.dirname(f))
9
+ FileUtils.touch(f)
10
+ end
11
+
12
+ symlinks.each do |link, target|
13
+ FileUtils.mkdir_p(File.dirname(link))
14
+ FileUtils.ln_s(target, link)
15
+ end
16
+ end
17
+
18
+ let(:test_files) { [] }
19
+ let(:symlinks) { {} }
20
+ let(:expected_output) do
21
+ symlinks.map { |link, target| "Symlink found: #{link} => #{target}" }.join("\n")
22
+ end
23
+
24
+ context 'when there are no files' do
25
+ it 'runs without raising an error' do
26
+ expect { task.execute }.not_to raise_error
27
+ end
28
+ end
29
+
30
+ context 'when there are regular files' do
31
+ let(:test_files) do
32
+ [
33
+ File.join(Dir.pwd, 'files', 'a_file.pp'),
34
+ File.join(Dir.pwd, 'files', 'another_file.pp'),
35
+ ]
36
+ end
37
+
38
+ it 'runs without raising an error' do
39
+ expect { task.execute }.not_to raise_error
40
+ end
41
+ end
42
+
43
+ context 'when there is a symlink present' do
44
+ let(:test_files) do
45
+ [
46
+ File.join(Dir.pwd, 'files', 'a_file.pp'),
47
+ ]
48
+ end
49
+
50
+ let(:symlinks) do
51
+ {
52
+ File.join(Dir.pwd, 'files', 'a_symlink.pp') => File.join(Dir.pwd, 'files', 'a_file.pp'),
53
+ }
54
+ end
55
+
56
+ it 'raises an error' do
57
+ expect { task.execute }
58
+ .to raise_error(%r{symlink\(s\) exist}i)
59
+ .and output(a_string_including(expected_output)).to_stdout
60
+ end
61
+ end
62
+
63
+ context 'when there are symlinks under .git/' do
64
+ let(:test_files) do
65
+ [
66
+ File.join(Dir.pwd, 'files', 'a_file.pp'),
67
+ ]
68
+ end
69
+
70
+ let(:symlinks) do
71
+ {
72
+ File.join(Dir.pwd, '.git', 'a_symlink.pp') => File.join(Dir.pwd, 'files', 'a_file.pp'),
73
+ }
74
+ end
75
+
76
+ it 'runs without raising an error' do
77
+ expect { task.execute }.not_to raise_error
78
+ end
79
+ end
80
+
81
+ context 'when there are symlinks under .bundle/' do
82
+ let(:test_files) do
83
+ [
84
+ File.join(Dir.pwd, 'files', 'a_file.pp'),
85
+ ]
86
+ end
87
+
88
+ let(:symlinks) do
89
+ {
90
+ File.join(Dir.pwd, '.bundle', 'a_symlink.pp') => File.join(Dir.pwd, 'files', 'a_file.pp'),
91
+ }
92
+ end
93
+
94
+ it 'runs without raising an error' do
95
+ expect { task.execute }.not_to raise_error
96
+ end
97
+ end
98
+
99
+ context 'when there are symlinks under vendor/' do
100
+ let(:test_files) do
101
+ [
102
+ File.join(Dir.pwd, 'files', 'a_file.pp'),
103
+ ]
104
+ end
105
+
106
+ let(:symlinks) do
107
+ {
108
+ File.join(Dir.pwd, 'vendor', 'a_symlink.pp') => File.join(Dir.pwd, 'files', 'a_file.pp'),
109
+ }
110
+ end
111
+
112
+ it 'runs without raising an error' do
113
+ expect { task.execute }.not_to raise_error
114
+ end
115
+ end
116
+
117
+ context 'when there are symlinks under a directory listed in .gitignore' do
118
+ before(:each) do
119
+ File.write(File.join(Dir.pwd, '.gitignore'), "a_directory/\n")
120
+ end
121
+
122
+ let(:test_files) do
123
+ [
124
+ File.join(Dir.pwd, 'files', 'a_file.pp'),
125
+ ]
126
+ end
127
+
128
+ let(:symlinks) do
129
+ {
130
+ File.join(Dir.pwd, 'a_directory', 'a_symlink.pp') => File.join(Dir.pwd, 'files', 'a_file.pp'),
131
+ }
132
+ end
133
+
134
+ it 'runs without raising an error' do
135
+ expect { task.execute }.not_to raise_error
136
+ end
137
+ end
138
+
139
+ context 'when there are symlinks under a directory listed in .pdkignore' do
140
+ before(:each) do
141
+ File.open(File.join(Dir.pwd, '.pdkignore'), 'w') do |f|
142
+ f.puts '/another_directory/'
143
+ end
144
+ end
145
+
146
+ let(:test_files) do
147
+ [
148
+ File.join(Dir.pwd, 'files', 'a_file.pp'),
149
+ ]
150
+ end
151
+
152
+ let(:symlinks) do
153
+ {
154
+ File.join(Dir.pwd, 'another_directory', 'a_symlink.pp') => File.join(Dir.pwd, 'files', 'a_file.pp'),
155
+ }
156
+ end
157
+
158
+ it 'runs without raising an error' do
159
+ expect { task.execute }.not_to raise_error
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'rake check:test_file', type: :task do
6
+ context 'when there are .pp files under tests/' do
7
+ before(:each) do
8
+ test_files.each do |f|
9
+ FileUtils.mkdir_p(File.dirname(f))
10
+ FileUtils.touch(f)
11
+ end
12
+ end
13
+
14
+ let(:test_files) do
15
+ [
16
+ File.join(Dir.pwd, 'tests', 'an_example.pp'),
17
+ File.join(Dir.pwd, 'tests', 'deep', 'directory', 'structure', 'another_example.pp'),
18
+ ]
19
+ end
20
+
21
+ it 'raises an error' do
22
+ expected_output = test_files.join("\n")
23
+
24
+ expect { task.execute }
25
+ .to raise_error(%r{pp files present in tests folder})
26
+ .and output(a_string_including(expected_output)).to_stdout
27
+ end
28
+ end
29
+
30
+ context 'when there are no .pp files under tests/' do
31
+ before(:each) do
32
+ FileUtils.mkdir('tests')
33
+ end
34
+
35
+ it 'runs without raising an error' do
36
+ expect { task.execute }.not_to raise_error
37
+ end
38
+ end
39
+
40
+ context 'when there is no tests/ directory' do
41
+ it 'runs without raising an error' do
42
+ expect { task.execute }.not_to raise_error
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,262 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'puppetlabs_spec_helper/tasks/fixtures'
5
+
6
+ describe PuppetlabsSpecHelper::Tasks::FixtureHelpers do
7
+ describe '.module_name' do
8
+ subject(:module_name) { described_class.module_name }
9
+
10
+ before(:each) do
11
+ allow(Dir).to receive(:pwd).and_return(File.join('path', 'to', 'my-awsome-module_from_pwd'))
12
+ end
13
+
14
+ shared_examples 'module name from working directory' do
15
+ it 'determines the module name from the working directory name' do
16
+ expect(module_name).to eq('module_from_pwd')
17
+ end
18
+ end
19
+
20
+ shared_examples 'module name from metadata' do
21
+ it 'determines the module name from the module metadata' do
22
+ expect(module_name).to eq('module_from_metadata')
23
+ end
24
+ end
25
+
26
+ context 'when metadata.json does not exist' do
27
+ before(:each) do
28
+ allow(File).to receive(:file?).with('metadata.json').and_return(false)
29
+ end
30
+
31
+ it_behaves_like 'module name from working directory'
32
+ end
33
+
34
+ context 'when metadata.json does exist' do
35
+ before(:each) do
36
+ allow(File).to receive(:file?).with('metadata.json').and_return(true)
37
+ end
38
+
39
+ context 'but it is not readable' do
40
+ before(:each) do
41
+ allow(File).to receive(:readable?).with('metadata.json').and_return(false)
42
+ end
43
+
44
+ it_behaves_like 'module name from working directory'
45
+ end
46
+
47
+ context 'and it is readable' do
48
+ before(:each) do
49
+ allow(File).to receive(:readable?).with('metadata.json').and_return(true)
50
+ allow(File).to receive(:read).with('metadata.json').and_return(metadata_content)
51
+ end
52
+
53
+ context 'but it contains invalid JSON' do
54
+ let(:metadata_content) { '{ "name": "my-awesome-module_from_metadata", }' }
55
+
56
+ it_behaves_like 'module name from working directory'
57
+ end
58
+
59
+ context 'and it contains a name value' do
60
+ let(:metadata_content) { '{ "name": "my-awesome-module_from_metadata" }' }
61
+
62
+ it_behaves_like 'module name from metadata'
63
+ end
64
+
65
+ context 'but it does not contain a name value' do
66
+ let(:metadata_content) { '{}' }
67
+
68
+ it_behaves_like 'module name from working directory'
69
+ end
70
+
71
+ context 'but the name has a null value' do
72
+ let(:metadata_content) { '{ "name": null }' }
73
+
74
+ it_behaves_like 'module name from working directory'
75
+ end
76
+
77
+ context 'but the name is blank' do
78
+ let(:metadata_content) { '{ "name": "" }' }
79
+
80
+ it_behaves_like 'module name from working directory'
81
+ end
82
+ end
83
+ end
84
+ end
85
+
86
+ describe '.fixtures' do
87
+ subject(:helper) { described_class }
88
+
89
+ before :each do
90
+ # Unstub the fixtures "helpers"
91
+ PuppetlabsSpec::Fixtures.instance_methods.each do |m|
92
+ PuppetlabsSpec::Fixtures.send(:undef_method, m)
93
+ end
94
+ allow(File).to receive(:exist?).with('.fixtures.yml').and_return false
95
+ allow(File).to receive(:exist?).with('.fixtures.yaml').and_return false
96
+ allow(ENV).to receive(:[]).and_call_original
97
+ allow(ENV).to receive(:[]).with('FIXTURES_YML').and_return(nil)
98
+ allow(described_class).to receive(:auto_symlink).and_return('project' => source_dir.to_s)
99
+ end
100
+
101
+ context 'when file is missing' do
102
+ it 'returns basic directories per category' do
103
+ expect(helper.fixtures('forge_modules')).to eq({})
104
+ expect(helper.fixtures('repositories')).to eq({})
105
+ end
106
+ end
107
+
108
+ context 'when file is empty' do
109
+ it 'returns basic directories per category' do
110
+ allow(File).to receive(:exist?).with('.fixtures.yml').and_return true
111
+ allow(YAML).to receive(:load_file).with('.fixtures.yml').and_return false
112
+ expect(helper.fixtures('forge_modules')).to eq({})
113
+ expect(helper.fixtures('repositories')).to eq({})
114
+ end
115
+ end
116
+
117
+ context 'when file is malformed' do
118
+ it 'raises an error' do
119
+ expect(File).to receive(:exist?).with('.fixtures.yml').and_return true
120
+ expect(YAML).to receive(:load_file).with('.fixtures.yml').and_raise(Psych::SyntaxError.new('/file', '123', '0', '0', 'spec message', 'spec context'))
121
+ expect { helper.fixtures('forge_modules') }.to raise_error(RuntimeError, %r{malformed YAML})
122
+ end
123
+ end
124
+
125
+ context 'when file contains no fixtures' do
126
+ it 'raises an error' do
127
+ allow(File).to receive(:exist?).with('.fixtures.yml').and_return true
128
+ allow(YAML).to receive(:load_file).with('.fixtures.yml').and_return('some' => 'key')
129
+ expect { helper.fixtures('forge_modules') }.to raise_error(RuntimeError, %r{No 'fixtures'})
130
+ end
131
+ end
132
+
133
+ context 'when file specifies fixtures' do
134
+ it 'returns the hash' do
135
+ allow(File).to receive(:exist?).with('.fixtures.yml').and_return true
136
+ allow(YAML).to receive(:load_file).with('.fixtures.yml').and_return('fixtures' => { 'forge_modules' => { 'stdlib' => 'puppetlabs-stdlib' } })
137
+ expect(helper.fixtures('forge_modules')).to eq(
138
+ 'puppetlabs-stdlib' => {
139
+ 'target' => 'spec/fixtures/modules/stdlib',
140
+ 'ref' => nil,
141
+ 'branch' => nil,
142
+ 'scm' => nil,
143
+ 'flags' => nil,
144
+ 'subdir' => nil,
145
+ },
146
+ )
147
+ end
148
+ end
149
+
150
+ context 'when file specifies defaults' do
151
+ it 'returns the hash' do
152
+ allow(File).to receive(:exist?).with('.fixtures.yml').and_return true
153
+ allow(YAML).to receive(:load_file).with('.fixtures.yml').and_return('defaults' => { 'forge_modules' => { 'flags' => '--module_repository=https://myforge.example.com/' } },
154
+ 'fixtures' => { 'forge_modules' => { 'stdlib' => 'puppetlabs-stdlib' } })
155
+ expect(helper.fixtures('forge_modules')).to eq(
156
+ 'puppetlabs-stdlib' => {
157
+ 'target' => 'spec/fixtures/modules/stdlib',
158
+ 'ref' => nil,
159
+ 'branch' => nil,
160
+ 'scm' => nil,
161
+ 'flags' => '--module_repository=https://myforge.example.com/',
162
+ 'subdir' => nil,
163
+ },
164
+ )
165
+ end
166
+ end
167
+
168
+ context 'when file specifies repository fixtures' do
169
+ before(:each) do
170
+ allow(File).to receive(:exist?).with('.fixtures.yml').and_return true
171
+ allow(YAML).to receive(:load_file).with('.fixtures.yml').and_return(
172
+ 'fixtures' => {
173
+ 'repositories' => { 'stdlib' => 'https://github.com/puppetlabs/puppetlabs-stdlib.git' },
174
+ },
175
+ )
176
+ end
177
+
178
+ it 'returns the hash' do
179
+ expect(helper.repositories).to eq(
180
+ 'https://github.com/puppetlabs/puppetlabs-stdlib.git' => {
181
+ 'target' => 'spec/fixtures/modules/stdlib',
182
+ 'ref' => nil,
183
+ 'branch' => nil,
184
+ 'scm' => nil,
185
+ 'flags' => nil,
186
+ 'subdir' => nil,
187
+ },
188
+ )
189
+ end
190
+ end
191
+
192
+ context 'when file specifies repository fixtures with an invalid git ref' do
193
+ before(:each) do
194
+ allow(File).to receive(:exist?).with('.fixtures.yml').and_return true
195
+ allow(YAML).to receive(:load_file).with('.fixtures.yml').and_return(
196
+ 'fixtures' => {
197
+ 'repositories' => {
198
+ 'stdlib' => {
199
+ 'scm' => 'git',
200
+ 'repo' => 'https://github.com/puppetlabs/puppetlabs-stdlib.git',
201
+ 'ref' => 'this/is/a/branch',
202
+ },
203
+ },
204
+ },
205
+ )
206
+ end
207
+
208
+ it 'raises an ArgumentError' do
209
+ expect { helper.fixtures('repositories') }.to raise_error(ArgumentError)
210
+ end
211
+ end
212
+
213
+ context 'when file specifies puppet version' do
214
+ def stub_fixtures(data)
215
+ allow(File).to receive(:exist?).with('.fixtures.yml').and_return true
216
+ allow(YAML).to receive(:load_file).with('.fixtures.yml').and_return(data)
217
+ end
218
+
219
+ it 'includes the fixture if the puppet version matches', if: Gem::Version.new(Puppet::PUPPETVERSION) > Gem::Version.new('4') do
220
+ stub_fixtures(
221
+ 'fixtures' => {
222
+ 'forge_modules' => {
223
+ 'stdlib' => {
224
+ 'repo' => 'puppetlabs-stdlib',
225
+ 'puppet_version' => Puppet::PUPPETVERSION,
226
+ },
227
+ },
228
+ },
229
+ )
230
+ expect(helper.fixtures('forge_modules')).to include('puppetlabs-stdlib')
231
+ end
232
+
233
+ it 'excludes the fixture if the puppet version does not match', if: Gem::Version.new(Puppet::PUPPETVERSION) > Gem::Version.new('4') do
234
+ stub_fixtures(
235
+ 'fixtures' => {
236
+ 'forge_modules' => {
237
+ 'stdlib' => {
238
+ 'repo' => 'puppetlabs-stdlib',
239
+ 'puppet_version' => '>= 999.9.9',
240
+ },
241
+ },
242
+ },
243
+ )
244
+ expect(helper.fixtures('forge_modules')).to eq({})
245
+ end
246
+
247
+ it 'includes the fixture on obsolete puppet versions', if: Gem::Version.new(Puppet::PUPPETVERSION) <= Gem::Version.new('4') do
248
+ stub_fixtures(
249
+ 'fixtures' => {
250
+ 'forge_modules' => {
251
+ 'stdlib' => {
252
+ 'repo' => 'puppetlabs-stdlib',
253
+ 'puppet_version' => Puppet::PUPPETVERSION,
254
+ },
255
+ },
256
+ },
257
+ )
258
+ expect(helper.fixtures('forge_modules')).to include('puppetlabs-stdlib')
259
+ end
260
+ end
261
+ end
262
+ end
data/spec/watchr.rb ADDED
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ ENV['FOG_MOCK'] ||= 'true'
4
+ ENV['AUTOTEST'] = 'true'
5
+ ENV['WATCHR'] = '1'
6
+
7
+ system 'clear'
8
+
9
+ def growl(message)
10
+ growlnotify = `which growlnotify`.chomp
11
+ title = 'Watchr Test Results'
12
+ image = case message
13
+ when %r{(\d+)\s+?(failure|error)}i
14
+ (Regexp.last_match(1).to_i == 0) ? '~/.watchr_images/passed.png' : '~/.watchr_images/failed.png'
15
+ else
16
+ '~/.watchr_images/unknown.png'
17
+ end
18
+ options = "-w -n Watchr --image '#{File.expand_path(image)}' -m '#{message}' '#{title}'"
19
+ system %(#{growlnotify} #{options} &)
20
+ end
21
+
22
+ def run(cmd)
23
+ puts(cmd)
24
+ `#{cmd}`
25
+ end
26
+
27
+ def run_spec_test(file)
28
+ if File.exist? file
29
+ result = run "rspec --format p #{file}"
30
+ growl result.split("\n").last
31
+ puts result
32
+ else
33
+ puts "FIXME: No test #{file} [#{Time.now}]"
34
+ end
35
+ end
36
+
37
+ def filter_rspec(data)
38
+ data.split("\n").select { |l|
39
+ l =~ %r{^(\d+)\s+exampl\w+.*?(\d+).*?failur\w+.*?(\d+).*?pending}
40
+ }.join("\n")
41
+ end
42
+
43
+ def run_all_tests
44
+ system('clear')
45
+ files = Dir.glob('spec/**/*_spec.rb').join(' ')
46
+ result = run "rspec #{files}"
47
+ growl_results = filter_rspec result
48
+ growl growl_results
49
+ puts result
50
+ puts "GROWL: #{growl_results}"
51
+ end
52
+
53
+ # Ctrl-\
54
+ Signal.trap 'QUIT' do
55
+ puts " --- Running all tests ---\n\n"
56
+ run_all_tests
57
+ end
58
+
59
+ @interrupted = false
60
+
61
+ # Ctrl-C
62
+ Signal.trap 'INT' do
63
+ if @interrupted
64
+ @wants_to_quit = true
65
+ abort("\n")
66
+ else
67
+ puts 'Interrupt a second time to quit'
68
+ @interrupted = true
69
+ Kernel.sleep 1.5
70
+ # raise Interrupt, nil # let the run loop catch it
71
+ run_suite
72
+ end
73
+ end
74
+
75
+ watch('spec/.*_spec\.rb') do |_md|
76
+ run_all_tests
77
+ end
78
+
79
+ watch('lib/.*\.rb') do |_md|
80
+ run_all_tests
81
+ end