taketo 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/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
|
|