dsl_block 1.0.0 → 2.0.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.
@@ -1,37 +1,37 @@
1
- class DslBlock
2
-
3
- # The Executor class is designed to run a block of code in isolation
4
- # for the DslBlock class. By running it in a 'sandbox', the block
5
- # of code cannot inadvertently access protected and private methods
6
- # within the DslBlock without explicate declaration by the DslBlock.
7
- # To the user, it will appear that the block runs directly in the
8
- # DslBlock but in a partly restricted manner if they care to investigate.
9
- # In this fashion, executor is effectively a transparent proxy.
10
- class Executor < BasicObject
11
-
12
- def initialize(dsl_block)
13
- @dsl_block = dsl_block
14
- end
15
-
16
- def method_missing(method, *args, &block)
17
- # If the dsl block lists the method as a callable command
18
- if @dsl_block._commands.include?(method)
19
- # Attempt to call it
20
- begin
21
- @dsl_block.send(method, *args, &block)
22
- rescue => e
23
- # If there is any type of error, remove ourselves from the callstack to reduce confusion.
24
- e.set_backtrace(::Kernel.caller.select { |x| !x.include?(__FILE__)})
25
- ::Kernel.raise e
26
- end
27
- else
28
- # Otherwise raise a no method error as if the method does not really exist, regardless of reality.
29
- name_error = ::NameError.new("undefined local variable or method `#{method}' for #{self.inspect}")
30
- name_error.set_backtrace(::Kernel.caller.select { |x| !x.include?(__FILE__)})
31
- ::Kernel::raise name_error
32
- end
33
- end
34
-
35
- end
36
-
37
- end
1
+ class DslBlock
2
+
3
+ # The Executor class is designed to run a block of code in isolation
4
+ # for the DslBlock class. By running it in a 'sandbox', the block
5
+ # of code cannot inadvertently access protected and private methods
6
+ # within the DslBlock without explicate declaration by the DslBlock.
7
+ # To the user, it will appear that the block runs directly in the
8
+ # DslBlock but in a partly restricted manner if they care to investigate.
9
+ # In this fashion, executor is effectively a transparent proxy.
10
+ class Executor < BasicObject
11
+
12
+ def initialize(dsl_block)
13
+ @dsl_block = dsl_block
14
+ end
15
+
16
+ def method_missing(method, *args, &block)
17
+ # If the dsl block lists the method as a callable command
18
+ if @dsl_block._commands.include?(method)
19
+ # Attempt to call it
20
+ begin
21
+ @dsl_block.send(method, *args, &block)
22
+ rescue => e
23
+ # If there is any type of error, remove ourselves from the callstack to reduce confusion.
24
+ e.set_backtrace(::Kernel.caller.select { |x| !x.include?(__FILE__)})
25
+ ::Kernel.raise e
26
+ end
27
+ else
28
+ # Otherwise raise a no method error as if the method does not really exist, regardless of reality.
29
+ name_error = ::NameError.new("undefined local variable or method `#{method}' for #{self.inspect}")
30
+ name_error.set_backtrace(::Kernel.caller.select { |x| !x.include?(__FILE__)})
31
+ ::Kernel::raise name_error
32
+ end
33
+ end
34
+
35
+ end
36
+
37
+ end
@@ -1,10 +1,10 @@
1
- class DslBlock
2
- # 1.0.0
3
- VERSION = '1.0.0'
4
-
5
- module Version # :nodoc: all
6
- MAJOR, MINOR, PATCH, *OTHER = VERSION.split('.')
7
- NUMBERS = [MAJOR, MINOR, PATCH, *OTHER]
8
- end
9
-
10
- end
1
+ class DslBlock
2
+ # 2.0.0
3
+ VERSION = '2.0.0'
4
+
5
+ module Version # :nodoc: all
6
+ MAJOR, MINOR, PATCH, *OTHER = VERSION.split('.')
7
+ NUMBERS = [MAJOR, MINOR, PATCH, *OTHER]
8
+ end
9
+
10
+ end
@@ -1,61 +1,61 @@
1
- require 'spec_helper'
2
-
3
- describe DslBlock::Executor do
4
-
5
- context '.new' do
6
-
7
- it 'inherits from BasicObject to constrain the block' do
8
- expect(DslBlock::Executor.superclass).to equal(BasicObject)
9
- end
10
-
11
- end
12
-
13
- context '#method_missing' do
14
-
15
- it 'calls the method on the dsl_block if it contains the method in its #_commands' do
16
- dsl_block = Object.new
17
- dsl_block.stub(:foo).and_return('bar')
18
- dsl_block.stub(:_commands).and_return([:foo, :inspect])
19
- executor = DslBlock::Executor.new(dsl_block)
20
- expect(executor.foo).to eql('bar')
21
- end
22
-
23
- it 'raises NameError if the dsl_block does not contain the method in its #_commands' do
24
- dsl_block = Object.new
25
- dsl_block.stub(:foo).and_return('bar')
26
- dsl_block.stub(:_commands).and_return([:inspect])
27
- executor = DslBlock::Executor.new(dsl_block)
28
- expect { executor.bar }.to raise_error(NameError)
29
- end
30
-
31
- end
32
-
33
- context 'any exception' do
34
-
35
- it 'removes itself from the backtrace to make it easier to understand' do
36
- begin
37
- dsl_block = Object.new
38
- dsl_block.stub(:_commands).and_return([:inspect])
39
- executor = DslBlock::Executor.new(dsl_block)
40
- executor.bar
41
- rescue => e
42
- expect(e.backtrace.any? { |x| x.include?('dsl_block/lib/dsl_block/executor.rb')} ).to be_false
43
- end
44
-
45
- begin
46
- dsl_block = Object.new
47
- dsl_block.stub(:foo) { raise 'Kaboom' }
48
- dsl_block.stub(:_commands).and_return([:inspect, :foo])
49
- executor = DslBlock::Executor.new(dsl_block)
50
- executor.foo
51
- rescue => e
52
- expect(e.message).to eql('Kaboom')
53
- expect(e.backtrace.any? { |x| x.include?('dsl_block/lib/dsl_block/executor.rb')} ).to be_false
54
- end
55
-
56
- end
57
-
58
- end
59
-
60
-
1
+ require 'spec_helper'
2
+
3
+ describe DslBlock::Executor do
4
+
5
+ context '.new' do
6
+
7
+ it 'inherits from BasicObject to constrain the block' do
8
+ expect(DslBlock::Executor.superclass).to equal(BasicObject)
9
+ end
10
+
11
+ end
12
+
13
+ context '#method_missing' do
14
+
15
+ it 'calls the method on the dsl_block if it contains the method in its #_commands' do
16
+ dsl_block = Object.new
17
+ dsl_block.stub(:foo).and_return('bar')
18
+ dsl_block.stub(:_commands).and_return([:foo, :inspect])
19
+ executor = DslBlock::Executor.new(dsl_block)
20
+ expect(executor.foo).to eql('bar')
21
+ end
22
+
23
+ it 'raises NameError if the dsl_block does not contain the method in its #_commands' do
24
+ dsl_block = Object.new
25
+ dsl_block.stub(:foo).and_return('bar')
26
+ dsl_block.stub(:_commands).and_return([:inspect])
27
+ executor = DslBlock::Executor.new(dsl_block)
28
+ expect { executor.bar }.to raise_error(NameError)
29
+ end
30
+
31
+ end
32
+
33
+ context 'any exception' do
34
+
35
+ it 'removes itself from the backtrace to make it easier to understand' do
36
+ begin
37
+ dsl_block = Object.new
38
+ dsl_block.stub(:_commands).and_return([:inspect])
39
+ executor = DslBlock::Executor.new(dsl_block)
40
+ executor.bar
41
+ rescue => e
42
+ expect(e.backtrace.any? { |x| x.include?('dsl_block/lib/dsl_block/executor.rb')} ).to be_false
43
+ end
44
+
45
+ begin
46
+ dsl_block = Object.new
47
+ dsl_block.stub(:foo) { raise 'Kaboom' }
48
+ dsl_block.stub(:_commands).and_return([:inspect, :foo])
49
+ executor = DslBlock::Executor.new(dsl_block)
50
+ executor.foo
51
+ rescue => e
52
+ expect(e.message).to eql('Kaboom')
53
+ expect(e.backtrace.any? { |x| x.include?('dsl_block/lib/dsl_block/executor.rb')} ).to be_false
54
+ end
55
+
56
+ end
57
+
58
+ end
59
+
60
+
61
61
  end
@@ -1,241 +1,251 @@
1
- require 'spec_helper'
2
-
3
- describe DslBlock do
4
-
5
- before(:each) do
6
- dsl_reset
7
- end
8
-
9
- context '.commands' do
10
-
11
- it 'starts as an empty array' do
12
- expect(dsl_class1.commands).to eql([])
13
- end
14
-
15
- it 'accepts multiple method names' do
16
- dsl_class1.commands :a, :b, :c
17
- expect(dsl_class1.commands).to eql([:a, :b, :c])
18
- end
19
-
20
- it 'appends the method names to the existing list' do
21
- dsl_class1.commands :a, :b, :c
22
- dsl_class1.commands :d, :e, :f
23
- expect(dsl_class1.commands).to eql([:a, :b, :c, :d, :e, :f])
24
- end
25
-
26
- it 'returns the current method names when setting' do
27
- expect(dsl_class1.commands(*[:a, :b, :c])).to eql([:a, :b, :c])
28
- expect(dsl_class1.commands(*[:d, :e, :f])).to eql([:a, :b, :c, :d, :e, :f])
29
- end
30
-
31
- it 'removes duplicates' do
32
- dsl_class1.commands :a, :b, :a
33
- dsl_class1.commands :c, :b, :d
34
- expect(dsl_class1.commands).to eql([:a, :b, :c, :d])
35
- end
36
-
37
- end
38
-
39
- context '.add_command_to' do
40
-
41
- it 'defines a method in the destination' do
42
- dsl_class2.add_command_to(dsl_class1)
43
- expect(dsl_class1.instance_methods.include?(dsl_class2_command)).to be_true
44
- end
45
-
46
- it 'allows for the name of the method to be chosen' do
47
- dsl_class2.add_command_to(dsl_class1, nil, :foo)
48
- expect(dsl_class1.instance_methods.include?(:foo)).to be_true
49
- end
50
-
51
- it 'adds to the commands in the destination if it is a DslBlock' do
52
- dsl_class2.add_command_to(dsl_class1)
53
- expect(dsl_class1.commands.include?(dsl_class2_command)).to be_true
54
- end
55
-
56
- it 'allows a non DslBlock destination' do
57
- generic_class = Class.new
58
- dsl_class2.add_command_to(generic_class)
59
- expect(generic_class.instance_methods.include?(dsl_class2_command)).to be_true
60
- end
61
-
62
- context 'the method created' do
63
-
64
- it 'creates a new instance of the target' do
65
- dsl_class2.should_receive(:new).and_call_original
66
- dsl12 {}
67
- end
68
-
69
- it 'calls the block given' do
70
- expect(dsl12 { 1 }).to equal(1)
71
- end
72
-
73
- it 'executes the block in the context of the target' do
74
- expect(dsl12 { self }).to be_instance_of(dsl_class2)
75
- end
76
-
77
- end
78
-
79
- context 'propagate_commands' do
80
-
81
- it 'by default is false and does not propagate parent block commands' do
82
- dsl_class1.send(:define_method, :foo) { |x| 'foo' * x }
83
- dsl_class1.commands :foo
84
-
85
- dsl = dsl12(false) { foo(2) }
86
-
87
- expect { dsl.yield }.to raise_error(NameError)
88
- # Prove we can call it normally
89
- expect( dsl.foo(1)).to eql('foo')
90
- end
91
-
92
- it 'can be true to propagate parent block commands' do
93
- target = nil
94
-
95
- dsl_class1.send(:define_method, :foo) { |x| 'foo' * x }
96
- dsl_class1.commands :foo
97
-
98
- dsl = dsl12(false, true) { foo(2) }
99
-
100
- expect(dsl.yield).to eql('foofoo')
101
- # Prove we can call it normally
102
- expect(dsl.foo(1)).to eql('foo')
103
- end
104
-
105
- it 'will not propagate parent block commands that aren\'t marked as commands' do
106
- dsl_class1.send(:define_method, :foo) { |x| 'foo' * x }
107
- # Unlike above, :foo will not added to the list of commands at this point.
108
-
109
- dsl = dsl12(false) { foo(2) }
110
-
111
- expect { dsl.yield }.to raise_error(NameError)
112
- # Prove we can call it normally
113
- expect(dsl.foo(1)).to eql('foo')
114
- end
115
-
116
- end
117
-
118
- end
119
-
120
-
121
- context '.new' do
122
-
123
- it 'requires a block' do
124
- expect{dsl_class1.new}.to raise_error(ArgumentError, 'block must be provided')
125
- end
126
-
127
- it 'stores the block for later execution' do
128
- block = Proc.new {}
129
- dsl = dsl_class1.new(&block)
130
- expect(dsl.instance_variable_get(:@block)).to equal(block)
131
- end
132
-
133
- it 'can also take a parent object' do
134
- object = Object.new
135
- dsl = dsl_class1.new(object) {}
136
- expect(dsl.instance_variable_get(:@parent)).to equal(object)
137
- end
138
-
139
- end
140
-
141
- context '#_commands' do
142
-
143
- context 'without a parent object' do
144
-
145
- it 'shows only the dsl class commands and the Kernel.methods available to the block passed' do
146
- dsl_class1.commands :foo, :bar
147
- dsl = dsl1(false) {}
148
- expect(dsl._commands.sort).to eql((dsl_class1.commands + Kernel.methods).uniq.sort)
149
- end
150
-
151
- end
152
-
153
- context 'with a DslBlock parent' do
154
-
155
- it 'shows the dls class commands, the parent._commands, and the Kernel.methods available to the block passed' do
156
- dsl_class2.send(:define_method, :true_self) { self }
157
- dsl_class2.commands :true_self
158
- dsl_class1.commands :foo, :bar
159
- dsl2_instance = dsl12(true, true) { true_self }
160
-
161
- expect(dsl2_instance._commands.sort).to eql((dsl_class1.commands + dsl_class2.commands + Kernel.methods).sort)
162
- end
163
-
164
- end
165
-
166
- context 'with a generic Object parent' do
167
-
168
- it 'shows the dls class commands, the object.public_methods, and the Kernel.methods available to the block passed' do
169
- array = Array.new
170
- dsl1_instance = dsl_class1.new(array) {}
171
- expect(dsl1_instance._commands.sort).to eql((Kernel.methods + dsl_class1.commands + array.public_methods).sort.uniq)
172
- end
173
-
174
- end
175
-
176
- end
177
-
178
- context '#yield' do
179
-
180
- it 'yields the block given at instantiation' do
181
- dsl = dsl_class1.new { 3 }
182
- expect(dsl.yield).to equal(3)
183
- end
184
-
185
- it 'creates an executor to evaluate the block' do
186
- dsl = dsl_class1.new {}
187
- DslBlock::Executor.should_receive(:new).with(dsl).and_call_original
188
- dsl.yield
189
- end
190
-
191
- it 'isolates the block by evaluating it in the context of the executor' do
192
- block = Proc.new {}
193
- dsl = dsl_class1.new(&block)
194
- executor = DslBlock::Executor.new(dsl)
195
- executor.should_receive(:instance_eval).with(&block)
196
- DslBlock::Executor.stub(:new).and_return(executor)
197
- dsl.yield
198
- end
199
-
200
- it 'cleans up any backtraces by removing itself from the call stack' do
201
- begin
202
- dsl123 { raise 'Kaboom' }
203
- rescue => e
204
- expect(e.message).to eql('Kaboom')
205
- expect(e.backtrace.any? { |x| x.include?('dsl_block/lib/dsl_block.rb')} ).to be_false
206
- end
207
- end
208
- end
209
-
210
- context '#respond_to_missing?' do
211
-
212
- it 'behaves as normal if no parent is set' do
213
- dsl = dsl_class1.new {}
214
- expect(dsl.respond_to?(:each)).to equal(false)
215
- expect(dsl.respond_to?(:to_s)).to equal(true)
216
- end
217
-
218
- it 'also checks with the parent if it is set' do
219
- dsl = dsl_class1.new(Array.new) {}
220
- expect(dsl.respond_to?(:each)).to equal(true)
221
- expect(dsl.respond_to?(:to_s)).to equal(true)
222
- end
223
-
224
- end
225
-
226
- context '#method_missing?' do
227
-
228
- it 'behaves as normal if no parent is set' do
229
- dsl = dsl_class1.new {}
230
- expect { dsl.each }.to raise_error(NoMethodError)
231
- end
232
-
233
- it 'relays the call to the parent if it is set' do
234
- dsl = dsl_class1.new(Array.new) {}
235
- expect { dsl.each }.not_to raise_error
236
- end
237
-
238
- end
239
-
240
- end
241
-
1
+ require 'spec_helper'
2
+
3
+ describe DslBlock do
4
+
5
+ before(:each) do
6
+ dsl_reset
7
+ end
8
+
9
+ context '.commands' do
10
+
11
+ it 'starts as an empty array' do
12
+ expect(dsl_class1.commands).to eql([])
13
+ end
14
+
15
+ it 'accepts multiple method names' do
16
+ dsl_class1.commands :a, :b, :c
17
+ expect(dsl_class1.commands).to eql([:a, :b, :c])
18
+ end
19
+
20
+ it 'appends the method names to the existing list' do
21
+ dsl_class1.commands :a, :b, :c
22
+ dsl_class1.commands :d, :e, :f
23
+ expect(dsl_class1.commands).to eql([:a, :b, :c, :d, :e, :f])
24
+ end
25
+
26
+ it 'returns the current method names when setting' do
27
+ expect(dsl_class1.commands(*[:a, :b, :c])).to eql([:a, :b, :c])
28
+ expect(dsl_class1.commands(*[:d, :e, :f])).to eql([:a, :b, :c, :d, :e, :f])
29
+ end
30
+
31
+ it 'removes duplicates' do
32
+ dsl_class1.commands :a, :b, :a
33
+ dsl_class1.commands :c, :b, :d
34
+ expect(dsl_class1.commands).to eql([:a, :b, :c, :d])
35
+ end
36
+
37
+ end
38
+
39
+ context '.add_command_to' do
40
+
41
+ it 'defines a method in the destination' do
42
+ dsl_class2.add_command_to(dsl_class1)
43
+ expect(dsl_class1.instance_methods.include?(dsl_class2_command)).to be_true
44
+ end
45
+
46
+ it 'allows for the name of the method to be chosen' do
47
+ dsl_class2.add_command_to(dsl_class1, :command_name => :foo)
48
+ expect(dsl_class1.instance_methods.include?(:foo)).to be_true
49
+ end
50
+
51
+ it 'adds to the commands in the destination if it is a DslBlock' do
52
+ dsl_class2.add_command_to(dsl_class1)
53
+ expect(dsl_class1.commands.include?(dsl_class2_command)).to be_true
54
+ end
55
+
56
+ it 'allows a non DslBlock destination' do
57
+ generic_class = Class.new
58
+ dsl_class2.add_command_to(generic_class)
59
+ expect(generic_class.instance_methods.include?(dsl_class2_command)).to be_true
60
+ end
61
+
62
+ context 'the method created' do
63
+
64
+ it 'creates a new instance of the target' do
65
+ dsl_class2.should_receive(:new).and_call_original
66
+ dsl12 {}
67
+ end
68
+
69
+ it 'calls the block given' do
70
+ expect(dsl12 { 1 }).to equal(1)
71
+ end
72
+
73
+ it 'executes the block in the context of the target' do
74
+ expect(dsl12 { self }).to be_instance_of(dsl_class2)
75
+ end
76
+
77
+ end
78
+
79
+ context 'propagate_commands' do
80
+
81
+ it 'by default is false and does not propagate parent block commands' do
82
+ dsl_class1.send(:define_method, :foo) { |x| 'foo' * x }
83
+ dsl_class1.commands :foo
84
+
85
+ dsl = dsl12(false) { foo(2) }
86
+
87
+ expect { dsl.yield }.to raise_error(NameError)
88
+ # Prove we can call it normally
89
+ expect( dsl.foo(1)).to eql('foo')
90
+ end
91
+
92
+ it 'can be true to propagate parent block commands' do
93
+ dsl_class1.send(:define_method, :foo) { |x| 'foo' * x }
94
+ dsl_class1.commands :foo
95
+
96
+ dsl = dsl12(false, true) { foo(2) }
97
+
98
+ expect(dsl.yield).to eql('foofoo')
99
+ # Prove we can call it normally
100
+ expect(dsl.foo(1)).to eql('foo')
101
+ end
102
+
103
+ it 'will not propagate parent block commands that aren\'t marked as commands' do
104
+ dsl_class1.send(:define_method, :foo) { |x| 'foo' * x }
105
+ # Unlike above, :foo will not added to the list of commands at this point.
106
+
107
+ dsl = dsl12(false) { foo(2) }
108
+
109
+ expect { dsl.yield }.to raise_error(NameError)
110
+ # Prove we can call it normally
111
+ expect(dsl.foo(1)).to eql('foo')
112
+ end
113
+
114
+ end
115
+
116
+ end
117
+
118
+
119
+ context '.new' do
120
+
121
+ it 'requires a block' do
122
+ expect{dsl_class1.new}.to raise_error(ArgumentError, 'block must be provided')
123
+ end
124
+
125
+ it 'accepts the block in the options hash' do
126
+ block = Proc.new {}
127
+ expect{dsl_class1.new(:block => block) }.to_not raise_error
128
+ end
129
+
130
+ it 'stores the block for later execution' do
131
+ block = Proc.new {}
132
+ dsl = dsl_class1.new(&block)
133
+ expect(dsl.instance_variable_get(:@block)).to equal(block)
134
+ end
135
+
136
+ it 'uses regular block over options block' do
137
+ block1 = Proc.new {}
138
+ block2 = Proc.new {}
139
+ dsl = dsl_class1.new(:block => block1, &block2)
140
+ expect(dsl.instance_variable_get(:@block)).to equal(block2)
141
+ end
142
+
143
+ it 'can also take a parent object' do
144
+ object = Object.new
145
+ dsl = dsl_class1.new(:parent => object) {}
146
+ expect(dsl.instance_variable_get(:@parent)).to equal(object)
147
+ end
148
+
149
+ end
150
+
151
+ context '#_commands' do
152
+
153
+ context 'without a parent object' do
154
+
155
+ it 'shows only the dsl class commands and the Kernel.methods available to the block passed' do
156
+ dsl_class1.commands :foo, :bar
157
+ dsl = dsl1(false) {}
158
+ expect(dsl._commands.sort).to eql((dsl_class1.commands + Kernel.methods).uniq.sort)
159
+ end
160
+
161
+ end
162
+
163
+ context 'with a DslBlock parent' do
164
+
165
+ it 'shows the dls class commands, the parent._commands, and the Kernel.methods available to the block passed' do
166
+ dsl_class2.send(:define_method, :true_self) { self }
167
+ dsl_class2.commands :true_self
168
+ dsl_class1.commands :foo, :bar
169
+ dsl2_instance = dsl12(true, true) { true_self }
170
+
171
+ expect(dsl2_instance._commands.sort).to eql((dsl_class1.commands + dsl_class2.commands + Kernel.methods).sort)
172
+ end
173
+
174
+ end
175
+
176
+ context 'with a generic Object parent' do
177
+
178
+ it 'shows the dls class commands, the object.public_methods, and the Kernel.methods available to the block passed' do
179
+ array = Array.new
180
+ dsl1_instance = dsl_class1.new(:parent => array) {}
181
+ expect(dsl1_instance._commands.sort).to eql((Kernel.methods + dsl_class1.commands + array.public_methods).sort.uniq)
182
+ end
183
+
184
+ end
185
+
186
+ end
187
+
188
+ context '#yield' do
189
+
190
+ it 'yields the block given at instantiation' do
191
+ dsl = dsl_class1.new { 3 }
192
+ expect(dsl.yield).to equal(3)
193
+ end
194
+
195
+ it 'creates an executor to evaluate the block' do
196
+ dsl = dsl_class1.new {}
197
+ DslBlock::Executor.should_receive(:new).with(dsl).and_call_original
198
+ dsl.yield
199
+ end
200
+
201
+ it 'isolates the block by evaluating it in the context of the executor' do
202
+ block = Proc.new {}
203
+ dsl = dsl_class1.new(&block)
204
+ executor = DslBlock::Executor.new(dsl)
205
+ executor.should_receive(:instance_eval).with(&block)
206
+ DslBlock::Executor.stub(:new).and_return(executor)
207
+ dsl.yield
208
+ end
209
+
210
+ it 'cleans up any backtraces by removing itself from the call stack' do
211
+ begin
212
+ dsl123 { raise 'Kaboom' }
213
+ rescue => e
214
+ expect(e.message).to eql('Kaboom')
215
+ expect(e.backtrace.any? { |x| x.include?('dsl_block/lib/dsl_block.rb')} ).to be_false
216
+ end
217
+ end
218
+ end
219
+
220
+ context '#respond_to_missing?' do
221
+
222
+ it 'behaves as normal if no parent is set' do
223
+ dsl = dsl_class1.new {}
224
+ expect(dsl.respond_to?(:each)).to equal(false)
225
+ expect(dsl.respond_to?(:to_s)).to equal(true)
226
+ end
227
+
228
+ it 'also checks with the parent if it is set' do
229
+ dsl = dsl_class1.new(:parent => Array.new) {}
230
+ expect(dsl.respond_to?(:each)).to equal(true)
231
+ expect(dsl.respond_to?(:to_s)).to equal(true)
232
+ end
233
+
234
+ end
235
+
236
+ context '#method_missing?' do
237
+
238
+ it 'behaves as normal if no parent is set' do
239
+ dsl = dsl_class1.new {}
240
+ expect { dsl.each }.to raise_error(NoMethodError)
241
+ end
242
+
243
+ it 'relays the call to the parent if it is set' do
244
+ dsl = dsl_class1.new(:parent => Array.new) {}
245
+ expect { dsl.each }.not_to raise_error
246
+ end
247
+
248
+ end
249
+
250
+ end
251
+