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,760 @@
1
+ require 'octothorpe'
2
+
3
+ require 'pod4/model'
4
+ require 'pod4/null_interface'
5
+
6
+
7
+ ##
8
+ # We define a model class to test, since in normal operation we would never use
9
+ # Model directly, and since it needs an inner Interface.
10
+ #
11
+ # We can't use a mock for the interface -- class definitions fall outside the
12
+ # RSpec DSL as far as I can tell, so I can neither create a mock here or inject
13
+ # it. Which means we can't mock the interface in the rest of the test either;
14
+ # any mock we created would not get called.
15
+ #
16
+ # But: we want to test that Model calls Interface correctly.
17
+ #
18
+ # We do have what appears to be a perfectly sane way of testing. We can define
19
+ # an inner class based on the genuinely existing, non-mock NullInterface class;
20
+ # and then define expectations on it. When we do this, Rspec fails to pass the
21
+ # call on to the object, unless we specifically say `.and_call_original`
22
+ # instead of `.and_return`.
23
+ #
24
+ # This is actually quite nice, but more than a little confusing when you see it
25
+ # for the first time. Its use isn't spelled out in the RSpec docs AFAICS.
26
+ #
27
+ class CustomerModel < Pod4::Model
28
+ attr_columns :id, :name, :groups
29
+ attr_columns :price # specifically testing multiple calls to attr_columns
30
+ set_interface NullInterface.new(:id, :name, :price, :groups, [])
31
+
32
+ def map_to_model(ot)
33
+ super
34
+ @groups = @groups ? @groups.split(',') : []
35
+ self
36
+ end
37
+
38
+ def map_to_interface
39
+ x = super
40
+ g = (x.>>.groups || []).join(',')
41
+ x.merge(groups: g)
42
+ end
43
+
44
+ def fake_an_alert(*args)
45
+ add_alert(*args) #private method
46
+ end
47
+
48
+ def validate
49
+ add_alert(:error, "falling over now") if name == "fall over"
50
+ end
51
+
52
+ def reset_alerts; @alerts = []; end
53
+ end
54
+
55
+
56
+
57
+ describe 'CustomerModel' do
58
+
59
+ let(:records) do
60
+ [ {id: 10, name: 'Gomez', price: 1.23, groups: 'trains' },
61
+ {id: 20, name: 'Morticia', price: 2.34, groups: 'spanish' },
62
+ {id: 30, name: 'Wednesday', price: 3.45, groups: 'school' },
63
+ {id: 40, name: 'Pugsley', price: 4.56, groups: 'trains,school'} ]
64
+ end
65
+
66
+ let(:recordsx) do
67
+ records.map {|h| h.reject{|k,_| k == :groups} }.flatten
68
+ end
69
+
70
+ let(:records_as_ot) { records.map{|r| Octothorpe.new(r) } }
71
+ let(:recordsx_as_ot) { recordsx.map{|r| Octothorpe.new(r) } }
72
+
73
+ def without_groups(ot)
74
+ ot.to_h.reject {|k,_| k == :groups}
75
+ end
76
+
77
+ # model is just a plain newly created object that you can call read on.
78
+ # model2 and model3 are in an identical state - they have been filled with a
79
+ # read(). We have two so that we can RSpec 'allow' on one and not the other.
80
+
81
+ let(:model) { CustomerModel.new(20) }
82
+
83
+ let(:model2) do
84
+ m = CustomerModel.new(30)
85
+
86
+ allow( m.interface ).to receive(:read).
87
+ and_return( Octothorpe.new(records[2]) )
88
+
89
+ m.read.or_die
90
+ end
91
+
92
+ let(:model3) do
93
+ m = CustomerModel.new(40)
94
+
95
+ allow( m.interface ).to receive(:read).
96
+ and_return( Octothorpe.new(records[3]) )
97
+
98
+ m.read.or_die
99
+ end
100
+
101
+
102
+ ##
103
+
104
+
105
+ describe 'Model.attr_columns' do
106
+
107
+ it 'requires a list of columns' do
108
+ expect( CustomerModel ).to respond_to(:attr_columns).with(1).argument
109
+ end
110
+
111
+ it 'exposes the columns just like attr_accessor' do
112
+ expect( CustomerModel.new ).to respond_to(:id)
113
+ expect( CustomerModel.new ).to respond_to(:name)
114
+ expect( CustomerModel.new ).to respond_to(:price)
115
+ expect( CustomerModel.new ).to respond_to(:groups)
116
+ expect( CustomerModel.new ).to respond_to(:id=)
117
+ expect( CustomerModel.new ).to respond_to(:name=)
118
+ expect( CustomerModel.new ).to respond_to(:price=)
119
+ expect( CustomerModel.new ).to respond_to(:groups=)
120
+ end
121
+
122
+ # it adds the columns to Model.columns -- covered by the columns test
123
+ end
124
+ ##
125
+
126
+
127
+ describe 'Model.columns' do
128
+ it 'lists the columns' do
129
+ expect( CustomerModel.columns ).to match_array( [:id,:name,:price,:groups] )
130
+ end
131
+ end
132
+ ##
133
+
134
+
135
+ describe 'Model.set_interface' do
136
+ it 'requires an Interface object' do
137
+ expect( CustomerModel ).to respond_to(:set_interface).with(1).argument
138
+ end
139
+
140
+ # it 'sets interface' - covered by the interface test
141
+ end
142
+ ##
143
+
144
+
145
+ describe 'Model.interface' do
146
+ it 'is the interface object' do
147
+ expect( CustomerModel.interface ).to be_a_kind_of NullInterface
148
+ expect( CustomerModel.interface.id_fld ).to eq :id
149
+ end
150
+ end
151
+ ##
152
+
153
+
154
+ describe 'Model.list' do
155
+
156
+ let(:list1) { CustomerModel.list }
157
+
158
+ def arr_without_groups(arr)
159
+ arr
160
+ .map {|m| without_groups(m.to_ot) }
161
+ .flatten
162
+
163
+ end
164
+
165
+ it 'allows an optional selection parameter' do
166
+ expect{ CustomerModel.list }.not_to raise_exception
167
+ expect{ CustomerModel.list(name: 'Betty') }.not_to raise_exception
168
+ end
169
+
170
+ it 'returns an array of CustomerModel records' do
171
+ expect( CustomerModel.interface ).
172
+ to receive(:list).with(nil).
173
+ and_return( records_as_ot )
174
+
175
+ expect( list1 ).to be_a_kind_of Array
176
+ expect( list1 ).to all(be_a_kind_of CustomerModel)
177
+ end
178
+
179
+ it 'returns the data from the interface' do
180
+ expect( CustomerModel.interface ).
181
+ to receive(:list).with(nil).
182
+ and_return(records_as_ot)
183
+
184
+ expect( list1.size ).to eq records.size
185
+ expect( arr_without_groups(list1) ).to include( *recordsx )
186
+ end
187
+
188
+ it 'honours passed selection criteria' do
189
+ hash = {price: 2.22}
190
+
191
+ expect( CustomerModel.interface ).
192
+ to receive(:list).with(hash).
193
+ and_return( [Octothorpe.new(records[1])] )
194
+
195
+ list2 = CustomerModel.list(hash)
196
+ expect( list2.size ).to eq 1
197
+ expect( arr_without_groups(list2).first ).to eq( recordsx[1] )
198
+ end
199
+
200
+ it 'returns an empty array if nothing matches' do
201
+ hash = {price: 1.23}
202
+
203
+ expect( CustomerModel.interface ).
204
+ to receive(:list).with(hash).
205
+ and_return([])
206
+
207
+ expect( CustomerModel.list(hash) ).to eq []
208
+ end
209
+
210
+ it 'returns an empty array if there are no records' do
211
+ expect( CustomerModel.list ).to eq []
212
+ end
213
+
214
+ it 'calls map_to_model to set the record data' do
215
+ allow( CustomerModel.interface ).
216
+ to receive(:list).
217
+ and_return(records_as_ot)
218
+
219
+ expect( CustomerModel.list.last.groups ).to eq(['trains', 'school'])
220
+ end
221
+
222
+ end
223
+ ##
224
+
225
+
226
+ describe '#new' do
227
+
228
+ it 'takes an optional ID' do
229
+ expect{ CustomerModel.new }.not_to raise_exception
230
+ expect{ CustomerModel.new(1) }.not_to raise_exception
231
+ end
232
+
233
+ it 'sets the ID attribute' do
234
+ expect( CustomerModel.new(23).model_id ).to eq 23
235
+ end
236
+
237
+ it 'sets the status to empty' do
238
+ expect( CustomerModel.new.model_status ).to eq :empty
239
+ end
240
+
241
+ it 'initializes the alerts attribute' do
242
+ expect( CustomerModel.new.alerts ).to eq([])
243
+ end
244
+
245
+ end
246
+ ##
247
+
248
+
249
+ describe '#interface' do
250
+ it 'returns the interface set in the class definition, again' do
251
+ expect( CustomerModel.new.interface ).to be_a_kind_of NullInterface
252
+ expect( CustomerModel.new.interface.id_fld ).to eq :id
253
+ end
254
+ end
255
+ ##
256
+
257
+
258
+ describe '#columns' do
259
+ it 'returns the attr_columns list from the class definition' do
260
+
261
+ expect( CustomerModel.new.columns ).
262
+ to match_array( [:id,:name,:price,:groups] )
263
+
264
+ end
265
+ end
266
+ ##
267
+
268
+
269
+ describe '#alerts' do
270
+ it 'returns the list of alerts against the model' do
271
+ cm = CustomerModel.new
272
+ cm.fake_an_alert(:warning, :foo, 'one')
273
+ cm.fake_an_alert(:error, :bar, 'two')
274
+
275
+ expect( cm.alerts.size ).to eq 2
276
+ expect( cm.alerts.map{|a| a.message} ).to match_array(%w|one two|)
277
+ end
278
+ end
279
+ ##
280
+
281
+
282
+ describe '#add_alert' do
283
+ # add_alert is a protected method, which is only supposed to be called
284
+ # within the validate method of a subclass of Method. So we test it by
285
+ # calling our alert faking method
286
+
287
+ it 'requires type, message or type, field, message' do
288
+ expect{ model.fake_an_alert }.to raise_exception ArgumentError
289
+ expect{ model.fake_an_alert(nil) }.to raise_exception ArgumentError
290
+ expect{ model.fake_an_alert('foo') }.to raise_exception ArgumentError
291
+
292
+ expect{ model.fake_an_alert(:error, 'foo') }.not_to raise_exception
293
+ expect{ model.fake_an_alert(:warning, :name, 'bar') }.
294
+ not_to raise_exception
295
+
296
+ end
297
+
298
+ it 'only allows valid types' do
299
+ [:brian, :werning, nil, :alert, :danger].each do |l|
300
+ expect{ model.fake_an_alert(l, 'foo') }.to raise_exception ArgumentError
301
+ end
302
+
303
+ [:warning, :error, :success, :info].each do |l|
304
+ expect{ model.fake_an_alert(l, 'foo') }.not_to raise_exception
305
+ end
306
+
307
+ end
308
+
309
+ it 'creates an Alert and adds it to @alerts' do
310
+ lurch = 'Dnhhhhhh'
311
+ model.fake_an_alert(:error, :price, lurch)
312
+
313
+ expect( model.alerts.size ).to eq 1
314
+ expect( model.alerts.first ).to be_a_kind_of Pod4::Alert
315
+ expect( model.alerts.first.message ).to eq lurch
316
+ end
317
+
318
+ it 'sets @model_status if the type is worse than @model_status' do
319
+ model.fake_an_alert(:warning, :price, 'xoo')
320
+ expect( model.model_status ).to eq :warning
321
+
322
+ model.fake_an_alert(:success, :price, 'flom')
323
+ expect( model.model_status ).to eq :warning
324
+
325
+ model.fake_an_alert(:info, :price, 'flom')
326
+ expect( model.model_status ).to eq :warning
327
+
328
+ model.fake_an_alert(:error, :price, 'qar')
329
+ expect( model.model_status ).to eq :error
330
+
331
+ model.fake_an_alert(:warning, :price, 'drazq')
332
+ expect( model.model_status ).to eq :error
333
+ end
334
+
335
+ it 'ignores a new alert if identical to an existing one' do
336
+ lurch = 'Dnhhhhhh'
337
+ 2.times { model.fake_an_alert(:error, :price, lurch) }
338
+
339
+ expect( model.alerts.size ).to eq 1
340
+ end
341
+
342
+ end
343
+ ##
344
+
345
+
346
+ describe '#validate' do
347
+ it 'takes no parameters' do
348
+ expect{ CustomerModel.new.validate(12) }.to raise_exception ArgumentError
349
+ expect{ CustomerModel.new.validate }.not_to raise_exception
350
+ end
351
+ end
352
+ ##
353
+
354
+
355
+ describe '#set' do
356
+
357
+ let (:ot) { records_as_ot[3] }
358
+
359
+ it 'takes an Octothorpe or a Hash' do
360
+ expect{ model.set }.to raise_exception ArgumentError
361
+ expect{ model.set(nil) }.to raise_exception ArgumentError
362
+ expect{ model.set(:foo) }.to raise_exception ArgumentError
363
+
364
+ expect{ model.set(ot) }.not_to raise_exception
365
+ end
366
+
367
+ it 'returns self' do
368
+ expect( model.set(ot) ).to eq model
369
+ end
370
+
371
+ it 'sets the attribute columns from the hash' do
372
+ model.set(ot)
373
+
374
+ expect( model.id ).to eq ot.>>.id
375
+ expect( model.name ).to eq ot.>>.name
376
+ expect( model.price ).to eq ot.>>.price
377
+ end
378
+
379
+ it 'only sets the attributes on the model that it is given' do
380
+ otx = Octothorpe.new(name: 'Piggy', price: 98.76, weapon: 'rake')
381
+
382
+ expect{ model3.set(otx) }.not_to raise_exception
383
+ expect( model3.id ).to eq 40
384
+ expect( model3.name ).to eq 'Piggy'
385
+ expect( model3.price ).to eq 98.76
386
+ expect( model3.groups ).to eq( ot.>>.groups.split(',') )
387
+ end
388
+
389
+ end
390
+ ##
391
+
392
+
393
+ describe '#to_ot' do
394
+ it 'returns an Octothorpe made of the attribute columns' do
395
+ expect( model.to_ot ).to be_a_kind_of Octothorpe
396
+
397
+ expect( model.to_ot.to_h ).
398
+ to eq( {id: nil, name: nil, price:nil, groups:nil} )
399
+
400
+ model.map_to_model(records[1])
401
+ expect( model.to_ot ).to be_a_kind_of Octothorpe
402
+ expect( without_groups(model.to_ot) ).to eq recordsx[1]
403
+
404
+ model.map_to_model(records_as_ot[2])
405
+ expect( model.to_ot ).to be_a_kind_of Octothorpe
406
+ expect( without_groups(model.to_ot) ).to eq recordsx[2]
407
+ end
408
+ end
409
+ ##
410
+
411
+
412
+ describe '#map_to_model' do
413
+
414
+ it 'sets the columns, with groups as an array' do
415
+ cm = CustomerModel.new
416
+ cm.map_to_model(records.last)
417
+
418
+ expect( cm.groups ).to eq( ['trains','school'] )
419
+ end
420
+
421
+ end
422
+ ##
423
+
424
+
425
+ describe '#map_to_interface' do
426
+
427
+ it 'returns the columns, with groups as a list' do
428
+ cm = CustomerModel.new
429
+ cm.map_to_model(records.last)
430
+
431
+ expect( cm.map_to_interface.>>.groups ).to eq( 'trains,school' )
432
+ end
433
+
434
+ end
435
+ ##
436
+
437
+
438
+ describe '#raise_exceptions' do
439
+
440
+ it 'is also known as .or_die' do
441
+ cm = CustomerModel.new
442
+ expect( cm.method(:raise_exceptions) ).to eq( cm.method(:or_die) )
443
+ end
444
+
445
+ it 'raises ValidationError if model status is :error' do
446
+ model.fake_an_alert(:error, :price, 'qar')
447
+ expect{ model.raise_exceptions }.to raise_exception Pod4::ValidationError
448
+ end
449
+
450
+ it 'does nothing if model status is not :error' do
451
+ expect{ model.raise_exceptions }.not_to raise_exception
452
+
453
+ model.fake_an_alert(:info, :price, 'qar')
454
+ expect{ model.raise_exceptions }.not_to raise_exception
455
+
456
+ model.fake_an_alert(:success, :price, 'qar')
457
+ expect{ model.raise_exceptions }.not_to raise_exception
458
+
459
+ model.fake_an_alert(:warning, :price, 'qar')
460
+ expect{ model.raise_exceptions }.not_to raise_exception
461
+ end
462
+
463
+ end
464
+ ##
465
+
466
+
467
+ describe '#create' do
468
+
469
+ let (:new_model) { CustomerModel.new }
470
+
471
+ it 'takes no parameters' do
472
+ expect{ CustomerModel.new.create(12) }.to raise_exception ArgumentError
473
+ expect{ CustomerModel.new.create }.not_to raise_exception
474
+ end
475
+
476
+ it 'returns self' do
477
+ expect( new_model.create ).to eq new_model
478
+ end
479
+
480
+ it 'calls validate' do
481
+ expect( new_model ).to receive(:validate)
482
+ new_model.create
483
+ end
484
+
485
+ it 'calls create on the interface if the record is good' do
486
+ expect( CustomerModel.interface ).to receive(:create)
487
+ CustomerModel.new.create
488
+
489
+ new_model.fake_an_alert(:warning, :name, 'foo')
490
+ expect( new_model.interface ).to receive(:create)
491
+ new_model.create
492
+ end
493
+
494
+
495
+ it 'doesnt call create on the interface if the record is bad' do
496
+ new_model.fake_an_alert(:error, :name, 'foo')
497
+ expect( new_model.interface ).not_to receive(:create)
498
+ new_model.create
499
+ end
500
+
501
+ it 'sets the ID' do
502
+ new_model.id = 50
503
+ new_model.name = "Lurch"
504
+ new_model.create
505
+
506
+ expect( new_model.model_id ).to eq 50
507
+ end
508
+
509
+ it 'sets model status to :okay if it was :empty' do
510
+ new_model.id = 50
511
+ new_model.name = "Lurch"
512
+ new_model.create
513
+
514
+ expect( new_model.model_status ).to eq :okay
515
+ end
516
+
517
+ it 'leaves the model status alone if it was not :empty' do
518
+ new_model.id = 50
519
+ new_model.name = "Lurch"
520
+ new_model.create
521
+
522
+ new_model.fake_an_alert(:warning, :price, 'qar')
523
+ expect( new_model.model_status ).to eq :warning
524
+ end
525
+
526
+ it 'calls map_to_interface to get record data' do
527
+ allow( new_model.interface ).to receive(:create)
528
+ expect( new_model ).to receive(:map_to_interface)
529
+
530
+ new_model.id = 50
531
+ new_model.name = "Lurch"
532
+ new_model.create
533
+ end
534
+
535
+ end
536
+ ##
537
+
538
+
539
+ describe '#read' do
540
+
541
+ it 'takes no parameters' do
542
+ expect{ CustomerModel.new.create(12) }.to raise_exception ArgumentError
543
+ expect{ CustomerModel.new.create }.not_to raise_exception
544
+ end
545
+
546
+ it 'returns self ' do
547
+ allow( model.interface ).
548
+ to receive(:read).
549
+ and_return( records_as_ot.first )
550
+
551
+ expect( model.read ).to eq model
552
+ end
553
+
554
+ it 'calls read on the interface' do
555
+ expect( model.interface ).
556
+ to receive(:read).
557
+ and_return( records_as_ot.first )
558
+
559
+ model.read
560
+ end
561
+
562
+ it 'calls validate' do
563
+ allow( model.interface ).
564
+ to receive(:read).
565
+ and_return( records_as_ot.first )
566
+
567
+ expect( model ).to receive(:validate)
568
+ model.read
569
+ end
570
+
571
+ it 'sets the attribute columns using map_to_model' do
572
+ ot = records_as_ot.last
573
+ allow( model.interface ).to receive(:read).and_return( ot )
574
+
575
+ cm = CustomerModel.new(10).read
576
+ expect( cm.id ).to eq ot.>>.id
577
+ expect( cm.name ).to eq ot.>>.name
578
+ expect( cm.price ).to eq ot.>>.price
579
+ expect( cm.groups ).to be_a_kind_of(Array)
580
+ expect( cm.groups ).to eq( ot.>>.groups.split(',') )
581
+ end
582
+
583
+ it 'sets model status to :okay if it was :empty' do
584
+ ot = records_as_ot.last
585
+ allow( model.interface ).to receive(:read).and_return( ot )
586
+
587
+ model.read
588
+ expect( model.model_status ).to eq :okay
589
+ end
590
+
591
+ it 'leaves the model status alone if it was not :empty' do
592
+ ot = records_as_ot.last
593
+ allow( model.interface ).to receive(:read).and_return( ot )
594
+
595
+ model.fake_an_alert(:warning, :price, 'qar')
596
+ model.read
597
+ expect( model.model_status ).to eq :warning
598
+ end
599
+
600
+ context 'if the interface.read returns an empty Octothorpe' do
601
+ let(:missing) { CustomerModel.new(99) }
602
+
603
+ it 'doesn\'t throw an exception' do
604
+ expect{ missing.read }.not_to raise_exception
605
+ end
606
+
607
+ it 'raises an error alert' do
608
+ expect( missing.read.model_status ).to eq :error
609
+ expect( missing.read.alerts.first.type ).to eq :error
610
+ end
611
+
612
+ end
613
+
614
+ end
615
+ ##
616
+
617
+
618
+ describe '#update' do
619
+
620
+ before do
621
+ allow( model2.interface ).
622
+ to receive(:update).
623
+ and_return( model2.interface )
624
+
625
+ end
626
+
627
+ it 'takes no parameters' do
628
+ expect{ model2.update(12) }.to raise_exception ArgumentError
629
+ expect{ model2.update }.not_to raise_exception
630
+ end
631
+
632
+ it 'returns self' do
633
+ expect( model2.update ).to eq model2
634
+ end
635
+
636
+ it 'raises a Pod4Error if model status is :empty' do
637
+ allow( model.interface ).to receive(:update).and_return( model.interface )
638
+
639
+ expect( model.model_status ).to eq :empty
640
+ expect{ model.update }.to raise_exception Pod4::Pod4Error
641
+ end
642
+
643
+ it 'raises a Pod4Error if model status is :deleted' do
644
+ model2.delete
645
+ expect{ model2.update }.to raise_exception Pod4::Pod4Error
646
+ end
647
+
648
+ it 'calls validate' do
649
+ expect( model2 ).to receive(:validate)
650
+ model2.update
651
+ end
652
+
653
+ it 'calls update on the interface if the validation passes' do
654
+ expect( model3.interface ).
655
+ to receive(:update).
656
+ and_return( model3.interface )
657
+
658
+ model3.update
659
+ end
660
+
661
+ it 'doesnt call update on the interface if the validation fails' do
662
+ expect( model3.interface ).not_to receive(:update)
663
+
664
+ model3.name = "fall over" # triggers validation
665
+ model3.update
666
+ end
667
+
668
+ it 'calls map_to_interface to get record data' do
669
+ expect( model3 ).to receive(:map_to_interface)
670
+ model3.update
671
+ end
672
+
673
+ context 'when the record already has error alerts' do
674
+
675
+ it 'passes if there is no longer anything wrong' do
676
+ expect( model3.interface ).
677
+ to receive(:update).
678
+ and_return( model3.interface )
679
+
680
+ model3.fake_an_alert(:error, "bad things")
681
+ model3.update
682
+ end
683
+
684
+ end
685
+
686
+
687
+ end
688
+ ##
689
+
690
+
691
+ describe '#delete' do
692
+
693
+ before do
694
+ allow( model2.interface ).
695
+ to receive(:delete).
696
+ and_return( model2.interface )
697
+
698
+ end
699
+
700
+ it 'takes no parameters' do
701
+ expect{ model2.delete(12) }.to raise_exception ArgumentError
702
+ expect{ model2.delete }.not_to raise_exception
703
+ end
704
+
705
+ it 'returns self' do
706
+ expect( model2.delete ).to eq model2
707
+ end
708
+
709
+ it 'raises a Pod4Error if model status is :empty' do
710
+ allow( model.interface ).to receive(:delete).and_return( model.interface )
711
+
712
+ expect( model.model_status ).to eq :empty
713
+ expect{ model.delete }.to raise_exception Pod4::Pod4Error
714
+ end
715
+
716
+ it 'raises a Pod4Error if model status is :deleted'do
717
+ model2.delete
718
+ expect{ model2.delete }.to raise_exception Pod4::Pod4Error
719
+ end
720
+
721
+ it 'calls validate' do
722
+ expect( model2 ).to receive(:validate)
723
+ model2.delete
724
+ end
725
+
726
+ it 'calls delete on the interface if the model status is good' do
727
+ expect( model3.interface ).
728
+ to receive(:delete).
729
+ and_return( model3.interface )
730
+
731
+ model3.delete
732
+ end
733
+
734
+ it 'calls delete on the interface if the model status is bad' do
735
+ expect( model3.interface ).
736
+ to receive(:delete).
737
+ and_return( model3.interface )
738
+
739
+ model3.fake_an_alert(:error, :price, 'qar')
740
+ model3.delete
741
+ end
742
+
743
+ it 'still gives you full access to the data after a delete' do
744
+ model2.delete
745
+
746
+ expect( model2.id ).to eq records_as_ot[2].>>.id
747
+ expect( model2.name ).to eq records_as_ot[2].>>.name
748
+ expect( model2.price ).to eq records_as_ot[2].>>.price
749
+ end
750
+
751
+ it 'sets status to :deleted' do
752
+ model2.delete
753
+ expect( model2.model_status ).to eq :deleted
754
+ end
755
+
756
+ end
757
+ ##
758
+
759
+ end
760
+