stairs 0.9.0 → 0.10.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -36
- data/.travis.yml +6 -2
- data/Guardfile +2 -2
- data/Rakefile +4 -4
- data/bin/stairs +10 -10
- data/lib/stairs.rb +13 -13
- data/lib/stairs/env_adapters.rb +6 -6
- data/lib/stairs/env_adapters/dotenv.rb +3 -3
- data/lib/stairs/env_adapters/rbenv.rb +3 -3
- data/lib/stairs/env_adapters/rvm.rb +3 -3
- data/lib/stairs/interactive_configuration.rb +11 -11
- data/lib/stairs/railtie.rb +1 -1
- data/lib/stairs/runner.rb +2 -2
- data/lib/stairs/step.rb +20 -17
- data/lib/stairs/steps.rb +3 -3
- data/lib/stairs/steps/facebook.rb +6 -6
- data/lib/stairs/steps/postgresql.rb +11 -11
- data/lib/stairs/steps/secret_key_base.rb +4 -4
- data/lib/stairs/tasks.rb +2 -2
- data/lib/stairs/util.rb +2 -2
- data/lib/stairs/util/cli.rb +3 -4
- data/lib/stairs/util/file_mutation.rb +10 -10
- data/lib/stairs/version.rb +1 -1
- data/spec/lib/configuration_spec.rb +8 -8
- data/spec/lib/stairs/env_adapters/dotenv_spec.rb +20 -20
- data/spec/lib/stairs/env_adapters/rbenv_spec.rb +22 -22
- data/spec/lib/stairs/env_adapters/rvm_spec.rb +22 -22
- data/spec/lib/stairs/env_adapters_spec.rb +12 -14
- data/spec/lib/stairs/interactive_configuration_spec.rb +27 -20
- data/spec/lib/stairs/runner_spec.rb +18 -14
- data/spec/lib/stairs/script_spec.rb +13 -14
- data/spec/lib/stairs/step_spec.rb +225 -189
- data/spec/lib/stairs/steps/secret_key_base_spec.rb +7 -5
- data/spec/lib/stairs/util/cli_spec.rb +29 -29
- data/spec/lib/stairs/util/file_mutation_spec.rb +46 -46
- data/spec/spec_helper.rb +6 -8
- data/stairs.gemspec +28 -23
- metadata +22 -23
- data/spec/support/configuration_helper.rb +0 -5
@@ -1,51 +1,58 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Stairs::InteractiveConfiguration do
|
4
4
|
subject { described_class.new }
|
5
5
|
|
6
|
-
describe
|
7
|
-
it
|
6
|
+
describe 'metadata' do
|
7
|
+
it 'has a title' do
|
8
8
|
expect(described_class.step_title).not_to be_nil
|
9
9
|
end
|
10
10
|
|
11
|
-
it
|
11
|
+
it 'has a description' do
|
12
12
|
expect(described_class.step_description).not_to be_nil
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
describe
|
16
|
+
describe '#run!' do
|
17
17
|
before do
|
18
|
-
Stairs::EnvAdapters
|
18
|
+
allow(Stairs::EnvAdapters)
|
19
|
+
.to receive(:recommended_adapter).and_return(Stairs::EnvAdapters::Rbenv)
|
19
20
|
end
|
20
21
|
|
21
|
-
it
|
22
|
-
output = follow_prompts(
|
22
|
+
it 'recommends an adapter' do
|
23
|
+
output = follow_prompts('Y') { subject.run! }
|
23
24
|
expect(output).to include "you're using rbenv"
|
24
25
|
end
|
25
26
|
|
26
|
-
it
|
27
|
-
follow_prompts(
|
28
|
-
expect(Stairs.configuration.env_adapter)
|
27
|
+
it 'sets the adapter' do
|
28
|
+
follow_prompts('Y') { subject.run! }
|
29
|
+
expect(Stairs.configuration.env_adapter)
|
30
|
+
.to be_a Stairs::EnvAdapters::Rbenv
|
29
31
|
end
|
30
32
|
|
31
|
-
it
|
32
|
-
follow_prompts(
|
33
|
-
expect(Stairs.configuration.env_adapter)
|
33
|
+
it 'allows for specifying your desired adapter' do
|
34
|
+
follow_prompts('N', 'dotenv') { subject.run! }
|
35
|
+
expect(Stairs.configuration.env_adapter)
|
36
|
+
.to be_a Stairs::EnvAdapters::Dotenv
|
34
37
|
end
|
35
38
|
|
36
|
-
context
|
39
|
+
context 'when Stairs is configured to use defaults' do
|
37
40
|
before { Stairs.configuration.use_defaults = true }
|
38
41
|
|
39
|
-
it
|
42
|
+
it 'uses the default adapter without asking' do
|
40
43
|
subject.run!
|
41
|
-
expect(Stairs.configuration.env_adapter)
|
44
|
+
expect(Stairs.configuration.env_adapter)
|
45
|
+
.to be_a Stairs::EnvAdapters::Rbenv
|
42
46
|
end
|
43
47
|
end
|
44
48
|
|
45
|
-
context
|
46
|
-
before
|
49
|
+
context 'when no adapter can be found to recommend' do
|
50
|
+
before do
|
51
|
+
allow(Stairs::EnvAdapters)
|
52
|
+
.to receive(:recommended_adapter).and_return(nil)
|
53
|
+
end
|
47
54
|
|
48
|
-
it
|
55
|
+
it 'aborts' do
|
49
56
|
expect { subject.run! }.to raise_error SystemExit
|
50
57
|
end
|
51
58
|
end
|
@@ -1,36 +1,40 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Stairs::Runner do
|
4
4
|
let(:groups) { nil }
|
5
5
|
let(:subject) { described_class.new(groups) }
|
6
6
|
|
7
|
-
describe
|
8
|
-
let(:script_double) { double(
|
7
|
+
describe '#run!' do
|
8
|
+
let(:script_double) { double('script', run!: true) }
|
9
9
|
|
10
10
|
before do
|
11
11
|
# Stub things as to not block IO
|
12
|
-
Stairs::InteractiveConfiguration.
|
13
|
-
Stairs::Script.
|
14
|
-
Stairs::Script.
|
12
|
+
allow_any_instance_of(Stairs::InteractiveConfiguration).to receive(:run!)
|
13
|
+
allow_any_instance_of(Stairs::Script).to receive(:run!)
|
14
|
+
allow(Stairs::Script).to receive(:new).and_return(script_double)
|
15
15
|
end
|
16
16
|
|
17
|
-
it
|
18
|
-
Stairs::InteractiveConfiguration
|
17
|
+
it 'runs the interactive configuration' do
|
18
|
+
expect_any_instance_of(Stairs::InteractiveConfiguration)
|
19
|
+
.to receive(:run!)
|
20
|
+
|
19
21
|
subject.run!
|
20
22
|
end
|
21
23
|
|
22
|
-
it
|
23
|
-
Stairs::Script
|
24
|
-
|
24
|
+
it 'runs all groups in the setup.rb script' do
|
25
|
+
expect(Stairs::Script)
|
26
|
+
.to receive(:new).with('setup.rb', groups).and_return(script_double)
|
27
|
+
|
28
|
+
expect(script_double).to receive(:run!)
|
25
29
|
|
26
30
|
subject.run!
|
27
31
|
end
|
28
32
|
|
29
|
-
context
|
33
|
+
context 'with groups provided' do
|
30
34
|
let(:groups) { [:reset] }
|
31
35
|
|
32
|
-
it
|
33
|
-
Stairs::Script.
|
36
|
+
it 'passes the specified groups to the script' do
|
37
|
+
expect(Stairs::Script).to receive(:new).with('setup.rb', groups)
|
34
38
|
subject.run!
|
35
39
|
end
|
36
40
|
end
|
@@ -1,38 +1,37 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Stairs::Script do
|
4
|
-
let(:filename) {
|
4
|
+
let(:filename) { 'setup.rb' }
|
5
5
|
let(:groups) { [:reset] }
|
6
6
|
subject { described_class.new(filename, groups) }
|
7
7
|
|
8
|
-
|
9
|
-
context "with a script present" do
|
8
|
+
context 'with a script present' do
|
10
9
|
before do
|
11
|
-
File.open(filename,
|
12
|
-
file.write(
|
10
|
+
File.open(filename, 'w') do |file|
|
11
|
+
file.write('self.class')
|
13
12
|
end
|
14
13
|
end
|
15
14
|
|
16
15
|
after { File.delete(filename) }
|
17
16
|
|
18
|
-
describe
|
19
|
-
it
|
17
|
+
describe 'initialize' do
|
18
|
+
it 'receives groups' do
|
20
19
|
expect { described_class.new(filename, groups) }.not_to raise_error
|
21
20
|
end
|
22
21
|
end
|
23
22
|
|
24
|
-
describe
|
25
|
-
it
|
23
|
+
describe '#run!' do
|
24
|
+
it 'outputs running message' do
|
26
25
|
output = capture_stdout { subject.run! }
|
27
|
-
expect(output).to include
|
26
|
+
expect(output).to include '= Running script setup.rb'
|
28
27
|
end
|
29
28
|
|
30
|
-
it
|
31
|
-
Stairs::Step.
|
29
|
+
it 'passes groups to the new instance of Step' do
|
30
|
+
expect(Stairs::Step).to receive(:new).with(groups)
|
32
31
|
subject.run!
|
33
32
|
end
|
34
33
|
|
35
|
-
it
|
34
|
+
it 'evaluates the script in the context of an instance of Step' do
|
36
35
|
# because our test setup.rb only contains `self.class` we can check
|
37
36
|
# this way:
|
38
37
|
expect(subject.run!).to eq Stairs::Step
|
@@ -1,349 +1,378 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Stairs::Step do
|
4
4
|
let(:anon_step) { Class.new(described_class) }
|
5
5
|
let(:groups) { nil }
|
6
6
|
subject { anon_step.new(groups) }
|
7
7
|
|
8
|
-
describe
|
9
|
-
describe
|
10
|
-
it
|
11
|
-
anon_step.title
|
12
|
-
expect(subject.step_title).to eq
|
8
|
+
describe 'metadata' do
|
9
|
+
describe 'step_title' do
|
10
|
+
it 'can be set on the class using title class DSL' do
|
11
|
+
anon_step.title 'Class Step Name'
|
12
|
+
expect(subject.step_title).to eq 'Class Step Name'
|
13
13
|
end
|
14
14
|
|
15
|
-
it
|
16
|
-
subject.step_title =
|
17
|
-
expect(subject.step_title).to eq
|
15
|
+
it 'can be set on the instance' do
|
16
|
+
subject.step_title = 'Instance Step Name'
|
17
|
+
expect(subject.step_title).to eq 'Instance Step Name'
|
18
18
|
end
|
19
19
|
|
20
|
-
it
|
21
|
-
anon_step.title
|
22
|
-
subject.step_title =
|
23
|
-
expect(subject.step_title).to eq
|
20
|
+
it 'prefers the value set on instance' do
|
21
|
+
anon_step.title 'Class Step Name'
|
22
|
+
subject.step_title = 'Instance Step Name'
|
23
|
+
expect(subject.step_title).to eq 'Instance Step Name'
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
describe
|
28
|
-
it
|
29
|
-
anon_step.description
|
30
|
-
expect(subject.step_description).to eq
|
27
|
+
describe 'step_description' do
|
28
|
+
it 'can be set on the class using description class DSL' do
|
29
|
+
anon_step.description 'Class Step Description'
|
30
|
+
expect(subject.step_description).to eq 'Class Step Description'
|
31
31
|
end
|
32
32
|
|
33
|
-
it
|
34
|
-
subject.step_description =
|
35
|
-
expect(subject.step_description).to eq
|
33
|
+
it 'can be set on the instance' do
|
34
|
+
subject.step_description = 'Instance Step Description'
|
35
|
+
expect(subject.step_description).to eq 'Instance Step Description'
|
36
36
|
end
|
37
37
|
|
38
|
-
it
|
39
|
-
anon_step.title
|
40
|
-
subject.step_description =
|
41
|
-
expect(subject.step_description).to eq
|
38
|
+
it 'prefers the value set on instance' do
|
39
|
+
anon_step.title 'Class Step Description'
|
40
|
+
subject.step_description = 'Instance Step Description'
|
41
|
+
expect(subject.step_description).to eq 'Instance Step Description'
|
42
42
|
end
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
-
describe
|
47
|
-
describe
|
48
|
-
describe
|
49
|
-
it
|
50
|
-
expect(subject.options[:required]).to
|
46
|
+
describe '#initialize' do
|
47
|
+
describe 'options' do
|
48
|
+
describe 'default options' do
|
49
|
+
it 'is required' do
|
50
|
+
expect(subject.options[:required]).to eq true
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
|
-
context
|
55
|
-
let(:options) { { something:
|
54
|
+
context 'with options' do
|
55
|
+
let(:options) { { something: 'cool' } }
|
56
56
|
subject { anon_step.new(options) }
|
57
57
|
|
58
|
-
it
|
59
|
-
expect(subject.options[:something]).to eq
|
58
|
+
it 'exposes options on the instance' do
|
59
|
+
expect(subject.options[:something]).to eq 'cool'
|
60
60
|
end
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
|
-
it
|
64
|
+
it 'exposes supplied groups on the instance' do
|
65
65
|
expect(subject.groups).to eq groups
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
69
|
-
describe
|
70
|
-
before { subject.
|
71
|
-
before { anon_step.title
|
69
|
+
describe '#run!' do
|
70
|
+
before { allow(subject).to receive(:run).and_return(true) }
|
71
|
+
before { anon_step.title 'Step Name' }
|
72
72
|
|
73
|
-
it
|
73
|
+
it 'outputs lead-in message' do
|
74
74
|
output = capture_stdout { subject.run! }
|
75
|
-
expect(output).to include
|
75
|
+
expect(output).to include '== Running Step Name'
|
76
76
|
end
|
77
77
|
|
78
|
-
it
|
79
|
-
subject.
|
78
|
+
it 'calls #run where the implementation lives' do
|
79
|
+
expect(subject).to receive(:run)
|
80
80
|
subject.run!
|
81
81
|
end
|
82
82
|
|
83
|
-
it
|
83
|
+
it 'outputs completed message' do
|
84
84
|
output = capture_stdout { subject.run! }
|
85
|
-
expect(output).to include
|
85
|
+
expect(output).to include '== Completed Step Name'
|
86
86
|
end
|
87
87
|
|
88
|
-
context
|
88
|
+
context 'when the step is not required' do
|
89
89
|
subject { anon_step.new required: false }
|
90
|
-
before { subject.
|
90
|
+
before { allow(subject).to receive(:run).and_return(true) }
|
91
91
|
|
92
|
-
it
|
93
|
-
output = follow_prompts(
|
94
|
-
expect(output).to include
|
92
|
+
it 'prompts the user to decide if we should run the step' do
|
93
|
+
output = follow_prompts('Y') { subject.run! }
|
94
|
+
expect(output).to include 'This step is optional, would you like to ' \
|
95
|
+
'perform it? (Y/N): '
|
95
96
|
end
|
96
97
|
|
97
|
-
context
|
98
|
-
it
|
99
|
-
subject.
|
100
|
-
follow_prompts(
|
98
|
+
context 'user says yes' do
|
99
|
+
it 'runs the step' do
|
100
|
+
expect(subject).to receive(:run)
|
101
|
+
follow_prompts('Y') { subject.run! }
|
101
102
|
end
|
102
103
|
end
|
103
104
|
|
104
|
-
context
|
105
|
+
context 'user says no' do
|
105
106
|
it "doesn't run the step" do
|
106
|
-
subject.
|
107
|
-
follow_prompts(
|
107
|
+
expect(subject).not_to receive(:run)
|
108
|
+
follow_prompts('N') { subject.run! }
|
108
109
|
end
|
109
110
|
end
|
110
111
|
end
|
111
112
|
end
|
112
113
|
|
113
|
-
describe
|
114
|
-
it
|
115
|
-
output = follow_prompts(
|
116
|
-
expect(output).to include
|
114
|
+
describe '#provide' do
|
115
|
+
it 'prompts the user to provide input' do
|
116
|
+
output = follow_prompts('here') { subject.provide 'Gimme' }
|
117
|
+
expect(output).to include 'Gimme: '
|
117
118
|
end
|
118
119
|
|
119
|
-
it
|
120
|
-
follow_prompts(
|
121
|
-
expect(subject.provide(
|
120
|
+
it 'returns the input' do
|
121
|
+
follow_prompts('here') do
|
122
|
+
expect(subject.provide('Gimme')).to eq 'here'
|
122
123
|
end
|
123
124
|
end
|
124
125
|
|
125
|
-
it
|
126
|
-
follow_prompts
|
127
|
-
expect(subject.provide(
|
126
|
+
it 'requires user input' do
|
127
|
+
follow_prompts '', '', '', 'finally' do
|
128
|
+
expect(subject.provide('Gimme')).to eq 'finally'
|
128
129
|
end
|
129
130
|
end
|
130
131
|
|
131
|
-
context
|
132
|
+
context 'Stairs is configured to use defaults automatically' do
|
132
133
|
before { Stairs.configuration.use_defaults = true }
|
133
134
|
|
134
|
-
context
|
135
|
-
it
|
136
|
-
follow_prompts
|
137
|
-
expect(subject.provide(
|
135
|
+
context 'but no default is provided' do
|
136
|
+
it 'prompts for input as usual' do
|
137
|
+
follow_prompts 'here ya go' do
|
138
|
+
expect(subject.provide('Gimme')).to eq 'here ya go'
|
138
139
|
end
|
139
140
|
end
|
140
141
|
end
|
141
142
|
|
142
|
-
context
|
143
|
-
it
|
144
|
-
expect(subject.provide(
|
143
|
+
context 'and a default is provided' do
|
144
|
+
it 'returns the default without prompting' do
|
145
|
+
expect(subject.provide('Gimme', default: 'adefault')).to eq 'adefault'
|
145
146
|
end
|
146
147
|
end
|
147
148
|
end
|
148
149
|
|
149
|
-
context
|
150
|
+
context 'with a default' do
|
150
151
|
def call_method
|
151
|
-
subject.provide
|
152
|
+
subject.provide 'Gimme', default: 'adefault'
|
152
153
|
end
|
153
154
|
|
154
|
-
it
|
155
|
-
|
155
|
+
it 'does not require input (this test would hang if it did)' do
|
156
|
+
follow_prompts('here') { call_method }
|
156
157
|
end
|
157
158
|
|
158
|
-
context
|
159
|
-
it
|
160
|
-
follow_prompts
|
161
|
-
expect(
|
159
|
+
context 'and required' do
|
160
|
+
it 'does not require input' do
|
161
|
+
follow_prompts '' do
|
162
|
+
expect(
|
163
|
+
subject.provide('Gimme', required: true, default: 'adefault')
|
164
|
+
).to eq 'adefault'
|
162
165
|
end
|
163
166
|
end
|
164
167
|
end
|
165
168
|
|
166
|
-
context
|
167
|
-
it
|
168
|
-
follow_prompts(
|
169
|
-
expect(call_method).to eq
|
169
|
+
context 'with no input' do
|
170
|
+
it 'returns the default' do
|
171
|
+
follow_prompts('') do
|
172
|
+
expect(call_method).to eq 'adefault'
|
170
173
|
end
|
171
174
|
end
|
172
175
|
end
|
173
176
|
|
174
|
-
context
|
175
|
-
it
|
176
|
-
follow_prompts(
|
177
|
-
expect(call_method).to eq
|
177
|
+
context 'with input' do
|
178
|
+
it 'returns the input' do
|
179
|
+
follow_prompts('here') do
|
180
|
+
expect(call_method).to eq 'here'
|
178
181
|
end
|
179
182
|
end
|
180
183
|
end
|
181
184
|
end
|
182
185
|
|
183
|
-
context
|
184
|
-
it
|
185
|
-
follow_prompts
|
186
|
-
expect(subject.provide(
|
186
|
+
context 'optional' do
|
187
|
+
it 'does not require input' do
|
188
|
+
follow_prompts '' do
|
189
|
+
expect(subject.provide('Gimme', required: false)).to eq nil
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
context 'with frozen string literals (in anticipation of ruby3)' do
|
195
|
+
it 'does not attempt to modify frozen string' do
|
196
|
+
follow_prompts 'here' do
|
197
|
+
expect { subject.provide('Gimme') }.not_to raise_error
|
187
198
|
end
|
188
199
|
end
|
189
200
|
end
|
190
201
|
end
|
191
202
|
|
192
|
-
describe
|
193
|
-
it
|
194
|
-
output = follow_prompts(
|
195
|
-
expect(output).to include
|
203
|
+
describe '#choice' do
|
204
|
+
it 'prompts the user to answer the question' do
|
205
|
+
output = follow_prompts('Y') { subject.choice('Should I?') }
|
206
|
+
expect(output).to include 'Should I?'
|
196
207
|
end
|
197
208
|
|
198
|
-
it
|
199
|
-
output = follow_prompts(
|
200
|
-
expect(output).to include
|
209
|
+
it 'defaults to a Y/N question' do
|
210
|
+
output = follow_prompts('Y') { subject.choice('Should I?') }
|
211
|
+
expect(output).to include '(Y/N)'
|
201
212
|
end
|
202
213
|
|
203
|
-
it
|
204
|
-
follow_prompts(
|
214
|
+
it 'returns true for Y' do
|
215
|
+
follow_prompts('Y') { expect(subject.choice('Should I?')).to eq true }
|
205
216
|
end
|
206
217
|
|
207
|
-
it
|
208
|
-
follow_prompts(
|
218
|
+
it 'returns true for Y' do
|
219
|
+
follow_prompts('N') { expect(subject.choice('Should I?')).to eq false }
|
209
220
|
end
|
210
221
|
|
211
|
-
context
|
212
|
-
it
|
213
|
-
output = follow_prompts(
|
214
|
-
|
222
|
+
context 'with available choices provided' do
|
223
|
+
it 'displays those choices' do
|
224
|
+
output = follow_prompts('Nick') do
|
225
|
+
subject.choice("What's your name?", %w(Nick Brendan))
|
226
|
+
end
|
227
|
+
|
228
|
+
expect(output).to include '(Nick/Brendan)'
|
215
229
|
end
|
216
230
|
|
217
231
|
it "returns the user's choice" do
|
218
|
-
follow_prompts(
|
219
|
-
expect(subject.choice("What's your name?",
|
232
|
+
follow_prompts('Nick') do
|
233
|
+
expect(subject.choice("What's your name?", %w(Nick Brendan)))
|
234
|
+
.to eq 'Nick'
|
220
235
|
end
|
221
236
|
end
|
222
237
|
|
223
|
-
it
|
224
|
-
follow_prompts(
|
225
|
-
expect(subject.choice("What's your name?",
|
238
|
+
it 'prompts repeatedly until it receives input in available choices' do
|
239
|
+
follow_prompts('Sally', 'Frank', 'Nick') do
|
240
|
+
expect(subject.choice("What's your name?", %w(Nick Brendan)))
|
241
|
+
.to eq 'Nick'
|
226
242
|
end
|
227
243
|
end
|
228
244
|
end
|
229
245
|
|
230
|
-
context
|
246
|
+
context 'with a block' do
|
231
247
|
it "calls the block with the user's choice" do
|
232
|
-
follow_prompts(
|
248
|
+
follow_prompts('Nick') do
|
233
249
|
expect do |block|
|
234
|
-
subject.choice("What's your name?",
|
235
|
-
end.to yield_with_args(
|
250
|
+
subject.choice("What's your name?", %w(Nick Brendan), &block)
|
251
|
+
end.to yield_with_args('Nick')
|
236
252
|
end
|
237
253
|
end
|
238
254
|
end
|
239
255
|
end
|
240
256
|
|
241
|
-
describe
|
242
|
-
before { subject.
|
257
|
+
describe '#rake' do
|
258
|
+
before { allow(subject).to receive(:system).and_return(true) }
|
243
259
|
|
244
|
-
it
|
245
|
-
output = capture_stdout { subject.rake
|
246
|
-
expect(output).to include
|
260
|
+
it 'outputs lead-in message' do
|
261
|
+
output = capture_stdout { subject.rake 'the_task' }
|
262
|
+
expect(output).to include '== Running the_task'
|
247
263
|
end
|
248
264
|
|
249
|
-
it
|
250
|
-
subject.
|
251
|
-
subject.rake
|
265
|
+
it 'runs the rake task' do
|
266
|
+
expect(subject).to receive(:system).with('rake the_task')
|
267
|
+
subject.rake 'the_task'
|
252
268
|
end
|
253
269
|
|
254
|
-
it
|
255
|
-
output = capture_stdout { subject.rake
|
256
|
-
expect(output).to include
|
270
|
+
it 'outputs completed message' do
|
271
|
+
output = capture_stdout { subject.rake 'the_task' }
|
272
|
+
expect(output).to include '== Completed the_task'
|
257
273
|
end
|
258
274
|
end
|
259
275
|
|
260
|
-
describe
|
261
|
-
let(:adapter) { double(
|
276
|
+
describe '#env' do
|
277
|
+
let(:adapter) { double('adapter', set: true) }
|
262
278
|
before { Stairs.configuration.env_adapter = adapter }
|
263
279
|
|
264
280
|
it "delegates to the adapter's set" do
|
265
|
-
adapter.
|
266
|
-
subject.env
|
281
|
+
expect(adapter).to receive(:set).with('NAME', 'value')
|
282
|
+
subject.env 'NAME', 'value'
|
267
283
|
end
|
268
284
|
|
269
|
-
it
|
270
|
-
ENV.
|
271
|
-
subject.env
|
285
|
+
it 'writes to ENV simultaneously so Rubyland can access without a reload' do
|
286
|
+
expect(ENV).to receive(:[]=).with('NAME', 'value')
|
287
|
+
subject.env 'NAME', 'value'
|
272
288
|
end
|
273
289
|
|
274
|
-
context
|
290
|
+
context 'with no value' do
|
275
291
|
it "delegates to the adapter's unset" do
|
276
|
-
adapter.
|
277
|
-
subject.env
|
292
|
+
expect(adapter).to receive(:unset).with('NAME')
|
293
|
+
subject.env 'NAME', nil
|
278
294
|
end
|
279
295
|
end
|
280
296
|
end
|
281
297
|
|
282
|
-
describe
|
283
|
-
it
|
284
|
-
Stairs::Util::FileMutation
|
285
|
-
|
298
|
+
describe '#write' do
|
299
|
+
it 'delegates to the well tested FileMutation util' do
|
300
|
+
expect(Stairs::Util::FileMutation)
|
301
|
+
.to receive(:write).with('something', 'file.txt')
|
302
|
+
|
303
|
+
subject.write('something', 'file.txt')
|
286
304
|
end
|
287
305
|
end
|
288
306
|
|
289
|
-
describe
|
290
|
-
it
|
291
|
-
Stairs::Util::FileMutation
|
292
|
-
|
307
|
+
describe '#write_line' do
|
308
|
+
it 'delegates to the well tested FileMutation util' do
|
309
|
+
expect(Stairs::Util::FileMutation)
|
310
|
+
.to receive(:write_line).with('something', 'file.txt')
|
311
|
+
|
312
|
+
subject.write_line('something', 'file.txt')
|
293
313
|
end
|
294
314
|
end
|
295
315
|
|
296
|
-
describe
|
297
|
-
it
|
298
|
-
output = capture_stdout { subject.finish
|
299
|
-
expect(output).to include
|
316
|
+
describe '#finish' do
|
317
|
+
it 'outputs lead-in message' do
|
318
|
+
output = capture_stdout { subject.finish 'Message' }
|
319
|
+
expect(output).to include '== All done!'
|
300
320
|
end
|
301
321
|
|
302
|
-
it
|
303
|
-
output = capture_stdout { subject.finish
|
304
|
-
expect(output).to include
|
322
|
+
it 'outputs supplied message' do
|
323
|
+
output = capture_stdout { subject.finish 'My message' }
|
324
|
+
expect(output).to include 'My message'
|
305
325
|
end
|
306
326
|
end
|
307
327
|
|
308
|
-
describe
|
309
|
-
it
|
310
|
-
output = capture_stdout { subject.stairs_info
|
311
|
-
expect(output).to include
|
328
|
+
describe '#stairs_info' do
|
329
|
+
it 'outputs the message' do
|
330
|
+
output = capture_stdout { subject.stairs_info 'Ohai' }
|
331
|
+
expect(output).to include 'Ohai'
|
312
332
|
end
|
313
333
|
end
|
314
334
|
|
315
|
-
describe
|
316
|
-
context
|
317
|
-
it
|
335
|
+
describe '#setup' do
|
336
|
+
context 'with an invalid step_name' do
|
337
|
+
it 'raises when step_name cannot be resolved in Stairs::Steps' do
|
318
338
|
expect { subject.setup :blahblahbefkj }.to raise_error
|
319
339
|
end
|
320
340
|
end
|
321
341
|
|
322
|
-
context
|
323
|
-
let!(:mock_step_class)
|
324
|
-
|
342
|
+
context 'with a valid step_name' do
|
343
|
+
let!(:mock_step_class) do
|
344
|
+
Stairs::Steps::MockStep = Class.new(Stairs::Step)
|
345
|
+
end
|
346
|
+
before do
|
347
|
+
allow_any_instance_of(mock_step_class)
|
348
|
+
.to receive(:run!).and_return(true)
|
349
|
+
end
|
325
350
|
|
326
|
-
it
|
327
|
-
mock_step_class.
|
351
|
+
it 'instantiates and runs the step' do
|
352
|
+
expect_any_instance_of(mock_step_class).to receive(:run!)
|
328
353
|
subject.setup :mock_step
|
329
354
|
end
|
330
355
|
|
331
|
-
it
|
332
|
-
mock_step_class
|
356
|
+
it 'passes groups to the step' do
|
357
|
+
expect(mock_step_class)
|
358
|
+
.to receive(:new).with(groups, {}).and_call_original
|
359
|
+
|
333
360
|
subject.setup :mock_step
|
334
361
|
end
|
335
362
|
|
336
|
-
context
|
337
|
-
let(:options) { { something:
|
363
|
+
context 'with options' do
|
364
|
+
let(:options) { { something: 'cool' } }
|
365
|
+
|
366
|
+
it 'passes options to the step' do
|
367
|
+
expect(mock_step_class)
|
368
|
+
.to receive(:new).with(groups, options).and_call_original
|
338
369
|
|
339
|
-
it "passes options to the step" do
|
340
|
-
mock_step_class.should_receive(:new).with(groups, options).and_call_original
|
341
370
|
subject.setup :mock_step, options
|
342
371
|
end
|
343
372
|
end
|
344
373
|
end
|
345
374
|
|
346
|
-
context
|
375
|
+
context 'with a block' do
|
347
376
|
def call_method
|
348
377
|
subject.setup(:custom_step) { puts "I'm running in #{self.class}" }
|
349
378
|
end
|
@@ -351,62 +380,69 @@ describe Stairs::Step do
|
|
351
380
|
# Initialize primary subject before asserting against #new for the Step
|
352
381
|
# it initializes
|
353
382
|
def initialize_primary_subject
|
354
|
-
|
383
|
+
subject
|
355
384
|
end
|
356
385
|
|
357
386
|
it "sets the new step's title to a titleized version of step_name" do
|
358
387
|
output = capture_stdout { call_method }
|
359
|
-
expect(output).to include
|
388
|
+
expect(output).to include 'Custom Step'
|
360
389
|
end
|
361
390
|
|
362
|
-
it
|
391
|
+
it 'runs the block in the context of the new step' do
|
363
392
|
output = capture_stdout { call_method }
|
364
393
|
expect(output).to include "I'm running in Stairs::Step"
|
365
394
|
end
|
366
395
|
|
367
|
-
it
|
396
|
+
it 'passes groups to the step' do
|
368
397
|
initialize_primary_subject
|
369
398
|
|
370
|
-
described_class
|
399
|
+
expect(described_class)
|
400
|
+
.to receive(:new).with(groups, {}).and_call_original
|
401
|
+
|
371
402
|
call_method
|
372
403
|
end
|
373
404
|
|
374
|
-
context
|
375
|
-
let(:options) { { something:
|
376
|
-
before
|
405
|
+
context 'with options' do
|
406
|
+
let(:options) { { something: 'cool' } }
|
407
|
+
before do
|
408
|
+
allow_any_instance_of(described_class)
|
409
|
+
.to receive(:run!).and_return(true)
|
410
|
+
end
|
377
411
|
|
378
|
-
it
|
412
|
+
it 'passes options to the step' do
|
379
413
|
initialize_primary_subject
|
380
414
|
|
381
|
-
described_class
|
415
|
+
expect(described_class)
|
416
|
+
.to receive(:new).with(groups, options).and_call_original
|
417
|
+
|
382
418
|
subject.setup(:custom_step, options) { true }
|
383
419
|
end
|
384
420
|
end
|
385
421
|
end
|
386
422
|
end
|
387
423
|
|
388
|
-
describe
|
424
|
+
describe '#group' do
|
389
425
|
let(:name) { :reset }
|
390
426
|
|
391
|
-
context
|
427
|
+
context 'when the name is in the groups to run' do
|
392
428
|
let(:groups) { [:reset, :init] }
|
393
429
|
|
394
|
-
it
|
430
|
+
it 'calls the supplied block' do
|
395
431
|
expect { |b| subject.group(name, &b) }.to yield_control
|
396
432
|
end
|
397
433
|
end
|
398
434
|
|
399
|
-
context
|
435
|
+
context 'when the name is not in the groups to run' do
|
400
436
|
let(:groups) { [:init] }
|
401
437
|
|
402
|
-
it
|
438
|
+
it 'does not call the supplied block' do
|
403
439
|
expect { |b| subject.group(name, &b) }.not_to yield_control
|
404
440
|
end
|
405
441
|
|
406
|
-
context
|
442
|
+
context 'but no groups to run are provided' do
|
407
443
|
let(:groups) { nil }
|
408
444
|
|
409
|
-
it
|
445
|
+
it 'calls the supplied block' do
|
410
446
|
expect { |b| subject.group(name, &b) }.to yield_control
|
411
447
|
end
|
412
448
|
end
|