ducktrap 0.0.1

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.
Files changed (165) hide show
  1. checksums.yaml +7 -0
  2. data/.circle.yml +6 -0
  3. data/.gitignore +5 -0
  4. data/.rspec +1 -0
  5. data/.travis.yml +16 -0
  6. data/Gemfile +6 -0
  7. data/Gemfile.devtools +59 -0
  8. data/Guardfile +18 -0
  9. data/LICENSE +20 -0
  10. data/README.md +47 -0
  11. data/Rakefile +2 -0
  12. data/TODO +4 -0
  13. data/config/devtools.yml +2 -0
  14. data/config/flay.yml +3 -0
  15. data/config/flog.yml +2 -0
  16. data/config/heckle.yml +3 -0
  17. data/config/mutant.yml +2 -0
  18. data/config/reek.yml +98 -0
  19. data/config/yardstick.yml +2 -0
  20. data/ducktrap.gemspec +23 -0
  21. data/lib/ducktrap.rb +73 -0
  22. data/lib/ducktrap/builder.rb +36 -0
  23. data/lib/ducktrap/error.rb +48 -0
  24. data/lib/ducktrap/evaluator.rb +127 -0
  25. data/lib/ducktrap/evaluator/invalid.rb +30 -0
  26. data/lib/ducktrap/evaluator/static.rb +25 -0
  27. data/lib/ducktrap/formatter.rb +138 -0
  28. data/lib/ducktrap/mapper.rb +59 -0
  29. data/lib/ducktrap/nary.rb +148 -0
  30. data/lib/ducktrap/node.rb +94 -0
  31. data/lib/ducktrap/node/anima.rb +40 -0
  32. data/lib/ducktrap/node/anima/dump.rb +39 -0
  33. data/lib/ducktrap/node/anima/load.rb +39 -0
  34. data/lib/ducktrap/node/block.rb +44 -0
  35. data/lib/ducktrap/node/coercion.rb +7 -0
  36. data/lib/ducktrap/node/custom.rb +121 -0
  37. data/lib/ducktrap/node/disjunction.rb +8 -0
  38. data/lib/ducktrap/node/forward.rb +55 -0
  39. data/lib/ducktrap/node/guard_nil.rb +42 -0
  40. data/lib/ducktrap/node/hash.rb +7 -0
  41. data/lib/ducktrap/node/hash/transform.rb +53 -0
  42. data/lib/ducktrap/node/invalid.rb +29 -0
  43. data/lib/ducktrap/node/inverse.rb +46 -0
  44. data/lib/ducktrap/node/key.rb +61 -0
  45. data/lib/ducktrap/node/key/add.rb +42 -0
  46. data/lib/ducktrap/node/key/delete.rb +44 -0
  47. data/lib/ducktrap/node/key/dump.rb +38 -0
  48. data/lib/ducktrap/node/key/fetch.rb +49 -0
  49. data/lib/ducktrap/node/map.rb +42 -0
  50. data/lib/ducktrap/node/noop.rb +30 -0
  51. data/lib/ducktrap/node/primitive.rb +61 -0
  52. data/lib/ducktrap/node/static.rb +33 -0
  53. data/lib/ducktrap/nullary.rb +41 -0
  54. data/lib/ducktrap/pretty_dump.rb +31 -0
  55. data/lib/ducktrap/registry.rb +60 -0
  56. data/lib/ducktrap/singleton.rb +55 -0
  57. data/lib/ducktrap/unary.rb +153 -0
  58. data/spec/rcov.opts +7 -0
  59. data/spec/shared/inverse_behavior.rb +7 -0
  60. data/spec/spec_helper.rb +20 -0
  61. data/spec/support/ice_nine_config.rb +8 -0
  62. data/spec/support/let_mock_helper.rb +13 -0
  63. data/spec/unit/ducktrap/builder/class_methods/new_spec.rb +41 -0
  64. data/spec/unit/ducktrap/builder/new_spec.rb +41 -0
  65. data/spec/unit/ducktrap/class_methods/build_spec.rb +11 -0
  66. data/spec/unit/ducktrap/error/exception/pretty_inspect_spec.rb +22 -0
  67. data/spec/unit/ducktrap/error/pretty_inspect_spec.rb +19 -0
  68. data/spec/unit/ducktrap/evaluator/assert_successful_spec.rb +38 -0
  69. data/spec/unit/ducktrap/evaluator/invalid/output_spec.rb +14 -0
  70. data/spec/unit/ducktrap/evaluator/noop/output_spec.rb +14 -0
  71. data/spec/unit/ducktrap/evaluator/output_spec.rb +52 -0
  72. data/spec/unit/ducktrap/evaluator/pretty_inspect_spec.rb +63 -0
  73. data/spec/unit/ducktrap/evaluator/successful_predicate_spec.rb +36 -0
  74. data/spec/unit/ducktrap/failed_transformation_error/message_spec.rb +10 -0
  75. data/spec/unit/ducktrap/formatter/attribute_spec.rb +24 -0
  76. data/spec/unit/ducktrap/formatter/body_spec.rb +19 -0
  77. data/spec/unit/ducktrap/formatter/class_methods/new_spec.rb +14 -0
  78. data/spec/unit/ducktrap/formatter/initialize_spec.rb +14 -0
  79. data/spec/unit/ducktrap/formatter/name_spec.rb +25 -0
  80. data/spec/unit/ducktrap/formatter/nest_spec.rb +48 -0
  81. data/spec/unit/ducktrap/formatter/puts_spec.rb +36 -0
  82. data/spec/unit/ducktrap/mapper/builder/dumper_spec.rb +20 -0
  83. data/spec/unit/ducktrap/mapper/builder/loader_spec.rb +20 -0
  84. data/spec/unit/ducktrap/mapper/builder/object_spec.rb +90 -0
  85. data/spec/unit/ducktrap/mapper/class_methods/build_spec.rb +20 -0
  86. data/spec/unit/ducktrap/nary/builder/add_spec.rb +16 -0
  87. data/spec/unit/ducktrap/nary/builder/method_missing_spec.rb +44 -0
  88. data/spec/unit/ducktrap/nary/builder/output_spec.rb +16 -0
  89. data/spec/unit/ducktrap/nary/class_methods/build_spec.rb +22 -0
  90. data/spec/unit/ducktrap/nary/class_methods/included_spec.rb +13 -0
  91. data/spec/unit/ducktrap/nary/evaluator/output_spec.rb +79 -0
  92. data/spec/unit/ducktrap/nary/instance_methods/inverse_spec.rb +24 -0
  93. data/spec/unit/ducktrap/nary/instance_methods/pretty_inspect_spec.rb +31 -0
  94. data/spec/unit/ducktrap/node/anima/dump/evaluator/output_spec.rb +18 -0
  95. data/spec/unit/ducktrap/node/anima/dump/inverse_spec.rb +10 -0
  96. data/spec/unit/ducktrap/node/anima/dump/pretty_inspect_spec.rb +15 -0
  97. data/spec/unit/ducktrap/node/anima/evaluator/output_spec.rb +18 -0
  98. data/spec/unit/ducktrap/node/anima/load/evaluator/output_spec.rb +35 -0
  99. data/spec/unit/ducktrap/node/anima/load/inverse_spec.rb +10 -0
  100. data/spec/unit/ducktrap/node/anima/load/pretty_inspect_spec.rb +15 -0
  101. data/spec/unit/ducktrap/node/anima/pretty_inspect_spec.rb +15 -0
  102. data/spec/unit/ducktrap/node/block/evaluator/output_spec.rb +79 -0
  103. data/spec/unit/ducktrap/node/block/inverse_spec.rb +24 -0
  104. data/spec/unit/ducktrap/node/call_spec.rb +21 -0
  105. data/spec/unit/ducktrap/node/class_methods/build_spec.rb +11 -0
  106. data/spec/unit/ducktrap/node/class_methods/register_spec.rb +16 -0
  107. data/spec/unit/ducktrap/node/custom/builder/forward_spec.rb +54 -0
  108. data/spec/unit/ducktrap/node/custom/builder/inverse_spec.rb +54 -0
  109. data/spec/unit/ducktrap/node/custom/builder/object_spec.rb +54 -0
  110. data/spec/unit/ducktrap/node/custom/call_spec.rb +21 -0
  111. data/spec/unit/ducktrap/node/custom/class_methods/build_spec.rb +20 -0
  112. data/spec/unit/ducktrap/node/custom/inverse_spec.rb +12 -0
  113. data/spec/unit/ducktrap/node/custom/pretty_inspect_spec.rb +15 -0
  114. data/spec/unit/ducktrap/node/forward/evaluator/output_spec.rb +13 -0
  115. data/spec/unit/ducktrap/node/forward/inverse_spec.rb +14 -0
  116. data/spec/unit/ducktrap/node/forward/pretty_inspect_spec.rb +19 -0
  117. data/spec/unit/ducktrap/node/guard_nil/call_spec.rb +21 -0
  118. data/spec/unit/ducktrap/node/guard_nil/evaluator/output_spec.rb +27 -0
  119. data/spec/unit/ducktrap/node/guard_nil/inverse_spec.rb +12 -0
  120. data/spec/unit/ducktrap/node/hash/transform/evaluator/output_spec.rb +51 -0
  121. data/spec/unit/ducktrap/node/hash/transform/inverse_spec.rb +27 -0
  122. data/spec/unit/ducktrap/node/invalid/call_spec.rb +13 -0
  123. data/spec/unit/ducktrap/node/invalid/inverse_spec.rb +11 -0
  124. data/spec/unit/ducktrap/node/inverse/call_spec.rb +11 -0
  125. data/spec/unit/ducktrap/node/inverse/inverse_spec.rb +14 -0
  126. data/spec/unit/ducktrap/node/inverse/pretty_inspect_spec.rb +19 -0
  127. data/spec/unit/ducktrap/node/key/add/call_spec.rb +15 -0
  128. data/spec/unit/ducktrap/node/key/add/evaluator/call_spec.rb +15 -0
  129. data/spec/unit/ducktrap/node/key/add/inverse_spec.rb +14 -0
  130. data/spec/unit/ducktrap/node/key/delete/call_spec.rb +13 -0
  131. data/spec/unit/ducktrap/node/key/delete/evaluator/call_spec.rb +13 -0
  132. data/spec/unit/ducktrap/node/key/delete/inverse_spec.rb +13 -0
  133. data/spec/unit/ducktrap/node/key/dump/evaluator/output_spec.rb +37 -0
  134. data/spec/unit/ducktrap/node/key/dump/inverse_spec.rb +14 -0
  135. data/spec/unit/ducktrap/node/key/evaluator/key_spec.rb +26 -0
  136. data/spec/unit/ducktrap/node/key/fetch/evaluator/output_spec.rb +48 -0
  137. data/spec/unit/ducktrap/node/key/fetch/inverse_spec.rb +14 -0
  138. data/spec/unit/ducktrap/node/key/pretty_inspect_spec.rb +20 -0
  139. data/spec/unit/ducktrap/node/map/evaluator/output_spec.rb +22 -0
  140. data/spec/unit/ducktrap/node/map/inverse_spec.rb +15 -0
  141. data/spec/unit/ducktrap/node/noop/call_spec.rb +11 -0
  142. data/spec/unit/ducktrap/node/noop/inverse_spec.rb +9 -0
  143. data/spec/unit/ducktrap/node/pretty_inspect_spec.rb +17 -0
  144. data/spec/unit/ducktrap/node/primitive/call_spec.rb +19 -0
  145. data/spec/unit/ducktrap/node/primitive/inverse_spec.rb +13 -0
  146. data/spec/unit/ducktrap/node/primitive/pretty_inspect_spec.rb +15 -0
  147. data/spec/unit/ducktrap/node/run_spec.rb +46 -0
  148. data/spec/unit/ducktrap/node/static/call_spec.rb +13 -0
  149. data/spec/unit/ducktrap/node/static/inverse_spec.rb +14 -0
  150. data/spec/unit/ducktrap/nullary/class_methods/build_spec.rb +37 -0
  151. data/spec/unit/ducktrap/nullary/class_methods/included_spec.rb +7 -0
  152. data/spec/unit/ducktrap/pretty_dump/pretty_dump_spec.rb +47 -0
  153. data/spec/unit/ducktrap/pretty_dump/pretty_inspect_spec.rb +22 -0
  154. data/spec/unit/ducktrap/registry/lookup_spec.rb +27 -0
  155. data/spec/unit/ducktrap/registry/register_spec.rb +21 -0
  156. data/spec/unit/ducktrap/singleton/class_methods/included_spec.rb +13 -0
  157. data/spec/unit/ducktrap/singleton/class_methods/instance_spec.rb +19 -0
  158. data/spec/unit/ducktrap/singleton/instance_methods/inspect_spec.rb +19 -0
  159. data/spec/unit/ducktrap/singleton/instance_methods/pretty_inspect_spec.rb +17 -0
  160. data/spec/unit/ducktrap/unary/class_methods/build_spec.rb +18 -0
  161. data/spec/unit/ducktrap/unary/class_methods/included_spec.rb +14 -0
  162. data/spec/unit/ducktrap/unary/evaluator/output2_spec.rb +48 -0
  163. data/spec/unit/ducktrap/unary/evaluator/output_spec.rb +37 -0
  164. data/spec/unit/ducktrap/unary/instance_methods/pretty_inspect_spec.rb +15 -0
  165. metadata +399 -0
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ducktrap::Formatter, '#body' do
4
+ let(:object) { described_class.new(output) }
5
+
6
+ let(:output) { StringIO.new }
7
+
8
+ subject { object.body(node) }
9
+
10
+ let(:node) { [Ducktrap::Node::Noop.instance, Ducktrap::Node::Noop.instance] }
11
+
12
+ it 'should print node with members' do
13
+ subject
14
+ output.rewind
15
+ output.read.should eql(" body:\n Ducktrap::Node::Noop\n Ducktrap::Node::Noop\n")
16
+ end
17
+
18
+ it_should_behave_like 'a command method'
19
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ducktrap::Formatter, '.new' do
4
+ subject { object.new(*arguments) }
5
+ let(:object) { described_class }
6
+
7
+ context 'with defaults' do
8
+ let(:arguments) { [] }
9
+ it 'should write to stderr' do
10
+ $stderr.should_receive(:puts).with('Class').and_return($stderr)
11
+ subject.name(described_class)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ducktrap::Formatter, '.new' do
4
+ subject { object.new(*arguments) }
5
+ let(:object) { described_class }
6
+
7
+ context 'with defaults' do
8
+ let(:arguments) { [] }
9
+ it 'should write to stderr' do
10
+ $stderr.should_receive(:puts).with('Class').and_return($stderr)
11
+ subject.name(described_class)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ducktrap::Formatter, '#name' do
4
+ subject { object.name(target) }
5
+
6
+ let(:object) { described_class.new(io) }
7
+ let(:io) { StringIO.new }
8
+
9
+ def output
10
+ io.rewind
11
+ io.read
12
+ end
13
+
14
+ before { subject }
15
+
16
+ let(:target) do
17
+ mock(:class => mock(:name => 'Target'))
18
+ end
19
+
20
+ it 'should print name of targets class' do
21
+ output.should eql("Target\n")
22
+ end
23
+
24
+ it_should_behave_like 'a command method'
25
+ end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ducktrap::Formatter, '#nest' do
4
+ subject { object.nest(label, nested) }
5
+
6
+ let(:label) { 'the-label' }
7
+ let(:nested) { mock }
8
+
9
+ let(:object) { described_class.new(io) }
10
+ let(:io) { StringIO.new }
11
+
12
+ before do
13
+ nested.should_receive(:pretty_dump).with(indented).and_return(nested)
14
+ end
15
+
16
+ def output
17
+ io.rewind
18
+ io.read
19
+ end
20
+
21
+ let(:string) { 'the-string' }
22
+
23
+ before { subject }
24
+
25
+ let(:indented) do
26
+ object.indent.indent
27
+ end
28
+
29
+ context 'unindented' do
30
+ it 'should write the string to io' do
31
+ output.should eql(" the-label:\n")
32
+ end
33
+
34
+ it_should_behave_like 'a command method'
35
+ end
36
+
37
+ context 'indented' do
38
+
39
+ let(:object) { super().indent }
40
+
41
+ it 'should write the indeted string to io' do
42
+ output.should eql(" the-label:\n")
43
+ end
44
+
45
+ it_should_behave_like 'a command method'
46
+ end
47
+
48
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ducktrap::Formatter, '#puts' do
4
+ subject { object.puts(string) }
5
+
6
+ let(:object) { described_class.new(io) }
7
+ let(:io) { StringIO.new }
8
+
9
+ def output
10
+ io.rewind
11
+ io.read
12
+ end
13
+
14
+ let(:string) { 'the-string' }
15
+
16
+ before { subject }
17
+
18
+ context 'unindented' do
19
+ it 'should write the string to io' do
20
+ output.should eql("the-string\n")
21
+ end
22
+
23
+ it_should_behave_like 'a command method'
24
+ end
25
+
26
+ context 'indented' do
27
+ let(:object) { super().indent }
28
+
29
+ it 'should write the indeted string to io' do
30
+ output.should eql(" the-string\n")
31
+ end
32
+
33
+ it_should_behave_like 'a command method'
34
+ end
35
+
36
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ducktrap::Mapper::Builder, '#dumper' do
4
+ subject do
5
+ block = self.block
6
+ described_class.new(Ducktrap::Mapper) do |mapper|
7
+ mapper.dumper(&block).should be(mapper)
8
+ end
9
+ end
10
+
11
+ let(:block) { dumper = self.dumper; proc { add(dumper) } }
12
+ let(:dumper) { mock('Dumper', :inverse => loader, :frozen? => true) }
13
+ let(:loader) { mock('Loader') }
14
+
15
+ its(:object) do
16
+ loader = Ducktrap::Node::Block.new([self.loader])
17
+ dumper = Ducktrap::Node::Block.new([self.dumper])
18
+ should eql(Ducktrap::Mapper.new(loader, dumper))
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ducktrap::Mapper::Builder, '#loader' do
4
+ subject do
5
+ block = self.block
6
+ described_class.new(Ducktrap::Mapper) do |mapper|
7
+ mapper.loader(&block).should be(mapper)
8
+ end
9
+ end
10
+
11
+ let(:block) { loader = self.loader; proc { add(loader) } }
12
+ let(:loader) { mock('Loader', :inverse => dumper, :frozen? => true) }
13
+ let(:dumper) { mock('Dumper') }
14
+
15
+ its(:object) do
16
+ loader = Ducktrap::Node::Block.new([self.loader])
17
+ dumper = Ducktrap::Node::Block.new([self.dumper])
18
+ should eql(Ducktrap::Mapper.new(loader, dumper))
19
+ end
20
+ end
@@ -0,0 +1,90 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ducktrap::Mapper::Builder, '#object' do
4
+ let(:object) do
5
+ described_class.new(Ducktrap::Mapper, &block)
6
+ end
7
+
8
+ subject { object.object }
9
+
10
+ let(:loader) { mock('Loader', :frozen? => true) }
11
+ let(:dumper) { mock('Dumper', :frozen? => true) }
12
+
13
+ context 'with loader' do
14
+ let(:block) do
15
+ node = self.loader
16
+ proc do
17
+ loader do
18
+ add(node)
19
+ end
20
+ end
21
+ end
22
+
23
+ before do
24
+ loader.stub(:inverse => dumper)
25
+ end
26
+
27
+ specify do
28
+ loader = Ducktrap::Node::Block.new([self.loader])
29
+ dumper = Ducktrap::Node::Block.new([self.dumper])
30
+ should eql(Ducktrap::Mapper.new(loader, dumper))
31
+ end
32
+ end
33
+
34
+ context 'with dumper' do
35
+ let(:block) do
36
+ node = self.dumper
37
+ proc do
38
+ dumper do
39
+ add(node)
40
+ end
41
+ end
42
+ end
43
+
44
+ before do
45
+ dumper.stub(:inverse => loader)
46
+ end
47
+
48
+ specify do
49
+ loader = Ducktrap::Node::Block.new([self.loader])
50
+ dumper = Ducktrap::Node::Block.new([self.dumper])
51
+ should eql(Ducktrap::Mapper.new(loader, dumper))
52
+ end
53
+ end
54
+
55
+ context 'with loader and dumper' do
56
+ let(:block) do
57
+ dumper = self.dumper
58
+ loader = self.loader
59
+ proc do
60
+ dumper do
61
+ add(dumper)
62
+ end
63
+
64
+ loader do
65
+ add(loader)
66
+ end
67
+ end
68
+ end
69
+
70
+ before do
71
+ dumper.stub(:inverse => loader)
72
+ loader.stub(:inverse => dumper)
73
+ end
74
+
75
+ specify do
76
+ loader = Ducktrap::Node::Block.new([self.loader])
77
+ dumper = Ducktrap::Node::Block.new([self.dumper])
78
+ should eql(Ducktrap::Mapper.new(loader, dumper))
79
+ end
80
+ end
81
+
82
+ context 'without loader or dumper' do
83
+ let(:block) do
84
+ end
85
+
86
+ it 'should raise error' do
87
+ expect { subject }.to raise_error(RuntimeError, 'Did not specify loader or dumper or both')
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ducktrap::Mapper do
4
+
5
+ let(:object) { described_class }
6
+
7
+ subject { described_class.build(&block) }
8
+
9
+ let(:block) { proc {} }
10
+ let(:builder) { mock('Builder', :object => mapper) }
11
+ let(:mapper) { mock('Mapper') }
12
+
13
+ it 'should call Ducktrap::Mapper::Builder' do
14
+ Ducktrap::Mapper::Builder.should_receive(:new).with(described_class) do |&block|
15
+ block.should be(self.block)
16
+ builder
17
+ end
18
+ subject.should be(mapper)
19
+ end
20
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ducktrap::Nary::Builder, '#add' do
4
+ let(:object) { described_class.new(klass) }
5
+ let(:klass) { Ducktrap::Node::Block }
6
+
7
+ let(:node) { Ducktrap::Node::Noop.instance }
8
+
9
+ subject { object.add(node) }
10
+
11
+ it 'should add node to body' do
12
+ expect { subject }.to change { object.body }.from([]).to([node])
13
+ end
14
+
15
+ it_should_behave_like 'a command method'
16
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ducktrap::Nary::Builder, '#method_missing' do
4
+ let(:object) { described_class.new(klass) }
5
+ let(:klass) { Ducktrap::Node::Block }
6
+
7
+ context 'known nullary DSL method' do
8
+ subject { object.noop }
9
+ it 'should add node to body' do
10
+ node = Ducktrap::Node::Noop.instance
11
+ expect { subject }.to change { object.body }.from([]).to([node])
12
+ end
13
+ end
14
+
15
+ context 'known unary DSL method' do
16
+ subject { object.guard_nil { noop } }
17
+ it 'should add node to body' do
18
+ node = Ducktrap::Node::GuardNil.new(
19
+ Ducktrap::Node::Block.new(
20
+ [Ducktrap::Node::Noop.instance]
21
+ )
22
+ )
23
+ expect { subject }.to change { object.body }.from([]).to([node])
24
+ end
25
+ end
26
+
27
+ context 'unknown DSL method' do
28
+ subject { object.unknown }
29
+
30
+ it 'should raise error' do
31
+ message =
32
+ if Devtools.rbx?
33
+ %q(undefined method `unknown' on an instance of Ducktrap::Nary::Builder.)
34
+ else
35
+ %q(undefined method `unknown' for #<Ducktrap::Nary::Builder klass=Ducktrap::Node::Block>)
36
+ end
37
+
38
+ expect { subject }.to raise_error(
39
+ NoMethodError,
40
+ message
41
+ )
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ducktrap::Nary::Builder, '#output' do
4
+ let(:object) { described_class.new(klass) }
5
+ let(:klass) { Ducktrap::Node::Block }
6
+ let(:node) { Ducktrap::Node::Noop.instance }
7
+
8
+ subject { object.object }
9
+
10
+ it 'should add node to body' do
11
+ object.add(node)
12
+ should eql(Ducktrap::Node::Block.new([node]))
13
+ end
14
+
15
+ it_should_behave_like 'an idempotent method'
16
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ducktrap::Nary::ClassMethods, '#build' do
4
+ let(:object) { Object.new.extend(described_class) }
5
+
6
+ subject { object.build(:foo, :bar, &block) }
7
+
8
+ let(:block) { proc {} }
9
+
10
+ let(:output) { mock('Output') }
11
+
12
+ it 'should delegate to nary builder' do
13
+ Ducktrap::Nary::Builder.should_receive(:new) do |first, second, third, &block|
14
+ first.should be(object)
15
+ second.should be(:foo)
16
+ third.should be(:bar)
17
+ block.should be(self.block)
18
+ mock(:object => output)
19
+ end
20
+ subject.should be(output)
21
+ end
22
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ducktrap::Nary, '.included' do
4
+ subject { described_class = self.described_class; Class.new { include described_class } }
5
+
6
+ its(:ancestors) { should include(Ducktrap::Nary::InstanceMethods) }
7
+ it { should respond_to(:build) }
8
+
9
+ specify do
10
+ subject.new(:foo).should eql(subject.new(:foo))
11
+ subject.new(:foo).should_not eql(subject.new(:bar))
12
+ end
13
+ end
@@ -0,0 +1,79 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ducktrap::Node::Block::Evaluator, '#output' do
4
+ subject { object.output }
5
+
6
+ let(:object) { described_class.new(context, input) }
7
+ let(:context) { mymock('Context', :body => body) }
8
+ let(:input) { :input }
9
+
10
+ def mymock(name, attributes={})
11
+ mock(name, attributes.merge(:frozen? => true))
12
+ end
13
+
14
+ context 'without elements in block' do
15
+ let(:body) { [] }
16
+
17
+ it { should be(input) }
18
+
19
+ it_should_behave_like 'an idempotent method'
20
+ end
21
+
22
+ context 'with elements in block' do
23
+ let(:body) { [trap_a, trap_b] }
24
+
25
+ context 'without failures' do
26
+ let(:trap_a) { Ducktrap::Node::Noop.instance }
27
+ let(:trap_b) { Ducktrap::Node::Noop.instance }
28
+
29
+ it { should be(input) }
30
+
31
+ it_should_behave_like 'an idempotent method'
32
+ end
33
+
34
+ context 'with late failure' do
35
+ let(:trap_a) { Ducktrap::Node::Static.new(:forward, :inverse) }
36
+ let(:trap_b) { Ducktrap::Node::Invalid.instance }
37
+
38
+ its(:pretty_inspect) do
39
+ should eql(strip(<<-STR))
40
+ Ducktrap::Error
41
+ input: :input
42
+ context:
43
+ Ducktrap::Evaluator::Invalid
44
+ input: :forward
45
+ error:
46
+ Ducktrap::Error
47
+ input: :forward
48
+ context:
49
+ Ducktrap::Node::Invalid
50
+ context:
51
+ Ducktrap::Node::Invalid
52
+ STR
53
+ end
54
+ end
55
+
56
+ context 'with early failure' do
57
+ let(:trap_a) { Ducktrap::Node::Invalid.instance }
58
+ let(:trap_b) { mock('Late Node') }
59
+
60
+ its(:pretty_inspect) do
61
+ should eql(strip(<<-STR))
62
+ Ducktrap::Error
63
+ input: :input
64
+ context:
65
+ Ducktrap::Evaluator::Invalid
66
+ input: :input
67
+ error:
68
+ Ducktrap::Error
69
+ input: :input
70
+ context:
71
+ Ducktrap::Node::Invalid
72
+ context:
73
+ Ducktrap::Node::Invalid
74
+ STR
75
+ end
76
+ end
77
+
78
+ end
79
+ end