capistrano 3.4.1 → 3.5.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/.gitignore +7 -5
- data/.rubocop.yml +49 -0
- data/.travis.yml +5 -4
- data/CHANGELOG.md +72 -9
- data/CONTRIBUTING.md +61 -93
- data/DEVELOPMENT.md +122 -0
- data/Gemfile +2 -2
- data/LICENSE.txt +1 -1
- data/README.md +121 -43
- data/RELEASING.md +16 -0
- data/Rakefile +4 -1
- data/bin/cap +1 -1
- data/capistrano.gemspec +16 -21
- data/features/doctor.feature +11 -0
- data/features/step_definitions/assertions.rb +17 -17
- data/features/step_definitions/cap_commands.rb +0 -1
- data/features/step_definitions/setup.rb +12 -8
- data/features/support/env.rb +5 -5
- data/features/support/remote_command_helpers.rb +8 -6
- data/features/support/vagrant_helpers.rb +5 -4
- data/issue_template.md +21 -0
- data/lib/Capfile +5 -1
- data/lib/capistrano/all.rb +9 -10
- data/lib/capistrano/application.rb +36 -26
- data/lib/capistrano/configuration.rb +56 -41
- data/lib/capistrano/configuration/empty_filter.rb +9 -0
- data/lib/capistrano/configuration/filter.rb +18 -47
- data/lib/capistrano/configuration/host_filter.rb +30 -0
- data/lib/capistrano/configuration/null_filter.rb +9 -0
- data/lib/capistrano/configuration/plugin_installer.rb +33 -0
- data/lib/capistrano/configuration/question.rb +10 -7
- data/lib/capistrano/configuration/role_filter.rb +30 -0
- data/lib/capistrano/configuration/server.rb +22 -23
- data/lib/capistrano/configuration/servers.rb +6 -7
- data/lib/capistrano/configuration/variables.rb +136 -0
- data/lib/capistrano/defaults.rb +13 -3
- data/lib/capistrano/deploy.rb +1 -1
- data/lib/capistrano/doctor.rb +5 -0
- data/lib/capistrano/doctor/environment_doctor.rb +19 -0
- data/lib/capistrano/doctor/gems_doctor.rb +45 -0
- data/lib/capistrano/doctor/output_helpers.rb +79 -0
- data/lib/capistrano/doctor/variables_doctor.rb +66 -0
- data/lib/capistrano/dotfile.rb +1 -2
- data/lib/capistrano/dsl.rb +12 -14
- data/lib/capistrano/dsl/env.rb +11 -42
- data/lib/capistrano/dsl/paths.rb +12 -13
- data/lib/capistrano/dsl/stages.rb +2 -4
- data/lib/capistrano/dsl/task_enhancements.rb +5 -7
- data/lib/capistrano/framework.rb +1 -1
- data/lib/capistrano/git.rb +17 -9
- data/lib/capistrano/hg.rb +4 -4
- data/lib/capistrano/i18n.rb +24 -24
- data/lib/capistrano/immutable_task.rb +29 -0
- data/lib/capistrano/install.rb +1 -1
- data/lib/capistrano/plugin.rb +95 -0
- data/lib/capistrano/scm.rb +7 -20
- data/lib/capistrano/setup.rb +19 -5
- data/lib/capistrano/svn.rb +9 -5
- data/lib/capistrano/tasks/console.rake +4 -8
- data/lib/capistrano/tasks/deploy.rake +75 -62
- data/lib/capistrano/tasks/doctor.rake +19 -0
- data/lib/capistrano/tasks/framework.rake +13 -14
- data/lib/capistrano/tasks/git.rake +10 -11
- data/lib/capistrano/tasks/hg.rake +7 -7
- data/lib/capistrano/tasks/install.rake +14 -15
- data/lib/capistrano/tasks/svn.rake +7 -7
- data/lib/capistrano/templates/Capfile +3 -3
- data/lib/capistrano/templates/deploy.rb.erb +6 -5
- data/lib/capistrano/upload_task.rb +1 -1
- data/lib/capistrano/version.rb +1 -1
- data/lib/capistrano/version_validator.rb +4 -6
- data/spec/integration/dsl_spec.rb +286 -239
- data/spec/integration_spec_helper.rb +3 -5
- data/spec/lib/capistrano/application_spec.rb +22 -14
- data/spec/lib/capistrano/configuration/empty_filter_spec.rb +17 -0
- data/spec/lib/capistrano/configuration/filter_spec.rb +82 -84
- data/spec/lib/capistrano/configuration/host_filter_spec.rb +61 -0
- data/spec/lib/capistrano/configuration/null_filter_spec.rb +17 -0
- data/spec/lib/capistrano/configuration/question_spec.rb +12 -16
- data/spec/lib/capistrano/configuration/role_filter_spec.rb +64 -0
- data/spec/lib/capistrano/configuration/server_spec.rb +102 -110
- data/spec/lib/capistrano/configuration/servers_spec.rb +124 -141
- data/spec/lib/capistrano/configuration_spec.rb +150 -61
- data/spec/lib/capistrano/doctor/environment_doctor_spec.rb +44 -0
- data/spec/lib/capistrano/doctor/gems_doctor_spec.rb +61 -0
- data/spec/lib/capistrano/doctor/output_helpers_spec.rb +47 -0
- data/spec/lib/capistrano/doctor/variables_doctor_spec.rb +79 -0
- data/spec/lib/capistrano/dsl/paths_spec.rb +58 -50
- data/spec/lib/capistrano/dsl/task_enhancements_spec.rb +62 -32
- data/spec/lib/capistrano/dsl_spec.rb +6 -8
- data/spec/lib/capistrano/git_spec.rb +35 -7
- data/spec/lib/capistrano/hg_spec.rb +14 -5
- data/spec/lib/capistrano/immutable_task_spec.rb +31 -0
- data/spec/lib/capistrano/plugin_spec.rb +84 -0
- data/spec/lib/capistrano/scm_spec.rb +6 -7
- data/spec/lib/capistrano/svn_spec.rb +40 -14
- data/spec/lib/capistrano/upload_task_spec.rb +7 -7
- data/spec/lib/capistrano/version_validator_spec.rb +37 -45
- data/spec/lib/capistrano_spec.rb +2 -3
- data/spec/spec_helper.rb +8 -8
- data/spec/support/Vagrantfile +9 -10
- data/spec/support/tasks/database.rake +3 -3
- data/spec/support/tasks/fail.rake +4 -3
- data/spec/support/tasks/failed.rake +2 -2
- data/spec/support/tasks/plugin.rake +6 -0
- data/spec/support/tasks/root.rake +4 -4
- data/spec/support/test_app.rb +31 -30
- metadata +93 -14
@@ -0,0 +1,64 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module Capistrano
|
4
|
+
class Configuration
|
5
|
+
describe RoleFilter do
|
6
|
+
subject(:role_filter) { RoleFilter.new(values) }
|
7
|
+
|
8
|
+
let(:available) do
|
9
|
+
[
|
10
|
+
Server.new("server1").add_roles([:web, :db]),
|
11
|
+
Server.new("server2").add_role(:web),
|
12
|
+
Server.new("server3").add_role(:redis),
|
13
|
+
Server.new("server4").add_role(:db),
|
14
|
+
Server.new("server5").add_role(:stageweb)
|
15
|
+
]
|
16
|
+
end
|
17
|
+
|
18
|
+
shared_examples "it filters roles correctly" do |expected_size, expected|
|
19
|
+
it "filters correctly" do
|
20
|
+
set = role_filter.filter(available)
|
21
|
+
expect(set.size).to eq(expected_size)
|
22
|
+
expect(set.map(&:hostname)).to eq(expected)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#filter' do
|
27
|
+
context "with a single role string" do
|
28
|
+
let(:values) { "web" }
|
29
|
+
it_behaves_like "it filters roles correctly", 2, %w{server1 server2}
|
30
|
+
end
|
31
|
+
|
32
|
+
context "with a single role" do
|
33
|
+
let(:values) { [:web] }
|
34
|
+
it_behaves_like "it filters roles correctly", 2, %w{server1 server2}
|
35
|
+
end
|
36
|
+
|
37
|
+
context "with multiple roles in a string" do
|
38
|
+
let(:values) { "web,db" }
|
39
|
+
it_behaves_like "it filters roles correctly", 3, %w{server1 server2 server4}
|
40
|
+
end
|
41
|
+
|
42
|
+
context "with multiple roles" do
|
43
|
+
let(:values) { [:web, :db] }
|
44
|
+
it_behaves_like "it filters roles correctly", 3, %w{server1 server2 server4}
|
45
|
+
end
|
46
|
+
|
47
|
+
context "with a regex" do
|
48
|
+
let(:values) { /red/ }
|
49
|
+
it_behaves_like "it filters roles correctly", 1, %w{server3}
|
50
|
+
end
|
51
|
+
|
52
|
+
context "with a regex string" do
|
53
|
+
let(:values) { "/red|web/" }
|
54
|
+
it_behaves_like "it filters roles correctly", 4, %w{server1 server2 server3 server5}
|
55
|
+
end
|
56
|
+
|
57
|
+
context "with both a string and regex" do
|
58
|
+
let(:values) { "db,/red/" }
|
59
|
+
it_behaves_like "it filters roles correctly", 3, %w{server1 server3 server4}
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -1,141 +1,139 @@
|
|
1
|
-
require
|
1
|
+
require "spec_helper"
|
2
2
|
|
3
3
|
module Capistrano
|
4
4
|
class Configuration
|
5
5
|
describe Server do
|
6
|
-
let(:server) { Server.new(
|
6
|
+
let(:server) { Server.new("root@hostname:1234") }
|
7
7
|
|
8
|
-
describe
|
8
|
+
describe "adding a role" do
|
9
9
|
subject { server.add_role(:test) }
|
10
|
-
it
|
11
|
-
expect{subject}.to change{server.roles.size}.from(0).to(1)
|
10
|
+
it "adds the role" do
|
11
|
+
expect { subject }.to change { server.roles.size }.from(0).to(1)
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
describe
|
15
|
+
describe "adding roles" do
|
16
16
|
subject { server.add_roles([:things, :stuff]) }
|
17
|
-
it
|
18
|
-
expect{subject}.to change{server.roles.size}.from(0).to(2)
|
17
|
+
it "adds the roles" do
|
18
|
+
expect { subject }.to change { server.roles.size }.from(0).to(2)
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
|
23
|
-
describe 'checking roles' do
|
22
|
+
describe "checking roles" do
|
24
23
|
subject { server.has_role?(:test) }
|
25
24
|
|
26
25
|
before do
|
27
26
|
server.add_role(:test)
|
28
27
|
end
|
29
28
|
|
30
|
-
it
|
29
|
+
it "adds the role" do
|
31
30
|
expect(subject).to be_truthy
|
32
31
|
end
|
33
32
|
end
|
34
33
|
|
35
|
-
describe
|
34
|
+
describe "comparing identity" do
|
36
35
|
subject { server.hostname == Server[hostname].hostname }
|
37
36
|
|
38
|
-
context
|
39
|
-
let(:hostname) {
|
37
|
+
context "with the same user, hostname and port" do
|
38
|
+
let(:hostname) { "root@hostname:1234" }
|
40
39
|
it { expect(subject).to be_truthy }
|
41
40
|
end
|
42
41
|
|
43
|
-
context
|
44
|
-
let(:hostname) {
|
42
|
+
context "with a different user" do
|
43
|
+
let(:hostname) { "deployer@hostname:1234" }
|
45
44
|
it { expect(subject).to be_truthy }
|
46
45
|
end
|
47
46
|
|
48
|
-
context
|
49
|
-
let(:hostname) {
|
47
|
+
context "with a different port" do
|
48
|
+
let(:hostname) { "root@hostname:5678" }
|
50
49
|
it { expect(subject).to be_truthy }
|
51
50
|
end
|
52
51
|
|
53
|
-
context
|
54
|
-
let(:hostname) {
|
52
|
+
context "with a different hostname" do
|
53
|
+
let(:hostname) { "root@otherserver:1234" }
|
55
54
|
it { expect(subject).to be_falsey }
|
56
55
|
end
|
57
56
|
end
|
58
57
|
|
59
|
-
describe
|
58
|
+
describe "identifying as primary" do
|
60
59
|
subject { server.primary }
|
61
|
-
context
|
60
|
+
context "server is primary" do
|
62
61
|
before do
|
63
62
|
server.set(:primary, true)
|
64
63
|
end
|
65
|
-
it
|
64
|
+
it "returns self" do
|
66
65
|
expect(subject).to eq server
|
67
66
|
end
|
68
67
|
end
|
69
68
|
|
70
|
-
context
|
71
|
-
it
|
69
|
+
context "server is not primary" do
|
70
|
+
it "is falesy" do
|
72
71
|
expect(subject).to be_falsey
|
73
72
|
end
|
74
73
|
end
|
75
74
|
end
|
76
75
|
|
77
|
-
describe
|
78
|
-
|
76
|
+
describe "assigning properties" do
|
79
77
|
before do
|
80
78
|
server.with(properties)
|
81
79
|
end
|
82
80
|
|
83
|
-
context
|
84
|
-
let(:properties) { {roles: [:clouds]} }
|
81
|
+
context "properties contains roles" do
|
82
|
+
let(:properties) { { roles: [:clouds] } }
|
85
83
|
|
86
|
-
it
|
84
|
+
it "adds the roles" do
|
87
85
|
expect(server.roles.first).to eq :clouds
|
88
86
|
end
|
89
87
|
end
|
90
88
|
|
91
|
-
context
|
92
|
-
let(:properties) { {user:
|
89
|
+
context "properties contains user" do
|
90
|
+
let(:properties) { { user: "tomc" } }
|
93
91
|
|
94
|
-
it
|
95
|
-
expect(server.user).to eq
|
92
|
+
it "sets the user" do
|
93
|
+
expect(server.user).to eq "tomc"
|
96
94
|
end
|
97
95
|
|
98
|
-
it
|
99
|
-
expect(server.netssh_options[:user]).to eq
|
96
|
+
it "sets the netssh_options user" do
|
97
|
+
expect(server.netssh_options[:user]).to eq "tomc"
|
100
98
|
end
|
101
99
|
end
|
102
100
|
|
103
|
-
context
|
104
|
-
let(:properties) { {port: 2222} }
|
101
|
+
context "properties contains port" do
|
102
|
+
let(:properties) { { port: 2222 } }
|
105
103
|
|
106
|
-
it
|
104
|
+
it "sets the port" do
|
107
105
|
expect(server.port).to eq 2222
|
108
106
|
end
|
109
107
|
end
|
110
108
|
|
111
|
-
context
|
112
|
-
let(:properties) { {key:
|
109
|
+
context "properties contains key" do
|
110
|
+
let(:properties) { { key: "/key" } }
|
113
111
|
|
114
|
-
it
|
115
|
-
expect(server.keys).to include
|
112
|
+
it "adds the key" do
|
113
|
+
expect(server.keys).to include "/key"
|
116
114
|
end
|
117
115
|
end
|
118
116
|
|
119
|
-
context
|
120
|
-
let(:properties) { {password:
|
117
|
+
context "properties contains password" do
|
118
|
+
let(:properties) { { password: "supersecret" } }
|
121
119
|
|
122
|
-
it
|
123
|
-
expect(server.password).to eq
|
120
|
+
it "adds the key" do
|
121
|
+
expect(server.password).to eq "supersecret"
|
124
122
|
end
|
125
123
|
end
|
126
124
|
|
127
|
-
context
|
125
|
+
context "new properties" do
|
128
126
|
let(:properties) { { webscales: 5 } }
|
129
127
|
|
130
|
-
it
|
128
|
+
it "adds the properties" do
|
131
129
|
expect(server.properties.webscales).to eq 5
|
132
130
|
end
|
133
131
|
end
|
134
132
|
|
135
|
-
context
|
133
|
+
context "existing properties" do
|
136
134
|
let(:properties) { { webscales: 6 } }
|
137
135
|
|
138
|
-
it
|
136
|
+
it "keeps the existing properties" do
|
139
137
|
expect(server.properties.webscales).to eq 6
|
140
138
|
server.properties.webscales = 5
|
141
139
|
expect(server.properties.webscales).to eq 5
|
@@ -152,128 +150,123 @@ module Capistrano
|
|
152
150
|
server.properties.active = true
|
153
151
|
end
|
154
152
|
|
155
|
-
context
|
153
|
+
context "options are empty" do
|
156
154
|
it { expect(subject).to be_truthy }
|
157
155
|
end
|
158
156
|
|
159
|
-
context
|
160
|
-
context
|
161
|
-
|
162
|
-
|
163
|
-
let(:options) { { filter: :active }}
|
157
|
+
context "value is a symbol" do
|
158
|
+
context "value matches server property" do
|
159
|
+
context "with :filter" do
|
160
|
+
let(:options) { { filter: :active } }
|
164
161
|
it { expect(subject).to be_truthy }
|
165
162
|
end
|
166
163
|
|
167
|
-
context
|
168
|
-
let(:options) { { select: :active }}
|
164
|
+
context "with :select" do
|
165
|
+
let(:options) { { select: :active } }
|
169
166
|
it { expect(subject).to be_truthy }
|
170
167
|
end
|
171
168
|
|
172
|
-
context
|
173
|
-
let(:options) { { exclude: :active }}
|
169
|
+
context "with :exclude" do
|
170
|
+
let(:options) { { exclude: :active } }
|
174
171
|
it { expect(subject).to be_falsey }
|
175
172
|
end
|
176
173
|
end
|
177
174
|
|
178
|
-
context
|
179
|
-
context
|
180
|
-
let(:options) { { active: true }}
|
175
|
+
context "value does not match server properly" do
|
176
|
+
context "with :active true" do
|
177
|
+
let(:options) { { active: true } }
|
181
178
|
it { expect(subject).to be_truthy }
|
182
179
|
end
|
183
180
|
|
184
|
-
context
|
185
|
-
let(:options) { { active: false }}
|
181
|
+
context "with :active false" do
|
182
|
+
let(:options) { { active: false } }
|
186
183
|
it { expect(subject).to be_falsey }
|
187
184
|
end
|
188
185
|
end
|
189
186
|
|
190
|
-
context
|
191
|
-
context
|
192
|
-
let(:options) { { filter: :inactive }}
|
187
|
+
context "value does not match server properly" do
|
188
|
+
context "with :filter" do
|
189
|
+
let(:options) { { filter: :inactive } }
|
193
190
|
it { expect(subject).to be_falsey }
|
194
191
|
end
|
195
192
|
|
196
|
-
context
|
197
|
-
let(:options) { { select: :inactive }}
|
193
|
+
context "with :select" do
|
194
|
+
let(:options) { { select: :inactive } }
|
198
195
|
it { expect(subject).to be_falsey }
|
199
196
|
end
|
200
197
|
|
201
|
-
context
|
202
|
-
let(:options) { { exclude: :inactive }}
|
198
|
+
context "with :exclude" do
|
199
|
+
let(:options) { { exclude: :inactive } }
|
203
200
|
it { expect(subject).to be_truthy }
|
204
201
|
end
|
205
202
|
end
|
206
203
|
end
|
207
204
|
|
208
|
-
context
|
209
|
-
context
|
210
|
-
let(:options) { { active: true }}
|
205
|
+
context "key is a property" do
|
206
|
+
context "with :active true" do
|
207
|
+
let(:options) { { active: true } }
|
211
208
|
it { expect(subject).to be_truthy }
|
212
209
|
end
|
213
210
|
|
214
|
-
context
|
215
|
-
let(:options) { { active: false }}
|
211
|
+
context "with :active false" do
|
212
|
+
let(:options) { { active: false } }
|
216
213
|
it { expect(subject).to be_falsey }
|
217
214
|
end
|
218
215
|
end
|
219
216
|
|
220
|
-
context
|
221
|
-
context
|
222
|
-
|
223
|
-
context 'with :filter' do
|
217
|
+
context "value is a proc" do
|
218
|
+
context "value matches server property" do
|
219
|
+
context "with :filter" do
|
224
220
|
let(:options) { { filter: ->(s) { s.properties.active } } }
|
225
221
|
it { expect(subject).to be_truthy }
|
226
222
|
end
|
227
223
|
|
228
|
-
context
|
224
|
+
context "with :select" do
|
229
225
|
let(:options) { { select: ->(s) { s.properties.active } } }
|
230
226
|
it { expect(subject).to be_truthy }
|
231
227
|
end
|
232
228
|
|
233
|
-
context
|
229
|
+
context "with :exclude" do
|
234
230
|
let(:options) { { exclude: ->(s) { s.properties.active } } }
|
235
231
|
it { expect(subject).to be_falsey }
|
236
232
|
end
|
237
|
-
|
238
233
|
end
|
239
234
|
|
240
|
-
context
|
241
|
-
context
|
235
|
+
context "value does not match server properly" do
|
236
|
+
context "with :filter" do
|
242
237
|
let(:options) { { filter: ->(s) { s.properties.inactive } } }
|
243
238
|
it { expect(subject).to be_falsey }
|
244
239
|
end
|
245
240
|
|
246
|
-
context
|
241
|
+
context "with :select" do
|
247
242
|
let(:options) { { select: ->(s) { s.properties.inactive } } }
|
248
243
|
it { expect(subject).to be_falsey }
|
249
244
|
end
|
250
245
|
|
251
|
-
context
|
246
|
+
context "with :exclude" do
|
252
247
|
let(:options) { { exclude: ->(s) { s.properties.inactive } } }
|
253
248
|
it { expect(subject).to be_truthy }
|
254
249
|
end
|
255
|
-
|
256
250
|
end
|
257
251
|
end
|
258
|
-
|
259
252
|
end
|
260
253
|
|
261
|
-
describe
|
262
|
-
let(:server) { Server.new(
|
254
|
+
describe "assign ssh_options" do
|
255
|
+
let(:server) { Server.new("user_name@hostname") }
|
263
256
|
|
264
|
-
context
|
265
|
-
it
|
257
|
+
context "defaults" do
|
258
|
+
it "forward agent" do
|
266
259
|
expect(server.netssh_options[:forward_agent]).to eq true
|
267
260
|
end
|
268
|
-
it
|
269
|
-
expect(server.netssh_options[:user]).to eq
|
261
|
+
it "contains user" do
|
262
|
+
expect(server.netssh_options[:user]).to eq "user_name"
|
270
263
|
end
|
271
264
|
end
|
272
265
|
|
273
|
-
context
|
266
|
+
context "custom" do
|
274
267
|
let(:properties) do
|
275
268
|
{ ssh_options: {
|
276
|
-
user:
|
269
|
+
user: "another_user",
|
277
270
|
keys: %w(/home/another_user/.ssh/id_rsa),
|
278
271
|
forward_agent: false,
|
279
272
|
auth_methods: %w(publickey password) } }
|
@@ -283,31 +276,30 @@ module Capistrano
|
|
283
276
|
server.with(properties)
|
284
277
|
end
|
285
278
|
|
286
|
-
it
|
279
|
+
it "not forward agent" do
|
287
280
|
expect(server.netssh_options[:forward_agent]).to eq false
|
288
281
|
end
|
289
|
-
it
|
290
|
-
expect(server.netssh_options[:user]).to eq
|
282
|
+
it "contains correct user" do
|
283
|
+
expect(server.netssh_options[:user]).to eq "another_user"
|
291
284
|
end
|
292
|
-
it
|
293
|
-
expect(server.user).to eq
|
285
|
+
it "does not affect server user in host" do
|
286
|
+
expect(server.user).to eq "user_name"
|
294
287
|
end
|
295
|
-
it
|
288
|
+
it "contains keys" do
|
296
289
|
expect(server.netssh_options[:keys]).to eq %w(/home/another_user/.ssh/id_rsa)
|
297
290
|
end
|
298
|
-
it
|
291
|
+
it "contains auth_methods" do
|
299
292
|
expect(server.netssh_options[:auth_methods]).to eq %w(publickey password)
|
300
293
|
end
|
301
294
|
end
|
302
|
-
|
303
295
|
end
|
304
296
|
|
305
297
|
describe ".[]" do
|
306
|
-
it
|
307
|
-
expect(Server[
|
298
|
+
it "creates a server if its argument is not already a server" do
|
299
|
+
expect(Server["hostname:1234"]).to be_a Server
|
308
300
|
end
|
309
301
|
|
310
|
-
it
|
302
|
+
it "returns its argument if it is already a server" do
|
311
303
|
expect(Server[server]).to be server
|
312
304
|
end
|
313
305
|
end
|