xmlconv2 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.
Files changed (108) hide show
  1. data/History.txt +6 -0
  2. data/LICENCE.txt +339 -0
  3. data/Manifest.txt +107 -0
  4. data/README.txt +25 -0
  5. data/Rakefile +28 -0
  6. data/bin/admin +65 -0
  7. data/bin/xmlconvd +19 -0
  8. data/data/grammar/i2.grammar +73 -0
  9. data/src/conversion/bdd_geh.rb +281 -0
  10. data/src/conversion/bdd_i2.rb +102 -0
  11. data/src/conversion/bdd_xml.rb +242 -0
  12. data/src/conversion/geh_bdd.rb +165 -0
  13. data/src/conversion/i2_bdd.rb +271 -0
  14. data/src/conversion/xml_bdd.rb +125 -0
  15. data/src/custom/lookandfeel.rb +47 -0
  16. data/src/i2/address.rb +33 -0
  17. data/src/i2/date.rb +37 -0
  18. data/src/i2/document.rb +26 -0
  19. data/src/i2/header.rb +24 -0
  20. data/src/i2/order.rb +44 -0
  21. data/src/i2/parser.rb +25 -0
  22. data/src/i2/position.rb +37 -0
  23. data/src/i2/record.rb +11 -0
  24. data/src/model/address.rb +20 -0
  25. data/src/model/agreement.rb +10 -0
  26. data/src/model/bdd.rb +26 -0
  27. data/src/model/bsr.rb +16 -0
  28. data/src/model/delivery.rb +15 -0
  29. data/src/model/delivery_item.rb +18 -0
  30. data/src/model/freetext_container.rb +26 -0
  31. data/src/model/id_container.rb +15 -0
  32. data/src/model/invoice.rb +18 -0
  33. data/src/model/invoice_item.rb +11 -0
  34. data/src/model/item.rb +19 -0
  35. data/src/model/item_container.rb +15 -0
  36. data/src/model/name.rb +27 -0
  37. data/src/model/part_info.rb +10 -0
  38. data/src/model/part_info_container.rb +15 -0
  39. data/src/model/party.rb +23 -0
  40. data/src/model/party_container.rb +20 -0
  41. data/src/model/price.rb +10 -0
  42. data/src/model/price_container.rb +18 -0
  43. data/src/model/transaction.rb +28 -0
  44. data/src/state/global.rb +28 -0
  45. data/src/state/global_predefine.rb +11 -0
  46. data/src/state/login.rb +38 -0
  47. data/src/state/transaction.rb +13 -0
  48. data/src/state/transactions.rb +130 -0
  49. data/src/util/application.rb +143 -0
  50. data/src/util/destination.rb +130 -0
  51. data/src/util/invoicer.rb +72 -0
  52. data/src/util/known_user.rb +16 -0
  53. data/src/util/polling_manager.rb +78 -0
  54. data/src/util/session.rb +23 -0
  55. data/src/util/transaction.rb +105 -0
  56. data/src/util/validator.rb +20 -0
  57. data/src/view/foot.rb +27 -0
  58. data/src/view/head.rb +13 -0
  59. data/src/view/login.rb +36 -0
  60. data/src/view/navigation.rb +30 -0
  61. data/src/view/navigationlink.rb +21 -0
  62. data/src/view/pager.rb +73 -0
  63. data/src/view/preformatted.rb +39 -0
  64. data/src/view/template.rb +17 -0
  65. data/src/view/transaction.rb +42 -0
  66. data/src/view/transactions.rb +90 -0
  67. data/test/mock.rb +149 -0
  68. data/test/suite.rb +16 -0
  69. data/test/test_conversion/bdd_geh.rb +533 -0
  70. data/test/test_conversion/bdd_i2.rb +314 -0
  71. data/test/test_conversion/bdd_xml.rb +556 -0
  72. data/test/test_conversion/geh_bdd.rb +372 -0
  73. data/test/test_conversion/i2_bdd.rb +804 -0
  74. data/test/test_conversion/xml_bdd.rb +203 -0
  75. data/test/test_i2/address.rb +88 -0
  76. data/test/test_i2/date.rb +49 -0
  77. data/test/test_i2/document.rb +62 -0
  78. data/test/test_i2/header.rb +39 -0
  79. data/test/test_i2/order.rb +94 -0
  80. data/test/test_i2/parser.rb +309 -0
  81. data/test/test_i2/position.rb +65 -0
  82. data/test/test_integration/geh_i2.rb +312 -0
  83. data/test/test_integration/i2_geh.rb +449 -0
  84. data/test/test_integration/i2_xml.rb +162 -0
  85. data/test/test_integration/xml_i2.rb +254 -0
  86. data/test/test_model/address.rb +35 -0
  87. data/test/test_model/agreement.rb +22 -0
  88. data/test/test_model/bdd.rb +55 -0
  89. data/test/test_model/bsr.rb +38 -0
  90. data/test/test_model/delivery.rb +79 -0
  91. data/test/test_model/delivery_item.rb +52 -0
  92. data/test/test_model/freetext_container.rb +45 -0
  93. data/test/test_model/invoice.rb +65 -0
  94. data/test/test_model/invoice_item.rb +41 -0
  95. data/test/test_model/name.rb +57 -0
  96. data/test/test_model/part_info.rb +24 -0
  97. data/test/test_model/party.rb +96 -0
  98. data/test/test_model/price.rb +24 -0
  99. data/test/test_util/application.rb +168 -0
  100. data/test/test_util/destination.rb +197 -0
  101. data/test/test_util/invoicer.rb +36 -0
  102. data/test/test_util/polling_manager.rb +111 -0
  103. data/test/test_util/transaction.rb +129 -0
  104. data/user-stories/UserStories_XmlConv2.txt +381 -0
  105. data/user-stories/doku/ABB.incoming.HTTP.invoice.xml +315 -0
  106. data/user-stories/doku/ABB.received.xml +259 -0
  107. data/user-stories/doku/BO_OrderProcessing.sxw +0 -0
  108. metadata +195 -0
@@ -0,0 +1,197 @@
1
+ #!/usr/bin/env ruby
2
+ # TestDestination -- xmlconv2 -- 08.06.2004 -- hwyss@ywesee.com
3
+
4
+ $: << File.dirname(__FILE__)
5
+ $: << File.expand_path('..', File.dirname(__FILE__))
6
+ $: << File.expand_path('../../src', File.dirname(__FILE__))
7
+
8
+ require 'test/unit'
9
+ require 'util/destination'
10
+ require 'mock'
11
+
12
+ module XmlConv
13
+ module Util
14
+ class DestinationHttp < Destination
15
+ HTTP_CLASS = Mock.new('DestinationHttp::HTTP_CLASS')
16
+ end
17
+ class TestDestination < Test::Unit::TestCase
18
+ def setup
19
+ @destination = Destination.new
20
+ end
21
+ def test_attr_accessors
22
+ assert_respond_to(@destination, :path)
23
+ assert_respond_to(@destination, :path=)
24
+ end
25
+ def test_attr_readers
26
+ assert_respond_to(@destination, :uri)
27
+ assert_respond_to(@destination, :status)
28
+ assert_respond_to(@destination, :update_status)
29
+ end
30
+ def test_deliver
31
+ delivery = Mock.new('Delivery')
32
+ assert_raises(RuntimeError) {
33
+ @destination.deliver(delivery)
34
+ }
35
+ end
36
+ def test_forget_credentials
37
+ assert_respond_to(@destination, :forget_credentials!)
38
+ end
39
+ end
40
+ class TestDestinationDir < Test::Unit::TestCase
41
+ def setup
42
+ @destination = DestinationDir.new
43
+ @target_dir = File.expand_path('data/destination',
44
+ File.dirname(__FILE__))
45
+ end
46
+ def teardown
47
+ if(File.exist?(@target_dir))
48
+ FileUtils.rm_r(@target_dir)
49
+ end
50
+ end
51
+ def test_attr_readers
52
+ assert_respond_to(@destination, :filename)
53
+ end
54
+ def test_deliver
55
+ storage = Mock.new('Storage')
56
+ storage.__next(:transaction) { |block|
57
+ block.call
58
+ }
59
+ ODBA.storage = storage
60
+ cache = Mock.new('Cache')
61
+ ODBA.cache = cache
62
+ cache.__next(:store) { |obj|
63
+ assert_equal(@destination, obj)
64
+ }
65
+ delivery = Mock.new('Delivery')
66
+ delivery.__next(:filename) { 'test_file.dat' }
67
+ if(File.exist?(@target_dir))
68
+ FileUtils.rm_r(@target_dir)
69
+ end
70
+ @destination.path = @target_dir
71
+ @destination.deliver(delivery)
72
+ target_file = File.expand_path('test_file.dat', @target_dir)
73
+ assert(File.exist?(@target_dir), "Target Directory was not created")
74
+ assert(File.exist?(target_file), "Target File was not written")
75
+ assert_equal(delivery.to_s, File.read(target_file))
76
+ assert_equal('test_file.dat', @destination.filename)
77
+ assert_equal(:pending_pickup, @destination.status)
78
+ cache.__verify
79
+ delivery.__verify
80
+ ensure
81
+ ODBA.storage = nil
82
+ ODBA.cache = nil
83
+ end
84
+ def test_uri
85
+ @destination.path = '/foo/bar/baz'
86
+ assert_instance_of(URI::Generic, @destination.uri)
87
+ assert_equal("file:/foo/bar/baz", @destination.uri.to_s)
88
+ @destination.instance_variable_set('@filename', 'test_file.dat')
89
+ assert_equal("file:/foo/bar/baz/test_file.dat", @destination.uri.to_s)
90
+ end
91
+ def test_status
92
+ storage = Mock.new('Storage')
93
+ storage.__next(:transaction) { |block|
94
+ block.call
95
+ }
96
+ ODBA.storage = storage
97
+ cache = Mock.new('Cache')
98
+ ODBA.cache = cache
99
+ cache.__next(:store) { |obj|
100
+ assert_equal(@destination, obj)
101
+ }
102
+ assert_equal(:open, @destination.status)
103
+ @destination.update_status
104
+ assert_equal(:open, @destination.status)
105
+ @destination.instance_variable_set('@status', :pending_pickup)
106
+ @destination.instance_variable_set('@filename', 'no_such.file')
107
+ assert_equal(:pending_pickup, @destination.status)
108
+ @destination.update_status
109
+ assert_equal(:picked_up, @destination.status)
110
+ @destination.update_status
111
+ assert_equal(:picked_up, @destination.status)
112
+ cache.__verify
113
+ ensure
114
+ ODBA.storage = nil
115
+ ODBA.cache = nil
116
+ end
117
+ def test_status_comparable
118
+ assert_equal(0, @destination.status_comparable)
119
+ @destination.instance_variable_set('@status', :pending_pickup)
120
+ assert_equal(10, @destination.status_comparable)
121
+ @destination.instance_variable_set('@status', :picked_up)
122
+ assert_equal(20, @destination.status_comparable)
123
+ end
124
+ end
125
+ class TestDestinationHttp < Test::Unit::TestCase
126
+ class ToSMock < Mock
127
+ def to_s
128
+ true
129
+ end
130
+ end
131
+ def setup
132
+ @destination = DestinationHttp.new
133
+ end
134
+ def test_attr_accessors
135
+ assert_respond_to(@destination, :path)
136
+ assert_respond_to(@destination, :path=)
137
+ assert_respond_to(@destination, :uri)
138
+ assert_respond_to(@destination, :uri=)
139
+ assert_respond_to(@destination, :host)
140
+ assert_respond_to(@destination, :host=)
141
+ end
142
+ def test_path_writer
143
+ assert_equal('http:/', @destination.uri.to_s)
144
+ @destination.path = '/foo/bar'
145
+ assert_equal('http:/foo/bar', @destination.uri.to_s)
146
+ end
147
+ def test_host_writer
148
+ assert_equal('http:/', @destination.uri.to_s)
149
+ @destination.host = 'www.example.org'
150
+ assert_equal('http://www.example.org/', @destination.uri.to_s)
151
+ end
152
+ def test_uri_writer
153
+ uri = URI.parse('http://www.example.org/foo/bar')
154
+ assert_instance_of(URI::HTTP, @destination.uri)
155
+ assert_equal('http:/', @destination.uri.to_s)
156
+ @destination.uri = uri
157
+ assert_instance_of(URI::HTTP, @destination.uri)
158
+ assert_equal('http://www.example.org/foo/bar', @destination.uri.to_s)
159
+ @destination.uri = 'http://www.example.com/foo/bar'
160
+ assert_instance_of(URI::HTTP, @destination.uri)
161
+ assert_equal('http://www.example.com/foo/bar', @destination.uri.to_s)
162
+ end
163
+ def test_deliver
164
+ @destination.uri = 'http://testaccount:password@janico.ywesee.com:12345/test.rbx'
165
+ http_session = Mock.new('HttpSession')
166
+ delivery = ToSMock.new('Delivery')
167
+ response = Mock.new('Response')
168
+ response.__next(:message) { 'Status' }
169
+ delivery.__next(:to_s) { 'The Delivery' }
170
+ http_session.__next(:request) { |post_request, body|
171
+ assert_instance_of(Net::HTTP::Post, post_request)
172
+ header = post_request.instance_variable_get('@header')
173
+ assert_equal(['text/xml'], header['content-type'])
174
+ assert(header.include?('authorization'), "Authorization-Headers not sent")
175
+ assert_equal('The Delivery', body)
176
+ response
177
+ }
178
+ DestinationHttp::HTTP_CLASS.__next(:start) { |block, host, port|
179
+ assert_equal('janico.ywesee.com', host)
180
+ assert_equal(12345, port)
181
+ block.call(http_session)
182
+ }
183
+ @destination.deliver(delivery)
184
+ assert_equal(:http_status, @destination.status)
185
+ # When the delivery is delivered, forget username and Password
186
+ uri = @destination.uri
187
+ assert_nil(uri.user)
188
+ assert_nil(uri.password)
189
+ assert_equal('http://janico.ywesee.com:12345/test.rbx', uri.to_s)
190
+ DestinationHttp::HTTP_CLASS.__verify
191
+ http_session.__verify
192
+ delivery.__verify
193
+ response.__verify
194
+ end
195
+ end
196
+ end
197
+ end
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env ruby
2
+ # Util::TestInvoicer -- xmlconv2 -- 03.08.2006 -- hwyss@ywesee.com
3
+
4
+ $: << File.dirname(__FILE__)
5
+ $: << File.expand_path('../../src', File.dirname(__FILE__))
6
+
7
+ require 'test/unit'
8
+ require 'util/invoicer'
9
+ require 'flexmock'
10
+
11
+ module XmlConv
12
+ module Util
13
+ class TestInvoicer < Test::Unit::TestCase
14
+ def setup
15
+ @invoicer = Invoicer.new
16
+ end
17
+ def test_group_by_partner
18
+ trans1 = FlexMock.new
19
+ trans1.mock_handle(:partner) { 'Group1' }
20
+ trans1.mock_handle(:model) { 'Model1' }
21
+ trans2 = FlexMock.new
22
+ trans2.mock_handle(:partner) { 'Group2' }
23
+ trans2.mock_handle(:model) { 'Model2' }
24
+ trans3 = FlexMock.new
25
+ trans3.mock_handle(:partner) { 'Group1' }
26
+ trans3.mock_handle(:model) { 'Model3' }
27
+ transactions = [trans1, trans2, trans3]
28
+ expected = {
29
+ 'Group1' => ['Model1', 'Model3'],
30
+ 'Group2' => ['Model2']
31
+ }
32
+ assert_equal(expected, @invoicer.group_by_partner(transactions))
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,111 @@
1
+ #!/usr/bin/env ruby
2
+ # Util::TestPollingManager -- xmlconv2 -- 29.06.2004 -- hwyss@ywesee.com
3
+
4
+ $: << File.expand_path('..', File.dirname(__FILE__))
5
+ $: << File.expand_path('../../src', File.dirname(__FILE__))
6
+
7
+ require 'test/unit'
8
+ require 'util/polling_manager'
9
+ require 'mock'
10
+
11
+ module XmlConv
12
+ module Util
13
+ class PollingManager
14
+ CONFIG_PATH = File.expand_path('data/polling.yaml',
15
+ File.dirname(__FILE__))
16
+ end
17
+ class TestPollingManager < Test::Unit::TestCase
18
+ def setup
19
+ @sys = Mock.new('System')
20
+ @polling = PollingManager.new(@sys)
21
+ @dir = File.expand_path('data/i2',
22
+ File.dirname(__FILE__))
23
+ FileUtils.mkdir_p(@dir)
24
+ @file1 = File.expand_path('file1.txt', @dir)
25
+ File.open(@file1, 'w') { |fh| fh << "File 1\n" }
26
+ end
27
+ def teardown
28
+ FileUtils.rm_rf(@dir)
29
+ @sys.__verify
30
+ end
31
+ def test_load_sources
32
+ File.open(PollingManager::CONFIG_PATH, 'w') { |fh|
33
+ fh << <<-EOS
34
+ --- !ruby/object:XmlConv::Util::PollingMission
35
+ reader: I2Bdd
36
+ directory: "./test/test_util/data/i2"
37
+ writer: BddXml
38
+ destination: "http://example.com:12345"
39
+ --- !ruby/object:XmlConv::Util::PollingMission
40
+ directory: "./test/test_util/data/xml"
41
+ destination: "http://user:pass@foo.bar.baz"
42
+ writer: BddI2
43
+ reader: XmlBdd
44
+ EOS
45
+ }
46
+ block = nil
47
+ block3 = Proc.new { |source|
48
+ flunk "too many sources"
49
+ }
50
+ block2 = Proc.new { |source|
51
+ assert_instance_of(PollingMission, source)
52
+ assert_equal('XmlBdd', source.reader)
53
+ expected = File.expand_path('data/xml', File.dirname(__FILE__))
54
+ assert_equal(expected, source.directory)
55
+ assert_equal('BddI2', source.writer)
56
+ assert_equal('http://user:pass@foo.bar.baz', source.destination)
57
+ block = block3
58
+ }
59
+ block1 = Proc.new { |source|
60
+ assert_instance_of(PollingMission, source)
61
+ assert_equal('I2Bdd', source.reader)
62
+ expected = File.expand_path('data/i2', File.dirname(__FILE__))
63
+ assert_equal(expected, source.directory)
64
+ assert_equal('BddXml', source.writer)
65
+ assert_equal('http://example.com:12345', source.destination)
66
+ block = block2
67
+ }
68
+ block = block1
69
+ @polling.load_sources { |source|
70
+ block.call(source)
71
+ }
72
+ end
73
+ def test_file_paths
74
+ file2 = File.expand_path('file2.txt', @dir)
75
+ File.open(file2, 'w') { |fh| fh << "File 2\n" }
76
+ assert_equal([@file1, file2], @polling.file_paths(@dir).sort)
77
+ end
78
+ def test_poll
79
+ backup_dir = File.expand_path('../data', File.dirname(__FILE__))
80
+ source = Mock.new('Source')
81
+ source.__next(:directory) { @dir }
82
+ source.__next(:glob_pattern) { '*' }
83
+ source.__next(:reader) { 'Reader' }
84
+ source.__next(:writer) { 'Writer' }
85
+ source.__next(:destination) { 'http://foo.bar.baz:2345' }
86
+ source.__next(:debug_recipients) { }
87
+ source.__next(:error_recipients) { }
88
+ source.__next(:backup_dir) { backup_dir }
89
+ @sys.__next(:execute) { |transaction|
90
+ assert_instance_of(Util::Transaction, transaction)
91
+ assert_equal("File 1\n", transaction.input)
92
+ assert_equal('file:' << @file1, transaction.origin)
93
+ assert_equal('Reader', transaction.reader)
94
+ assert_equal('Writer', transaction.writer)
95
+ dest = transaction.destination
96
+ assert_instance_of(Util::DestinationHttp, dest)
97
+ assert_equal('http://foo.bar.baz:2345', dest.uri.to_s)
98
+ }
99
+ @polling.poll(source)
100
+ source.__verify
101
+ end
102
+ def test_destination
103
+ dest = @polling.destination('http://foo:bar@baz.com')
104
+ assert_instance_of(Util::DestinationHttp, dest)
105
+ assert_equal('baz.com', dest.host)
106
+ assert_instance_of(URI::HTTP, dest.uri)
107
+ assert_equal('http://foo:bar@baz.com', dest.uri.to_s)
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,129 @@
1
+ #!/usr/bin/env ruby
2
+ # Util::TestTransaction -- xmlconv2 -- 04.06.2004 -- hwyss@ywesee.com
3
+
4
+ $: << File.dirname(__FILE__)
5
+ $: << File.expand_path('../../src', File.dirname(__FILE__))
6
+
7
+ require 'test/unit'
8
+ require 'util/transaction'
9
+ require 'mock'
10
+
11
+ module XmlConv
12
+ module Conversion
13
+ def const_get(symbol)
14
+ if(symbol.is_a?(Mock))
15
+ symbol
16
+ else
17
+ super
18
+ end
19
+ end
20
+ module_function :const_get
21
+ end
22
+ module Util
23
+ class Transaction
24
+ SMTP_HANDLER = Mock.new('SMTP-Handler')
25
+ end
26
+ class TestTransaction < Test::Unit::TestCase
27
+ def setup
28
+ @transaction = Util::Transaction.new
29
+ end
30
+ def test_attr_accessors
31
+ assert_respond_to(@transaction, :input)
32
+ assert_respond_to(@transaction, :input=)
33
+ assert_respond_to(@transaction, :reader)
34
+ assert_respond_to(@transaction, :reader=)
35
+ assert_respond_to(@transaction, :writer)
36
+ assert_respond_to(@transaction, :writer=)
37
+ assert_respond_to(@transaction, :transaction_id)
38
+ assert_respond_to(@transaction, :transaction_id=)
39
+ assert_respond_to(@transaction, :error)
40
+ assert_respond_to(@transaction, :error=)
41
+ end
42
+ def test_attr_readers
43
+ assert_respond_to(@transaction, :output)
44
+ assert_respond_to(@transaction, :model)
45
+ assert_respond_to(@transaction, :start_time)
46
+ assert_respond_to(@transaction, :commit_time)
47
+ end
48
+ def test_execute
49
+ src = Mock.new('source')
50
+ input = Mock.new('input')
51
+ reader = Mock.new('reader')
52
+ model = Mock.new('model')
53
+ writer = Mock.new('writer')
54
+ output = Mock.new('output')
55
+ destination = Mock.new('destination')
56
+ @transaction.input = src
57
+ @transaction.reader = reader
58
+ @transaction.writer = writer
59
+ @transaction.destination = destination
60
+ reader.__next(:parse) { |read_src|
61
+ assert_equal(src, read_src)
62
+ input
63
+ }
64
+ reader.__next(:convert) { |read_input|
65
+ assert_equal(input, read_input)
66
+ model
67
+ }
68
+ writer.__next(:convert) { |write_input|
69
+ assert_equal(model, write_input)
70
+ output
71
+ }
72
+ destination.__next(:deliver) { |delivery|
73
+ assert_equal(output, delivery)
74
+ }
75
+ destination.__next(:forget_credentials!) { }
76
+ time1 = Time.now
77
+ result = @transaction.execute
78
+ time2 = Time.now
79
+ assert_equal(src, @transaction.input)
80
+ assert_equal(reader, @transaction.reader)
81
+ assert_equal(model, @transaction.model)
82
+ assert_equal(writer, @transaction.writer)
83
+ assert_equal(output.to_s, @transaction.output)
84
+ assert_equal(output.to_s, result)
85
+ assert_in_delta(time1, @transaction.start_time, 0.001)
86
+ assert_in_delta(time2, @transaction.commit_time, 0.001)
87
+ input.__verify
88
+ reader.__verify
89
+ model.__verify
90
+ writer.__verify
91
+ output.__verify
92
+ destination.__verify
93
+ end
94
+ def test_persistable
95
+ assert_kind_of(ODBA::Persistable, @transaction)
96
+ end
97
+ def test_dumpable
98
+ assert_nothing_raised { Marshal.dump(@transaction) }
99
+ end
100
+ def test_notify
101
+ @transaction.instance_variable_set('@start_time', Time.now)
102
+ @transaction.error_recipients = ['bar']
103
+ smtp = Transaction::SMTP_HANDLER
104
+ @transaction.notify
105
+ @transaction.debug_recipients = ['foo']
106
+ mail = Mock.new('MailSession')
107
+ mail.__next(:sendmail) { |encoded, from, recipients|
108
+ assert_equal(['foo'], recipients)
109
+
110
+ }
111
+ smtp.__next(:start) { |block, server|
112
+ block.call(mail)
113
+ }
114
+ @transaction.notify
115
+ @transaction.error = 'error!'
116
+ mail.__next(:sendmail) { |encoded, from, recipients|
117
+ assert_equal(['foo', 'bar'], recipients)
118
+
119
+ }
120
+ smtp.__next(:start) { |block, server|
121
+ block.call(mail)
122
+ }
123
+ @transaction.notify
124
+ smtp.__verify
125
+ mail.__verify
126
+ end
127
+ end
128
+ end
129
+ end