pod4 0.6.2

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.
@@ -0,0 +1,286 @@
1
+ require 'pod4/nebulous_interface'
2
+
3
+ require 'nebulous'
4
+ require 'nebulous/nebrequest_null'
5
+
6
+ require_relative 'shared_examples_for_interface'
7
+
8
+
9
+ ##
10
+ # In order to conform with 'acts_like an interface', our CRUDL routines must
11
+ # pass a single value as the record, which we are making an array. When you
12
+ # subclass NebulousInterface for your model, you don't have to follow that; you
13
+ # can have a parameter per nebulous parameter, if you want, buy overriding the
14
+ # CRUDL methods.
15
+ #
16
+ class TestNebulousInterface < NebulousInterface
17
+ set_target 'faketarget'
18
+ set_id_fld :id
19
+
20
+ set_verb :create, 'custcreate', :name, :price
21
+ set_verb :read, 'custread', :id
22
+ set_verb :update, 'custupdate', :id, :name, :price
23
+ set_verb :delete, 'custdelete', :id
24
+ set_verb :list, 'custlist', :name
25
+ end
26
+ ##
27
+
28
+
29
+ ##
30
+ # This is the class we will pass an instance of to NebulousInterface to use as
31
+ # a cut-out for creating Nebulous::NebRequest objects.
32
+ #
33
+ # If we pass an instance of this class to NebulousInterface it will call our
34
+ # send method instead of creating a NebRequest instance by itself. (It expects
35
+ # send to return a Nebrequest instance, or something that behaves like one.)
36
+ #
37
+ # This means we can cut Nebulous out of the loop and don't need a real
38
+ # responder. We can also check the behaviour of NebulousInterface by using
39
+ # RSpec 'inspect' syntax on our cutout object.
40
+ #
41
+ # We're basically emulating both a responder and a data source here (!)
42
+ #
43
+ class FakeRequester
44
+
45
+ def initialize(data={}); @data = data; end
46
+
47
+
48
+ def send(verb, paramStr, withCache)
49
+ array = (paramStr || '').split(',')
50
+
51
+ hash1 = { stompHeaders: nil,
52
+ stompBody: '',
53
+ verb: '',
54
+ params: '',
55
+ desc: '',
56
+ replyTo: nil,
57
+ replyId: nil,
58
+ inReplyTo: nil,
59
+ contentType: 'application/json' }
60
+
61
+ case verb
62
+ when 'custcreate'
63
+ id = create(*array)
64
+ hash2 = {verb: 'success', params: id.to_s}
65
+
66
+ when 'custread'
67
+ record = @data[paramStr.to_i]
68
+ hash2 = { stompBody: (record ? record.to_json : ''.to_json) }
69
+
70
+ when 'custupdate'
71
+ hash2 = update(*array) ? {verb: 'success'} : {verb: 'error' }
72
+
73
+ when 'custdelete'
74
+ hash2 =
75
+ if @data.delete(paramStr.to_i)
76
+ {verb: 'success'}
77
+ else
78
+ {verb: 'error'}
79
+ end
80
+
81
+ when 'custlist'
82
+ subset = @data.values
83
+ if paramStr && !array[0].empty?
84
+ subset.select!{|x| x[:name] == array[0] }
85
+ end
86
+ hash2 = { stompBody: subset.to_json }
87
+
88
+ end
89
+
90
+ req = Nebulous::NebRequestNull.new('faketarget', verb, paramStr)
91
+ mess = Nebulous::Message.from_cache( hash1.merge(hash2).to_json )
92
+ req.insert_fake_stomp(mess)
93
+ req
94
+ end
95
+
96
+
97
+ def create(name, price)
98
+ id = @data.keys.sort.last.to_i + 1
99
+ @data[id] = {id: id, name: name, price: price.to_f}
100
+ id
101
+ end
102
+
103
+
104
+ def update(id, name, price)
105
+ return nil unless @data[id.to_i]
106
+ @data[id.to_i] = {id: id.to_i, name: name, price: price.to_f}
107
+ end
108
+
109
+ end
110
+ ##
111
+
112
+
113
+
114
+ describe TestNebulousInterface do
115
+
116
+ def init_nebulous
117
+ stomp_hash = { hosts: [{ login: 'guest',
118
+ passcode: 'guest',
119
+ host: '10.0.0.150',
120
+ port: 61613,
121
+ ssl: false }],
122
+ reliable: false }
123
+
124
+ # We turn Redis off for this test; we're not testing Nebulous here.
125
+ Nebulous.init( :stompConnectHash => stomp_hash,
126
+ :redisConnectHash => {},
127
+ :messageTimeout => 5,
128
+ :cacheTimeout => 20 )
129
+
130
+ Nebulous.add_target( :faketarget,
131
+ :sendQueue => "/queue/fake.in",
132
+ :receiveQueue => "/queue/fake.out",
133
+ :messageTimeout => 1 )
134
+
135
+ end
136
+
137
+
138
+ it_behaves_like 'an interface' do
139
+ let(:record) { {id: 1, name: 'percy', price: 1.23} }
140
+
141
+ let(:interface) do
142
+ init_nebulous
143
+ TestNebulousInterface.new( FakeRequester.new )
144
+ end
145
+
146
+ end
147
+ ##
148
+
149
+
150
+ let(:data) do
151
+ { 1 => {id: 1, name: 'Barney', price: 1.11},
152
+ 2 => {id: 2, name: 'Fred', price: 2.22},
153
+ 3 => {id: 3, name: 'Betty', price: 3.33} }
154
+ end
155
+
156
+ let(:interface) do
157
+ init_nebulous
158
+ TestNebulousInterface.new( FakeRequester.new(data) )
159
+ end
160
+
161
+
162
+ describe '#new' do
163
+
164
+ it 'requires no parameters' do
165
+ expect{ TestNebulousInterface.new }.not_to raise_exception
166
+ end
167
+
168
+ end
169
+ ##
170
+
171
+
172
+ describe '#create' do
173
+
174
+ let(:hash) { {name: 'Bam-Bam', price: 4.44} }
175
+ let(:ot) { Octothorpe.new(name: 'Wilma', price: 5.55) }
176
+
177
+ it 'creates the record when given a hash' do
178
+ id = interface.create(hash)
179
+
180
+ expect{ interface.read(id) }.not_to raise_exception
181
+ expect( interface.read(id).to_h ).to include hash
182
+ end
183
+
184
+ it 'creates the record when given an Octothorpe' do
185
+ id = interface.create(ot)
186
+
187
+ expect{ interface.read(id) }.not_to raise_exception
188
+ expect( interface.read(id).to_h ).to include ot.to_h
189
+ end
190
+
191
+ end
192
+ ##
193
+
194
+
195
+ describe '#read' do
196
+
197
+ it 'returns the record for the id as an Octothorpe' do
198
+ expect( interface.read(1) ).to be_a_kind_of Octothorpe
199
+ expect( interface.read(2).to_h ).
200
+ to include(name: 'Fred', price: 2.22)
201
+
202
+ end
203
+
204
+ it 'returns an empty Octothorpe if no record matches the ID' do
205
+ expect{ interface.read(99) }.not_to raise_exception
206
+ expect( interface.read(99) ).to be_a_kind_of Octothorpe
207
+ expect( interface.read(99) ).to be_empty
208
+ end
209
+
210
+ end
211
+ ##
212
+
213
+
214
+
215
+ describe '#list' do
216
+
217
+ it 'has an optional selection parameter, a hash' do
218
+ expect{ interface.list }.not_to raise_exception
219
+ expect{ interface.list(name: 'Barney') }.not_to raise_exception
220
+ end
221
+
222
+ it 'returns an array of Octothorpes that match the records' do
223
+ arr = interface.list.map(&:to_h)
224
+ expect( arr ).to match_array data.values
225
+ end
226
+
227
+ it 'returns a subset of records based on the selection parameter' do
228
+ expect( interface.list(name: 'Fred').size ).to eq 1
229
+
230
+ expect( interface.list(name: 'Betty').first.to_h ).
231
+ to include(name: 'Betty', price: 3.33)
232
+
233
+ end
234
+
235
+ it 'returns an empty Array if nothing matches' do
236
+ expect( interface.list(name: 'Yogi') ).to eq([])
237
+ end
238
+
239
+ it 'returns an empty array if there is no data' do
240
+ interface.list.each{|x| interface.delete(x[interface.id_fld]) }
241
+ expect( interface.list ).to eq([])
242
+ end
243
+
244
+ end
245
+ ##
246
+
247
+
248
+ describe '#update' do
249
+
250
+ let(:id) { interface.list.first[:id] }
251
+
252
+ it 'updates the record at ID with record parameter' do
253
+ rec = {price: 99.99}
254
+ interface.update(id, rec)
255
+
256
+ expect( interface.read(id).to_h ).to include(rec)
257
+ end
258
+
259
+ end
260
+ ##
261
+
262
+
263
+ describe '#delete' do
264
+
265
+ let(:id) { interface.list.first[:id] }
266
+
267
+ def list_contains(id)
268
+ interface.list.find {|x| x[interface.id_fld] == id }
269
+ end
270
+
271
+ it 'raises CantContinue if anything hinky happens with the ID' do
272
+ expect{ interface.delete(:foo) }.to raise_exception CantContinue
273
+ expect{ interface.delete(99) }.to raise_exception CantContinue
274
+ end
275
+
276
+ it 'makes the record at ID go away' do
277
+ expect( list_contains(id) ).to be_truthy
278
+ interface.delete(id)
279
+ expect( list_contains(id) ).to be_falsy
280
+ end
281
+
282
+ end
283
+ ##
284
+
285
+
286
+ end
@@ -0,0 +1,153 @@
1
+ require 'pod4/null_interface'
2
+
3
+ require_relative 'shared_examples_for_interface'
4
+
5
+
6
+ describe NullInterface do
7
+
8
+ let(:data) do
9
+ [ {name: 'Barney', price: 1.11},
10
+ {name: 'Fred', price: 2.22},
11
+ {name: 'Betty', price: 3.33} ]
12
+ end
13
+
14
+ let (:interface) { NullInterface.new(:name, :price, data) }
15
+
16
+ ##
17
+
18
+
19
+ it_behaves_like "an interface" do
20
+ let(:record) { {name: 'barney', price:1.11} }
21
+ let(:interface) { NullInterface.new( :name, :price, [record] ) }
22
+ end
23
+
24
+
25
+ describe '#new' do
26
+
27
+ it 'requires a list of columns and an array of hashes' do
28
+ expect{ NullInterface.new }.to raise_exception ArgumentError
29
+ expect{ NullInterface.new(nil) }.to raise_exception ArgumentError
30
+ expect{ NullInterface.new('foo') }.to raise_exception ArgumentError
31
+
32
+ expect{ NullInterface.new(:one, [{one:1}]) }.not_to raise_exception
33
+ end
34
+
35
+ end
36
+ ##
37
+
38
+
39
+ describe '#create' do
40
+
41
+ let(:hash) { {name: 'Bam-Bam', price: 4.44} }
42
+ let(:ot) { Octothorpe.new(name: 'Wilma', price: 5.55) }
43
+
44
+ it 'creates the record when given a hash' do
45
+ id = interface.create(hash)
46
+
47
+ expect{ interface.read(id) }.not_to raise_exception
48
+ expect( interface.read(id).to_h ).to include hash
49
+ end
50
+
51
+ it 'creates the record when given an Octothorpe' do
52
+ id = interface.create(ot)
53
+
54
+ expect{ interface.read(id) }.not_to raise_exception
55
+ expect( interface.read(id).to_h ).to include ot.to_h
56
+ end
57
+
58
+ end
59
+ ##
60
+
61
+
62
+ describe '#read' do
63
+
64
+ it 'returns the record for the id as an Octothorpe' do
65
+ expect( interface.read('Barney') ).to be_a_kind_of Octothorpe
66
+ expect( interface.read('Fred').to_h ).
67
+ to include(name: 'Fred', price: 2.22)
68
+
69
+ end
70
+
71
+ it 'returns an empty Octothorpe if no record matches the ID' do
72
+ expect{ interface.read(:foo) }.not_to raise_exception
73
+ expect( interface.read(:foo) ).to be_a_kind_of Octothorpe
74
+ expect( interface.read(:foo) ).to be_empty
75
+ end
76
+
77
+ end
78
+ ##
79
+
80
+
81
+ describe '#list' do
82
+
83
+ it 'has an optional selection parameter, a hash' do
84
+ expect{ interface.list }.not_to raise_exception
85
+ expect{ interface.list(name: 'Barney') }.not_to raise_exception
86
+ end
87
+
88
+ it 'returns an array of Octothorpes that match the records' do
89
+ arr = interface.list.map(&:to_h)
90
+ expect( arr ).to match_array data
91
+ end
92
+
93
+ it 'returns a subset of records based on the selection parameter' do
94
+ expect( interface.list(name: 'Fred').size ).to eq 1
95
+
96
+ expect( interface.list(name: 'Betty').first.to_h ).
97
+ to include(name: 'Betty', price: 3.33)
98
+
99
+ end
100
+
101
+ it 'returns an empty Array if nothing matches' do
102
+ expect( interface.list(name: 'Yogi') ).to eq([])
103
+ end
104
+
105
+ it 'returns an empty array if there is no data' do
106
+ interface.list.each {|x| interface.delete(x[interface.id_fld]) }
107
+ expect( interface.list ).to eq([])
108
+ end
109
+
110
+ end
111
+ ##
112
+
113
+
114
+ describe '#update' do
115
+
116
+ let(:id) { interface.list.first[:name] }
117
+
118
+ it 'updates the record at ID with record parameter' do
119
+ record = {price: 99.99}
120
+ interface.update(id, record)
121
+
122
+ expect( interface.read(id).to_h ).to include(record)
123
+ end
124
+
125
+ end
126
+ ##
127
+
128
+
129
+ describe '#delete' do
130
+
131
+ def list_contains(id)
132
+ interface.list.find {|x| x[interface.id_fld] == id }
133
+ end
134
+
135
+ let(:id) { interface.list.first[:name] }
136
+
137
+ it 'raises CantContinue if anything hinky happens with the ID' do
138
+ expect{ interface.delete(:foo) }.to raise_exception CantContinue
139
+ expect{ interface.delete(99) }.to raise_exception CantContinue
140
+ end
141
+
142
+ it 'makes the record at ID go away' do
143
+ expect( list_contains(id) ).to be_truthy
144
+ interface.delete(id)
145
+ expect( list_contains(id) ).to be_falsy
146
+ end
147
+
148
+ end
149
+ ##
150
+
151
+
152
+ end
153
+
@@ -0,0 +1,89 @@
1
+ require 'pod4/param'
2
+
3
+
4
+ describe Param do
5
+
6
+ after do
7
+ Param.reset
8
+ end
9
+
10
+ ##
11
+
12
+
13
+ describe 'Param.set' do
14
+
15
+ it 'requires a parameter and a value' do
16
+ # We're not fussed about much validation since this is internal
17
+ expect{ Param.set }.to raise_exception ArgumentError
18
+ expect{ Param.set(:foo) }.to raise_exception ArgumentError
19
+
20
+ expect{ Param.set(:foo, 'bar') }.not_to raise_exception
21
+ end
22
+
23
+ it 'sets a parameter to a value' do
24
+ Param.set(:foo, 'bar')
25
+ expect( Param.params ).to include({foo: 'bar'})
26
+ end
27
+
28
+ end
29
+ ##
30
+
31
+
32
+ describe 'Param.get' do
33
+
34
+ it 'requires a parameter name' do
35
+ # We're not fussed about much validation since this is internal
36
+ expect{ Param.get }.to raise_exception ArgumentError
37
+ expect{ Param.get(:foo) }.not_to raise_exception
38
+ end
39
+
40
+ it 'returns a parameter value' do
41
+ Param.set(:foo, 'bar')
42
+ expect( Param.get(:foo) ).to eq 'bar'
43
+ end
44
+
45
+ it 'returns nil if the parameter was not set' do
46
+ expect( Param.get(:baz) ).to eq nil
47
+ end
48
+
49
+ end
50
+ ##
51
+
52
+
53
+ describe 'Param.reset' do
54
+
55
+ it 'removes all parameters' do
56
+ # probably only this test program needs this method
57
+ Param.set(:ermintrude, 'darling')
58
+ Param.reset
59
+ expect( Param.params ).to eq({})
60
+ end
61
+
62
+ end
63
+ ##
64
+
65
+
66
+ describe 'param.get_all' do
67
+
68
+ it 'returns all the parameters as an Octothorpe' do
69
+ Param.set(:ermintrude, 'darling')
70
+ Param.set(:dillon, 'zzz')
71
+ Param.set(:zebedee, 'time for bed')
72
+
73
+ expect( Param.get_all ).to be_a_kind_of Octothorpe
74
+ expect( Param.get_all.to_h ).to include( ermintrude: 'darling',
75
+ dillon: 'zzz',
76
+ zebedee: 'time for bed' )
77
+
78
+ end
79
+
80
+ it 'still returns an Octothorpe if no parameters were set' do
81
+ expect( Param.get_all ).to be_a_kind_of Octothorpe
82
+ expect( Param.get_all.to_h ).to eq({})
83
+ end
84
+
85
+ end
86
+ ##
87
+
88
+ end
89
+