taketo 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -1
- data/Gemfile.lock +3 -3
- data/README.md +20 -7
- data/VERSION +1 -1
- data/bin/taketo +30 -31
- data/features/config.feature +33 -3
- data/features/config_validation.feature +29 -4
- data/features/connect_to_server.feature +2 -1
- data/features/error_handling.feature +1 -0
- data/features/help.feature +5 -3
- data/features/support/env.rb +2 -0
- data/lib/taketo/associated_nodes.rb +90 -0
- data/lib/taketo/commands/ssh_command.rb +0 -4
- data/lib/taketo/config_printer_visitor.rb +68 -0
- data/lib/taketo/config_traverser.rb +55 -0
- data/lib/taketo/config_validator.rb +33 -34
- data/lib/taketo/config_visitor.rb +29 -0
- data/lib/taketo/constructs/base_construct.rb +9 -54
- data/lib/taketo/constructs/command.rb +9 -1
- data/lib/taketo/constructs/environment.rb +11 -1
- data/lib/taketo/constructs/project.rb +5 -0
- data/lib/taketo/constructs/server.rb +7 -4
- data/lib/taketo/dsl.rb +13 -2
- data/lib/taketo/support/named_nodes_collection.rb +10 -0
- data/lib/taketo/support.rb +0 -1
- data/lib/taketo.rb +2 -1
- data/spec/integration/dsl_integration_spec.rb +1 -1
- data/spec/lib/taketo/associated_nodes_spec.rb +101 -0
- data/spec/lib/taketo/commands/ssh_command_spec.rb +5 -15
- data/spec/lib/taketo/config_printer_visitor_spec.rb +112 -0
- data/spec/lib/taketo/config_traverser_spec.rb +63 -0
- data/spec/lib/taketo/config_validator_spec.rb +53 -39
- data/spec/lib/taketo/config_visitor_spec.rb +51 -0
- data/spec/lib/taketo/constructs/base_construct_spec.rb +7 -70
- data/spec/lib/taketo/constructs/command_spec.rb +20 -8
- data/spec/lib/taketo/constructs/config_spec.rb +2 -6
- data/spec/lib/taketo/constructs/environment_spec.rb +12 -7
- data/spec/lib/taketo/constructs/project_spec.rb +10 -4
- data/spec/lib/taketo/constructs/server_spec.rb +25 -16
- data/spec/lib/taketo/constructs_factory_spec.rb +12 -12
- data/spec/lib/taketo/destination_resolver_spec.rb +32 -32
- data/spec/lib/taketo/dsl_spec.rb +115 -98
- data/spec/lib/taketo/support/named_nodes_collection_spec.rb +49 -21
- data/spec/support/helpers/construct_spec_helper.rb +5 -5
- data/spec/support/matchers/be_appropriate_construct_matcher.rb +9 -1
- data/spec/support/matchers/have_accessor_matcher.rb +6 -3
- metadata +18 -7
- data/lib/taketo/config_printer.rb +0 -84
- data/lib/taketo/support/eval_delegator.rb +0 -25
- data/spec/lib/taketo/config_printer_spec.rb +0 -116
- data/spec/lib/taketo/support/eval_delegator_spec.rb +0 -43
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
require 'taketo/destination_resolver'
|
3
3
|
require 'taketo/support/named_nodes_collection'
|
4
4
|
|
@@ -50,29 +50,29 @@ describe "DestinationResolver" do
|
|
50
50
|
let(:config) { TestNode.new(:config, nil, project1, project2, project3, project4) }
|
51
51
|
|
52
52
|
context "when project, environment and server specified" do
|
53
|
-
it "
|
54
|
-
resolver(config, "foo:bar:s1").resolve.
|
53
|
+
it "returns server if it exists" do
|
54
|
+
expect(resolver(config, "foo:bar:s1").resolve).to eq(server1)
|
55
55
|
end
|
56
56
|
|
57
|
-
it "
|
57
|
+
it "raises error if server does not exist" do
|
58
58
|
expect { resolver(config, "foo:bar:noserver").resolve }.to raise_error(NonExistentDestinationError)
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
62
62
|
context "when there are 2 segments in path" do
|
63
63
|
context "when there is matching project - environment pair" do
|
64
|
-
it "
|
65
|
-
resolver(config, "foo:bar").resolve.
|
66
|
-
resolver(config, "baz:qux").resolve.
|
64
|
+
it "returns server if only one specified" do
|
65
|
+
expect(resolver(config, "foo:bar").resolve).to eq(server1)
|
66
|
+
expect(resolver(config, "baz:qux").resolve).to eq(server2)
|
67
67
|
end
|
68
68
|
|
69
|
-
it "
|
69
|
+
it "raises error if there are multiple servers" do
|
70
70
|
expect { resolver(config, "quux:corge").resolve }.to raise_error(AmbiguousDestinationError)
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
74
|
context "when there is no matching project - environment pair" do
|
75
|
-
it "
|
75
|
+
it "raises error if no such project - environment pair exist" do
|
76
76
|
expect { resolver(config, "chunky:bacon").resolve }.to raise_error(NonExistentDestinationError)
|
77
77
|
end
|
78
78
|
end
|
@@ -82,27 +82,27 @@ describe "DestinationResolver" do
|
|
82
82
|
context "when project with given name exists" do
|
83
83
|
context "when there's one environment" do
|
84
84
|
context "when there's one server" do
|
85
|
-
it "
|
86
|
-
resolver(config, "foo").resolve.
|
85
|
+
it "returns the server" do
|
86
|
+
expect(resolver(config, "foo").resolve).to eq(server1)
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
90
90
|
context "when there are multiple servers" do
|
91
|
-
it "
|
91
|
+
it "raises error" do
|
92
92
|
expect { resolver(config, "quux").resolve }.to raise_error(AmbiguousDestinationError)
|
93
93
|
end
|
94
94
|
end
|
95
95
|
end
|
96
96
|
|
97
97
|
context "when there are multiple environments" do
|
98
|
-
it "
|
98
|
+
it "raises error" do
|
99
99
|
expect { resolver(config, "grault").resolve }.to raise_error(AmbiguousDestinationError)
|
100
100
|
end
|
101
101
|
end
|
102
102
|
end
|
103
103
|
|
104
104
|
context "when there is no such project" do
|
105
|
-
it "
|
105
|
+
it "raises error" do
|
106
106
|
expect { resolver(config, "chunky").resolve }.to raise_error(NonExistentDestinationError)
|
107
107
|
end
|
108
108
|
end
|
@@ -113,15 +113,15 @@ describe "DestinationResolver" do
|
|
113
113
|
context "when there's one project" do
|
114
114
|
context "when there's one environment" do
|
115
115
|
context "when there's one server" do
|
116
|
-
it "
|
116
|
+
it "executes command without asking project/environment/server" do
|
117
117
|
config = TestNode.new(:config, nil, project1)
|
118
118
|
config.stub(:default_destination => nil)
|
119
|
-
resolver(config, "").resolve.
|
119
|
+
expect(resolver(config, "").resolve).to eq(server1)
|
120
120
|
end
|
121
121
|
end
|
122
122
|
|
123
123
|
context "when there are multiple servers" do
|
124
|
-
it "
|
124
|
+
it "asks for server" do
|
125
125
|
config = TestNode.new(:config, nil, project3)
|
126
126
|
config.stub(:default_destination => nil)
|
127
127
|
expect { resolver(config, "").resolve }.to raise_error AmbiguousDestinationError, /server/i
|
@@ -130,7 +130,7 @@ describe "DestinationResolver" do
|
|
130
130
|
end
|
131
131
|
|
132
132
|
context "when there are multiple environments" do
|
133
|
-
it "
|
133
|
+
it "asks for environment" do
|
134
134
|
config = TestNode.new(:config, nil, project4)
|
135
135
|
config.stub(:default_destination => nil)
|
136
136
|
expect { resolver(config, "").resolve }.to raise_error AmbiguousDestinationError, /environment/i
|
@@ -139,7 +139,7 @@ describe "DestinationResolver" do
|
|
139
139
|
end
|
140
140
|
|
141
141
|
context "when there are multiple projects" do
|
142
|
-
it "
|
142
|
+
it "asks for project" do
|
143
143
|
config = TestNode.new(:config, nil, project3, project4)
|
144
144
|
config.stub(:default_destination => nil)
|
145
145
|
|
@@ -149,38 +149,38 @@ describe "DestinationResolver" do
|
|
149
149
|
end
|
150
150
|
|
151
151
|
context "when there is default destination" do
|
152
|
-
it "
|
152
|
+
it "resolves by default destination" do
|
153
153
|
config.stub(:default_destination => "foo:bar:s1")
|
154
|
-
resolver(config, "").resolve.
|
154
|
+
expect(resolver(config, "").resolve).to eq(server1)
|
155
155
|
end
|
156
156
|
end
|
157
157
|
end
|
158
158
|
|
159
159
|
context "when there is global matching server alias" do
|
160
|
-
it "
|
161
|
-
resolver(config, "the_alias").resolve.
|
160
|
+
it "resolves by alias" do
|
161
|
+
expect(resolver(config, "the_alias").resolve).to eq(server1)
|
162
162
|
end
|
163
163
|
end
|
164
164
|
|
165
165
|
describe "#get_node" do
|
166
|
-
it "
|
167
|
-
resolver(config, "foo:bar:s1").get_node.
|
166
|
+
it "returns server when path has 3 segments and is correct" do
|
167
|
+
expect(resolver(config, "foo:bar:s1").get_node).to eq(server1)
|
168
168
|
end
|
169
169
|
|
170
|
-
it "
|
171
|
-
resolver(config, "foo:bar").get_node.
|
170
|
+
it "returns environment when path has 2 segments and is correct" do
|
171
|
+
expect(resolver(config, "foo:bar").get_node).to eq(environment1)
|
172
172
|
end
|
173
173
|
|
174
|
-
it "
|
175
|
-
resolver(config, "foo").get_node.
|
174
|
+
it "returns project when path has 1 segment and is correct" do
|
175
|
+
expect(resolver(config, "foo").get_node).to eq(project1)
|
176
176
|
end
|
177
177
|
|
178
|
-
it "
|
178
|
+
it "returns the config if path has is empty and there's no default destination" do
|
179
179
|
config.stub(:default_destination => nil)
|
180
|
-
resolver(config, "").get_node.
|
180
|
+
expect(resolver(config, "").get_node).to eq(config)
|
181
181
|
end
|
182
182
|
|
183
|
-
it "
|
183
|
+
it "raises NonExistentDestinationError when path is not correct" do
|
184
184
|
config.should_receive(:find).with(:project, :i).and_raise(KeyError)
|
185
185
|
expect { resolver(config, "i").get_node }.to raise_error(NonExistentDestinationError)
|
186
186
|
end
|
data/spec/lib/taketo/dsl_spec.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
require 'support/helpers/dsl_spec_helper'
|
3
3
|
require 'taketo/dsl'
|
4
4
|
|
@@ -8,57 +8,57 @@ describe "DSL" do
|
|
8
8
|
extend DSLSpec
|
9
9
|
include DSLSpec
|
10
10
|
|
11
|
-
shared_examples "a
|
11
|
+
shared_examples "a scoped construct" do |name, parent_scope_name, with_block|
|
12
12
|
parent_scope = scopes[parent_scope_name]
|
13
|
-
|
14
|
-
it { should enclose_scope(scope_name).under(parent_scope) }
|
15
|
-
it { should be_appropriate_construct(scope_name, :foo).under(parent_scope) }
|
13
|
+
it { should be_appropriate_construct(name, :foo).with_block(with_block).under(parent_scope) }
|
16
14
|
|
17
15
|
scopes.except(parent_scope_name).each do |inappropriate_scope|
|
18
|
-
it { should_not be_appropriate_construct(
|
16
|
+
it { should_not be_appropriate_construct(name, :foo).with_block(with_block).under(inappropriate_scope) }
|
19
17
|
end
|
18
|
+
end
|
19
|
+
|
20
|
+
shared_examples "a scope" do |scope_name, parent_scope_name|
|
21
|
+
parent_scope = scopes[parent_scope_name]
|
22
|
+
|
23
|
+
it_behaves_like "a scoped construct", scope_name, parent_scope_name, true
|
24
|
+
|
25
|
+
it { should enclose_scope(scope_name).under(parent_scope) }
|
20
26
|
|
21
|
-
it "
|
27
|
+
it "creates a #{scope_name} and set it as current scope object" do # it "creates project and set it as current scope object"
|
22
28
|
dsl(parent_scope, factory.create(parent_scope_name)) do |c| # dsl([:config], factory.create(:config)) do |c|
|
23
29
|
stub_find_or_create_scope_object(c, scope_name, :bar) # stub_find_or_create_scope_object(c, :project, :bar)
|
24
30
|
c.send(scope_name, :bar) do # c.project(:bar) do
|
25
|
-
c.current_scope_object.
|
26
|
-
c.current_scope_object.
|
31
|
+
expect(c.current_scope_object).not_to be_nil # expect(c.current_scope_object).not_to be_nil
|
32
|
+
expect(c.current_scope_object).to eq(factory.send(scope_name)) # expect(c.current_scope_object).to eq(factory.project)
|
27
33
|
end # end
|
28
34
|
end # end
|
29
35
|
end # end
|
30
36
|
|
31
|
-
it "
|
37
|
+
it "does not leak #{scope_name} as current scope object" do # it "does not leak project as current scope object"
|
32
38
|
dsl(parent_scope, factory.create(parent_scope_name)) do |c| # dsl([:config], factory.create(:config)) do |c|
|
33
39
|
stub_find_or_create_scope_object(c, scope_name, :bar) # stub_find_or_create_scope_object(c, :project, :bar)
|
34
40
|
c.send(scope_name, :bar) do # c.project(:bar) do
|
35
|
-
c.current_scope_object.
|
41
|
+
expect(c.current_scope_object).to eq(factory.send(scope_name)) # expect(c.current_scope_object).to eq(factory.project)
|
36
42
|
end # end
|
37
|
-
c.current_scope_object.
|
43
|
+
expect(c.current_scope_object).not_to eq(factory.send(scope_name)) # expect(c.current_scope_object).not_to eq(factory.project)
|
38
44
|
end # end
|
39
45
|
end # end
|
40
46
|
|
41
|
-
it "
|
42
|
-
dsl(parent_scope, factory.create(parent_scope_name)) do |c|
|
43
|
-
stub_find_or_create_scope_object(c, scope_name, :bar)
|
44
|
-
c.current_scope_object.should_receive("append_#{scope_name}").
|
45
|
-
with(factory.send(scope_name))
|
46
|
-
c.send(scope_name, :bar) {}
|
47
|
-
end
|
48
|
-
end
|
47
|
+
it "adds a #{scope_name} to the #{parent_scope_name}'s #{scope_name}s collection" do # it "adds a project to the config's projects collection" do
|
48
|
+
dsl(parent_scope, factory.create(parent_scope_name)) do |c| # dsl([:config], factory.create(:config)) do |c|
|
49
|
+
stub_find_or_create_scope_object(c, scope_name, :bar) # stub_find_or_create_scope_object(c, :project, :bar)
|
50
|
+
c.current_scope_object.should_receive("append_#{scope_name}"). # c.current_scope_object.should_receive(:append_project).
|
51
|
+
with(factory.send(scope_name)) # with(factory.project)
|
52
|
+
c.send(scope_name, :bar) {} # c.project(:bar) {}
|
53
|
+
end # end
|
54
|
+
end # end
|
49
55
|
end
|
50
56
|
|
51
57
|
shared_examples "a scoped method" do |attribute_name, parent_scope_name, parent_scope_method, example_value|
|
52
|
-
|
53
|
-
|
54
|
-
it { should be_appropriate_construct(attribute_name, example_value).under(parent_scope) }
|
58
|
+
it_behaves_like "a scoped construct", attribute_name, parent_scope_name, false
|
55
59
|
|
56
|
-
|
57
|
-
|
58
|
-
end
|
59
|
-
|
60
|
-
it "should call #{parent_scope_method} on current #{parent_scope_name}" do # it "should call default_location= on current server" do
|
61
|
-
dsl(parent_scope, factory.create(parent_scope_name, :foo)) do |c| # dsl([:config, :project, :environment, :server], factory.create(:server, :foo)) do |c|
|
60
|
+
it "calls #{parent_scope_method} on current #{parent_scope_name}" do # it "calls default_location= on current server" do
|
61
|
+
dsl(scopes[parent_scope_name], factory.create(parent_scope_name, :foo)) do |c| # dsl([:config, :project, :environment, :server], factory.create(:server, :foo)) do |c|
|
62
62
|
factory.send(parent_scope_name).should_receive(parent_scope_method).with(example_value) # factory.server.should_receive(:default_location=).with('/var/app/')
|
63
63
|
c.send(attribute_name, example_value) # c.location "/var/app"
|
64
64
|
end # end
|
@@ -69,143 +69,160 @@ describe "DSL" do
|
|
69
69
|
it_behaves_like "a scoped method", :default_destination, :config, :default_destination=, "foo:bar:baz"
|
70
70
|
end
|
71
71
|
|
72
|
-
describe "
|
73
|
-
|
72
|
+
describe "#shared_server_config" do
|
73
|
+
it_behaves_like "a scoped construct", :shared_server_config, :config
|
74
|
+
|
75
|
+
it "stores a block" do
|
74
76
|
dsl(scopes[:config], factory.create(:config)) do |c|
|
75
77
|
cfg = proc { any_method_call_here }
|
76
78
|
c.shared_server_config(:foo, &cfg)
|
77
|
-
c.shared_server_configs[:foo].
|
79
|
+
expect(c.shared_server_configs[:foo]).to eq(cfg)
|
78
80
|
end
|
79
81
|
end
|
82
|
+
end
|
80
83
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
84
|
+
describe "#include_shared_server_config" do
|
85
|
+
it "executes the block on dsl object in server scope for given shared config names" do
|
86
|
+
dsl(scopes[:server], factory.create(:server)) do |c|
|
87
|
+
c.stub(:shared_server_configs => { :foo => proc { any_method_call_here }, :bar => proc { second_method_call_here } })
|
88
|
+
c.should_receive(:any_method_call_here)
|
89
|
+
c.should_receive(:second_method_call_here)
|
90
|
+
c.include_shared_server_config(:foo, :bar)
|
88
91
|
end
|
92
|
+
end
|
89
93
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
94
|
+
context "when the only argument is hash where shared config names are keys" do
|
95
|
+
context "when hash values are arrays" do
|
96
|
+
it "includes config corresponding to hash key and passes exploded arguments" do
|
97
|
+
dsl(scopes[:server], factory.create(:server)) do |c|
|
98
|
+
c.stub(:shared_server_configs => { :foo => proc { |a, b| any_method_call_here(a, b) } })
|
99
|
+
c.should_receive(:any_method_call_here).with(321, 322)
|
100
|
+
c.include_shared_server_config(:foo => [321, 322])
|
101
|
+
end
|
95
102
|
end
|
96
103
|
end
|
97
104
|
|
98
|
-
|
99
|
-
|
100
|
-
|
105
|
+
context "when hash values are single values" do
|
106
|
+
it "includes config corresponding to hash key and passes the argument" do
|
107
|
+
dsl(scopes[:server], factory.create(:server)) do |c|
|
108
|
+
c.stub(:shared_server_configs => { :foo => proc { |qux| any_method_call_here(qux) } })
|
109
|
+
c.should_receive(:any_method_call_here).with(321)
|
110
|
+
c.include_shared_server_config(:foo => 321)
|
111
|
+
end
|
101
112
|
end
|
102
113
|
end
|
103
114
|
end
|
115
|
+
|
116
|
+
it "raises ConfigError if non-existent config included" do
|
117
|
+
dsl(scopes[:server], factory.create(:server)) do |c|
|
118
|
+
expect { c.include_shared_server_config(:foo) }.to raise_error(Taketo::DSL::ConfigError, "Shared server config 'foo' is not defined!")
|
119
|
+
end
|
120
|
+
end
|
104
121
|
end
|
105
122
|
|
106
123
|
describe "#project" do
|
107
124
|
it_behaves_like "a scope", :project, :config
|
125
|
+
end
|
108
126
|
|
109
|
-
|
110
|
-
|
127
|
+
describe "#environment" do
|
128
|
+
it_behaves_like "a scope", :environment, :project
|
129
|
+
end
|
111
130
|
|
112
|
-
|
113
|
-
|
131
|
+
describe "#server" do
|
132
|
+
it_behaves_like "a scope", :server, :environment
|
114
133
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
end
|
121
|
-
end
|
134
|
+
it "has name optional" do
|
135
|
+
dsl(scopes[:environment], factory.create(:environment, :foo)) do |c|
|
136
|
+
stub_find_or_create_scope_object(c, :server, :default)
|
137
|
+
c.server do
|
138
|
+
expect(c.current_scope_object.name).to eq(:default)
|
122
139
|
end
|
140
|
+
end
|
141
|
+
end
|
123
142
|
|
124
|
-
|
125
|
-
|
126
|
-
|
143
|
+
describe "#host" do
|
144
|
+
it_behaves_like "a scoped method", :host, :server, :host=, "127.0.0.2"
|
145
|
+
end
|
127
146
|
|
128
|
-
|
129
|
-
|
130
|
-
|
147
|
+
describe "#port" do
|
148
|
+
it_behaves_like "a scoped method", :port, :server, :port=, 4096
|
149
|
+
end
|
131
150
|
|
132
|
-
|
133
|
-
|
134
|
-
|
151
|
+
describe "#user" do
|
152
|
+
it_behaves_like "a scoped method", :user, :server, :username=, "deployer"
|
153
|
+
end
|
135
154
|
|
136
|
-
|
137
|
-
|
138
|
-
|
155
|
+
describe "#location" do
|
156
|
+
it_behaves_like "a scoped method", :location, :server, :default_location=, "/var/app/"
|
157
|
+
end
|
139
158
|
|
140
|
-
|
141
|
-
|
142
|
-
|
159
|
+
describe "#env" do
|
160
|
+
it_behaves_like "a scoped method", :env, :server, :env, { :FOO => "bar" }
|
161
|
+
end
|
143
162
|
|
144
|
-
|
145
|
-
|
146
|
-
|
163
|
+
describe "#global_alias" do
|
164
|
+
it_behaves_like "a scoped method", :global_alias, :server, :global_alias=, "foobared"
|
165
|
+
end
|
147
166
|
|
148
|
-
|
149
|
-
|
150
|
-
|
167
|
+
describe "#identity_file" do
|
168
|
+
it_behaves_like "a scoped method", :identity_file, :server, :identity_file=, "/home/gor/.ssh/qqq"
|
169
|
+
end
|
151
170
|
|
152
|
-
|
153
|
-
|
171
|
+
describe "#command" do
|
172
|
+
it_behaves_like "a scope", :command, :server
|
154
173
|
|
155
|
-
|
156
|
-
|
157
|
-
|
174
|
+
describe "#execute" do
|
175
|
+
it_behaves_like "a scoped method", :execute, :command, :command=, "rails c"
|
176
|
+
end
|
158
177
|
|
159
|
-
|
160
|
-
|
161
|
-
end
|
162
|
-
end
|
178
|
+
describe "#desc" do
|
179
|
+
it_behaves_like "a scoped method", :desc, :command, :description=, "Run rails console"
|
163
180
|
end
|
164
181
|
end
|
165
182
|
end
|
166
183
|
|
167
184
|
describe "#current_scope_object" do
|
168
|
-
it "
|
185
|
+
it "is config initially" do
|
169
186
|
dsl do |c|
|
170
|
-
c.current_scope_object.
|
187
|
+
expect(c.current_scope_object).to eq(factory.config)
|
171
188
|
end
|
172
189
|
end
|
173
190
|
|
174
|
-
it "
|
191
|
+
it "corresponds to current scope" do
|
175
192
|
dsl(:project, factory.create_project(:foo)) do |c|
|
176
|
-
c.current_scope_object.
|
193
|
+
expect(c.current_scope_object).to eq(factory.project)
|
177
194
|
end
|
178
195
|
|
179
196
|
dsl(:server, factory.create_server(:foo)) do |c|
|
180
|
-
c.current_scope_object.
|
197
|
+
expect(c.current_scope_object).to eq(factory.server)
|
181
198
|
end
|
182
199
|
end
|
183
200
|
end
|
184
201
|
|
185
202
|
describe "#configure" do
|
186
|
-
it "
|
203
|
+
it "reads config from file if filename passed" do
|
187
204
|
File.stub(:read => "the config")
|
188
205
|
dsl = Taketo::DSL.new(factory)
|
189
206
|
dsl.should_receive(:instance_eval) do |config, *args|
|
190
|
-
config.
|
207
|
+
expect(config).to eq("the config")
|
191
208
|
end
|
192
209
|
dsl.configure("path/to/config")
|
193
210
|
end
|
194
211
|
|
195
|
-
it "
|
212
|
+
it "is configured from block unless filename specified" do
|
196
213
|
dsl = Taketo::DSL.new(factory)
|
197
214
|
config = proc { }
|
198
215
|
dsl.should_receive(:instance_eval).with(&config)
|
199
216
|
dsl.configure &config
|
200
217
|
end
|
201
218
|
|
202
|
-
it "
|
219
|
+
it "raises an error if neither config filename nor block passed" do
|
203
220
|
expect do
|
204
221
|
Taketo::DSL.new(factory).configure
|
205
222
|
end.to raise_error ArgumentError, /(config|block)/
|
206
223
|
end
|
207
224
|
|
208
|
-
it "
|
225
|
+
it "raises meaningful error if config parse failed"
|
209
226
|
end
|
210
227
|
|
211
228
|
def stub_find_or_create_scope_object(scope_object, scope, name)
|
@@ -1,37 +1,65 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
require 'taketo/support/named_nodes_collection'
|
3
3
|
|
4
|
+
include Taketo::Support
|
5
|
+
|
4
6
|
describe "NamedNodesCollection" do
|
5
|
-
|
7
|
+
subject(:collection) { NamedNodesCollection.new }
|
6
8
|
let(:node1) { stub(:name => :foo) }
|
7
9
|
let(:node2) { stub(:name => :bar) }
|
8
10
|
|
9
|
-
it "
|
10
|
-
|
11
|
+
it "can be initialized with array" do
|
12
|
+
expect(NamedNodesCollection.new([1, 2, 3]).length).to eq(3)
|
11
13
|
end
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
collection.
|
19
|
-
collection.length.should == 2
|
20
|
-
collection.size.should == 2
|
21
|
-
collection.first.should == node1
|
22
|
-
collection.last.should == node2
|
15
|
+
[:empty?, :each, :length, :size, :first, :last].each do |delegated_method|
|
16
|
+
it { should respond_to(delegated_method) }
|
17
|
+
end
|
18
|
+
|
19
|
+
it "is Enumerable" do
|
20
|
+
expect(collection).to be_kind_of(Enumerable)
|
23
21
|
end
|
24
22
|
|
25
|
-
|
26
|
-
|
27
|
-
|
23
|
+
describe "#[]" do
|
24
|
+
subject(:collection) { NamedNodesCollection.new([node1]) }
|
25
|
+
|
26
|
+
it "retrieves node by index" do
|
27
|
+
expect(collection[0]).to eq(node1)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "retrieves node by name" do
|
31
|
+
expect(collection[:foo]).to eq(node1)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "raises error if node not found" do
|
35
|
+
expect { collection[3] }.to raise_error KeyError, /#3/i
|
36
|
+
expect { collection[:quux] }.to raise_error KeyError, /name/i
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "#push, #<<" do
|
41
|
+
it "adds node to the collection" do
|
42
|
+
collection.push(node1)
|
43
|
+
expect(collection.length).to eq(1)
|
44
|
+
collection << node2
|
45
|
+
expect(collection.length).to eq(2)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "does nothing if node with same name exists" do
|
49
|
+
collection.push(node1)
|
50
|
+
collection.push(node1)
|
51
|
+
expect(collection.length).to eq(1)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "supports chaining" do
|
55
|
+
collection << node1 << node2
|
56
|
+
expect(collection.length).to eq(2)
|
57
|
+
end
|
28
58
|
end
|
29
59
|
|
30
|
-
it "
|
60
|
+
it "compares itself to array" do
|
31
61
|
collection << node1
|
32
|
-
collection.
|
33
|
-
collection.length.should == 1
|
34
|
-
collection.first.should == node1
|
62
|
+
expect(collection).to eq([node1])
|
35
63
|
end
|
36
64
|
end
|
37
65
|
|
@@ -1,15 +1,15 @@
|
|
1
1
|
shared_examples "a construct with nodes" do |name_plural, name_singular|
|
2
|
-
specify "#append_#{name_singular}
|
3
|
-
"
|
2
|
+
specify "#append_#{name_singular} adds a #{name_singular} to " + # specify "#append_server adds a server to " +
|
3
|
+
"the #{name_plural} collection" do # "the servers collection" do
|
4
4
|
node = mock(:name => :foo).as_null_object # server = mock(:name => :foo).as_null_object
|
5
5
|
subject.send("append_#{name_singular}", node) # environment.append_server(server)
|
6
|
-
subject.send(name_plural).
|
6
|
+
expect(subject.send(name_plural)).to include(node) # expect(environment.servers).to include(server)
|
7
7
|
end # end
|
8
8
|
|
9
|
-
specify "#find_#{name_singular}
|
9
|
+
specify "#find_#{name_singular} finds #{name_singular} by name" do # specify "#find_server finds server by name" do
|
10
10
|
subject.send(name_plural).should_receive(:find_by_name). # environment.servers.should_receive(:find_by_name).
|
11
11
|
with(:foo).and_return(:bar) # with(:foo).and_return(:bar)
|
12
|
-
subject.send("find_#{name_singular}", :foo).
|
12
|
+
expect(subject.send("find_#{name_singular}", :foo)).to eq(:bar) # expect(environment.find_server(:foo)).to eq(:bar)
|
13
13
|
end # end
|
14
14
|
end
|
15
15
|
|
@@ -5,6 +5,10 @@ RSpec::Matchers.define :be_appropriate_construct do |construct, *args|
|
|
5
5
|
@enclosing_scope = enclosing_scope
|
6
6
|
end
|
7
7
|
|
8
|
+
chain(:with_block) do |with_block|
|
9
|
+
@blk = Proc.new {} if with_block
|
10
|
+
end
|
11
|
+
|
8
12
|
match do |actual|
|
9
13
|
unless @enclosing_scope
|
10
14
|
raise ArgumentError, "#under must be called to set enclosing scope"
|
@@ -13,7 +17,11 @@ RSpec::Matchers.define :be_appropriate_construct do |construct, *args|
|
|
13
17
|
@result = true
|
14
18
|
dsl(@enclosing_scope) do |c|
|
15
19
|
begin
|
16
|
-
|
20
|
+
if @blk
|
21
|
+
c.send(construct, *args, &@blk)
|
22
|
+
else
|
23
|
+
c.send(construct, *args)
|
24
|
+
end
|
17
25
|
rescue Taketo::DSL::ScopeError => e
|
18
26
|
@result = false
|
19
27
|
rescue
|
@@ -1,7 +1,10 @@
|
|
1
|
-
RSpec::Matchers.define :have_accessor do |
|
1
|
+
RSpec::Matchers.define :have_accessor do |*args|
|
2
|
+
accessor = args.shift or raise ArgumentError, "No accessor name supplied"
|
3
|
+
value = args.shift || :foo
|
4
|
+
|
2
5
|
match do |construct|
|
3
|
-
construct.send("#{accessor}=",
|
4
|
-
construct.send(accessor) ==
|
6
|
+
construct.send("#{accessor}=", value)
|
7
|
+
construct.send(accessor) == value
|
5
8
|
end
|
6
9
|
end
|
7
10
|
|