dsl_block 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+