amee-data-abstraction 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/.rvmrc +1 -0
  2. data/CHANGELOG.txt +4 -0
  3. data/Gemfile +16 -0
  4. data/Gemfile.lock +41 -0
  5. data/LICENSE.txt +27 -0
  6. data/README.txt +188 -0
  7. data/Rakefile +102 -0
  8. data/VERSION +1 -0
  9. data/amee-data-abstraction.gemspec +115 -0
  10. data/examples/_calculator_form.erb +27 -0
  11. data/examples/calculation_controller.rb +16 -0
  12. data/init.rb +4 -0
  13. data/lib/amee-data-abstraction.rb +30 -0
  14. data/lib/amee-data-abstraction/calculation.rb +236 -0
  15. data/lib/amee-data-abstraction/calculation_set.rb +101 -0
  16. data/lib/amee-data-abstraction/drill.rb +63 -0
  17. data/lib/amee-data-abstraction/exceptions.rb +47 -0
  18. data/lib/amee-data-abstraction/input.rb +197 -0
  19. data/lib/amee-data-abstraction/metadatum.rb +58 -0
  20. data/lib/amee-data-abstraction/ongoing_calculation.rb +545 -0
  21. data/lib/amee-data-abstraction/output.rb +16 -0
  22. data/lib/amee-data-abstraction/profile.rb +108 -0
  23. data/lib/amee-data-abstraction/prototype_calculation.rb +350 -0
  24. data/lib/amee-data-abstraction/term.rb +506 -0
  25. data/lib/amee-data-abstraction/terms_list.rb +150 -0
  26. data/lib/amee-data-abstraction/usage.rb +90 -0
  27. data/lib/config/amee_units.rb +129 -0
  28. data/lib/core-extensions/class.rb +27 -0
  29. data/lib/core-extensions/hash.rb +43 -0
  30. data/lib/core-extensions/ordered_hash.rb +21 -0
  31. data/lib/core-extensions/proc.rb +15 -0
  32. data/rails/init.rb +32 -0
  33. data/spec/amee-data-abstraction/calculation_set_spec.rb +54 -0
  34. data/spec/amee-data-abstraction/calculation_spec.rb +75 -0
  35. data/spec/amee-data-abstraction/drill_spec.rb +38 -0
  36. data/spec/amee-data-abstraction/input_spec.rb +77 -0
  37. data/spec/amee-data-abstraction/metadatum_spec.rb +17 -0
  38. data/spec/amee-data-abstraction/ongoing_calculation_spec.rb +494 -0
  39. data/spec/amee-data-abstraction/profile_spec.rb +39 -0
  40. data/spec/amee-data-abstraction/prototype_calculation_spec.rb +256 -0
  41. data/spec/amee-data-abstraction/term_spec.rb +385 -0
  42. data/spec/amee-data-abstraction/terms_list_spec.rb +53 -0
  43. data/spec/config/amee_units_spec.rb +71 -0
  44. data/spec/core-extensions/class_spec.rb +25 -0
  45. data/spec/core-extensions/hash_spec.rb +44 -0
  46. data/spec/core-extensions/ordered_hash_spec.rb +12 -0
  47. data/spec/core-extensions/proc_spec.rb +12 -0
  48. data/spec/fixtures/electricity.rb +35 -0
  49. data/spec/fixtures/electricity_and_transport.rb +55 -0
  50. data/spec/fixtures/transport.rb +26 -0
  51. data/spec/spec.opts +2 -0
  52. data/spec/spec_helper.rb +244 -0
  53. metadata +262 -0
@@ -0,0 +1,53 @@
1
+ require File.dirname(File.dirname(__FILE__)) + '/spec_helper.rb'
2
+
3
+ describe TermsList do
4
+ it 'should be returned from calculations' do
5
+ Transport.terms.should be_a TermsList
6
+ end
7
+ it 'should give properties' do
8
+ Transport.terms.labels.should eql [:fuel,:size,:distance,:co2]
9
+ Transport.terms.paths.should eql ['fuel','size','distance',:default]
10
+ Transport.terms.names.should eql ['Fuel Type','Vehicle Size','Distance Driven','Carbon Dioxide']
11
+ end
12
+ it 'should select by class' do
13
+ Transport.terms.drills.labels.should eql [:fuel,:size]
14
+ Transport.terms.profiles.labels.should eql [:distance]
15
+ Transport.terms.outputs.labels.should eql [:co2]
16
+ end
17
+ it 'should select by property' do
18
+ t=Transport.begin_calculation
19
+ t[:distance].value 5
20
+ t.terms.set.labels.should eql [:distance]
21
+ t.terms.unset.labels.should eql [:fuel,:size,:co2]
22
+ end
23
+ it 'should select by chain' do
24
+ t=Transport.begin_calculation
25
+ t[:fuel].value 'diesel'
26
+ t.terms.drills.set.labels.should eql [:fuel]
27
+ t.terms.drills.unset.labels.should eql [:size]
28
+ t.terms.set.drills.labels.should eql [:fuel]
29
+ t.terms.unset.drills.labels.should eql [:size]
30
+ end
31
+ it 'should select by order' do
32
+ t=Transport.clone
33
+ t.terms.before(:distance).labels.
34
+ should eql [:fuel,:size]
35
+ t.terms.after(:distance).labels.
36
+ should eql [:co2]
37
+ end
38
+ it 'can select terms by usage' do
39
+ mocker=AMEEMocker.new self,:path=>'transport/car/generic'
40
+ mocker.item_value_definitions.
41
+ item_definition.data_category.
42
+ item_value_definition('distance',['usage1'],['usage2'],['usage3'])
43
+ t=Transport.clone
44
+ t.profiles.compulsory('usage1').labels.should eql [:distance]
45
+ t.profiles.optional('usage2').labels.should eql [:distance]
46
+ t.profiles.compulsory('usage2').labels.should be_empty
47
+ t.profiles.optional('usage1').labels.should be_empty
48
+ t.profiles.in_use('usage2').labels.should eql [:distance]
49
+ t.profiles.in_use('usage1').labels.should eql [:distance]
50
+ t.profiles.in_use('usage3').labels.should be_empty
51
+ end
52
+
53
+ end
@@ -0,0 +1,71 @@
1
+
2
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
3
+
4
+ describe "AMEE units" do
5
+
6
+ include Quantify
7
+
8
+ # The Unit.<unit_name_symbol_or_label> pattern retrieves the unit which is
9
+ # provided as the (pseudo) method name (using #method_missing). In cases where
10
+ # the named unit does not exist an error is raised. In some cases, however,
11
+ # where the unit can be constructed from a known and compatible unit and prefix
12
+ # combination, it is created but not loaded to the canonical system of units.
13
+ # Therefore, to test for presence or absence of partiuclar units, we check that
14
+ # the units we want are #loaded? and that the ones we don't want are either NOT
15
+ # #loaded? (if the happen to be derivable) or otherwise raise an error.
16
+
17
+ it "should include commonly used SI units" do
18
+ Unit.metre.should be_loaded
19
+ Unit.second.should be_loaded
20
+ Unit.kg.should be_loaded
21
+ end
22
+
23
+ it "should include commonly used non SI units" do
24
+ Unit.foot.should be_loaded
25
+ Unit.pound.should be_loaded
26
+ Unit.month.should be_loaded
27
+ end
28
+
29
+ it "should exclude uncommonly used SI units" do
30
+ Unit.micrometre.should_not be_loaded
31
+ lambda{Unit.galileo}.should raise_error
32
+ lambda{Unit.inverse_centimetre}.should raise_error
33
+ end
34
+
35
+ it "should exclude uncommonly used non SI units" do
36
+ lambda{Unit.astronomical_unit}.should raise_error
37
+ lambda{Unit.dyne_centimetre}.should raise_error
38
+ lambda{Unit.maxwell}.should raise_error
39
+ end
40
+
41
+ it "should include commonly used SI units and prefixes" do
42
+ Unit.terajoule.should be_loaded
43
+ Unit.gigagram.should be_loaded
44
+ Unit.megawatt.should be_loaded
45
+ end
46
+
47
+ it "should include commonly used Non SI units and prefixes" do
48
+ Unit.MBTU.should be_loaded
49
+ end
50
+
51
+ it "should exclude uncommonly used SI units and prefixes" do
52
+ Unit.microjoule.should_not be_loaded
53
+ Unit.nanogram.should_not be_loaded
54
+ Unit.picowatt.should_not be_loaded
55
+ end
56
+
57
+ it "should represent the BTU with the 59F version" do
58
+ Unit.BTU.label.should eql "BTU_FiftyNineF"
59
+ end
60
+
61
+ it "should label the unit for 'day' as 'day'" do
62
+ Unit.day.label.should eql 'day'
63
+ end
64
+
65
+ it "should recognise the unit for megawatt_hour as 'MWh'" do
66
+ Unit.megawatt_hour.label.should eql 'MWh'
67
+ Unit.megawatt_hour.symbol.should eql 'MWh'
68
+ end
69
+
70
+ end
71
+
@@ -0,0 +1,25 @@
1
+ require File.dirname(File.dirname(__FILE__)) + '/spec_helper.rb'
2
+
3
+ class Myclass
4
+ attr_property :prop
5
+ end
6
+
7
+ describe Class do
8
+ before :all do
9
+ @it=Myclass.new
10
+ end
11
+ it 'can have a property defined' do
12
+ @it.prop 5
13
+ @it.prop.should eql 5
14
+ end
15
+ it 'can have a prop unset' do
16
+ @it.prop 5
17
+ @it.prop nil
18
+ @it.prop.should be_nil
19
+ end
20
+ it 'does not unset by query' do
21
+ @it.prop 5
22
+ @it.prop
23
+ @it.prop.should_not be_nil
24
+ end
25
+ end
@@ -0,0 +1,44 @@
1
+
2
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
3
+
4
+ describe Hash do
5
+ before(:each) do
6
+ @hash = { 'first_name' => 'Kenny',
7
+ 'last_name' => 'Rogers',
8
+ 'date_of_birth' => {'day' => 17,
9
+ 'month' => 'April',
10
+ 'year' => 1939 },
11
+ 'interests' => [ {'movie' => 'Birds',
12
+ 'book' => 'Catch 22'},
13
+ "guitar",
14
+ {'song' => 'Leaving On a Jetplane'} ],
15
+ :already_a_symbol => 'dummy' }
16
+ end
17
+
18
+ it "should symbolize keys, returning new hash" do
19
+ new_hash = @hash.recursive_symbolize_keys
20
+ new_hash.keys.size.should eql 5
21
+ new_hash.keys.each { |k| k.should be_a Symbol }
22
+ new_hash[:first_name].should eql 'Kenny'
23
+ new_hash[:date_of_birth].should be_a Hash
24
+ new_hash[:date_of_birth].keys.each { |k| k.should be_a Symbol }
25
+ new_hash[:date_of_birth][:month].should eql 'April'
26
+ new_hash[:interests].should be_a Array
27
+ new_hash[:interests][0].keys.each { |k| k.should be_a Symbol }
28
+ new_hash[:interests][0][:movie].should eql 'Birds'
29
+ end
30
+
31
+ it "should symbolize keys in place, returning self" do
32
+ @hash.recursive_symbolize_keys!
33
+ @hash.keys.size.should eql 5
34
+ @hash.keys.each { |k| k.should be_a Symbol }
35
+ @hash[:first_name].should eql 'Kenny'
36
+ @hash[:date_of_birth].should be_a Hash
37
+ @hash[:date_of_birth].keys.each { |k| k.should be_a Symbol }
38
+ @hash[:date_of_birth][:month].should eql 'April'
39
+ @hash[:interests].should be_a Array
40
+ @hash[:interests][0].keys.each { |k| k.should be_a Symbol }
41
+ @hash[:interests][0][:movie].should eql 'Birds'
42
+ end
43
+ end
44
+
@@ -0,0 +1,12 @@
1
+ require File.dirname(File.dirname(__FILE__)) + '/spec_helper.rb'
2
+
3
+
4
+ describe ActiveSupport::OrderedHash do
5
+ it 'Can insert at start' do
6
+ x=ActiveSupport::OrderedHash[[[1,2],[3,4]]]
7
+ x.keys.should eql [1,3]
8
+ x.insert_at_start(5,6)
9
+ x.keys.should eql [5,1,3]
10
+ x.to_a.should eql [[5,6],[1,2],[3,4]]
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require File.dirname(File.dirname(__FILE__)) + '/spec_helper.rb'
2
+
3
+ describe Proc do
4
+ before :all do
5
+ @it=Proc.new{|x|x.is_a? Float}
6
+ end
7
+ it 'uses call as ===' do
8
+ (@it===3.4).should be_true
9
+ (@it===7).should be_false
10
+ (@it==='hello').should be_false
11
+ end
12
+ end
@@ -0,0 +1,35 @@
1
+ Electricity=AMEE::DataAbstraction::PrototypeCalculation.new { # The application has support for an electricity calculation. :electricity is the internal label used to refer to it
2
+ label :electricity
3
+ name "Electricity Consumption"
4
+ path '/business/energy/electricity/grid'
5
+
6
+ drill {
7
+ fixed 'argentina' #Not to be unset, value pre-given
8
+ label :country #Name will default to label.humanize if not given
9
+ path 'country' #Some of the fields on the form are drill-downs, but the application doesn't need to display these differently
10
+ #type :autocompleting_text_box #default for a drill with entries is probably a dropdown
11
+ }
12
+
13
+ profile {
14
+ label :energy_used
15
+ # Symbol provided here is used in generating html ids for elements etc
16
+ path 'energyPerTime' #The amee profile item value corresponding to the field
17
+ name "Energy Used" #The display name used on the form
18
+ unit "kWh" #Default unit choice
19
+ interface :text_box #Probably not needed, as likely to be the default for profile item value unsets
20
+ validation lambda{|x|x.is_a? Float} #Probably not needed, as default can be deduced from PIV TYPE in API. Here as illustrative.
21
+ alternative_units :MWh, :MBTU, :BTU # If these are explcitly specified then the alternatives are limited to only these units. Otherwise all dimensionally equivalent units are available as alternatives by default
22
+ }
23
+
24
+ # Alternatively, the drill might be fixed
25
+ #permanent :country {
26
+ # drill_path 'country'
27
+ # value 'Argentina'
28
+
29
+ output { #A marv output value
30
+ label :co2
31
+ path :default #It's not a marv, use the default output
32
+ name "Carbon Dioxide"
33
+ }
34
+ }
35
+
@@ -0,0 +1,55 @@
1
+ ElectricityAndTransport=AMEE::DataAbstraction::CalculationSet.new {
2
+ all_calculations {
3
+ metadatum {
4
+ label :department
5
+ choices %w{stuff things more_stuff meta_things}
6
+ }
7
+ }
8
+
9
+ calculation{
10
+ name 'electricity'
11
+ label :electricity
12
+ path '/business/energy/electricity/grid'
13
+ profile {
14
+ label :usage
15
+ name 'Electricity Used'
16
+ path 'energyPerTime'
17
+ }
18
+ drill {
19
+ label :country
20
+ path 'country'
21
+ fixed 'Argentina'
22
+ }
23
+ output {
24
+ label :co2
25
+ path :default
26
+ }
27
+ }
28
+
29
+ calculation {
30
+ name 'transport'
31
+ label :transport
32
+ path '/transport/car/generic'
33
+
34
+ drill {
35
+ path 'fuel'
36
+ label :fuel
37
+ name 'Fuel Type'
38
+ }
39
+ drill {
40
+ path 'size'
41
+ label :size
42
+ name 'Vehicle Size'
43
+ }
44
+ profile {
45
+ path 'distance'
46
+ label :distance
47
+ name 'Distance Driven'
48
+ }
49
+ output {
50
+ label :co2
51
+ path :default
52
+ name 'Carbon Dioxide'
53
+ }
54
+ }
55
+ }
@@ -0,0 +1,26 @@
1
+ Transport=AMEE::DataAbstraction::PrototypeCalculation.new{
2
+ name 'transport'
3
+ label :transport
4
+ path '/transport/car/generic'
5
+
6
+ drill {
7
+ path 'fuel'
8
+ label :fuel
9
+ name 'Fuel Type'
10
+ }
11
+ drill {
12
+ path 'size'
13
+ label :size
14
+ name 'Vehicle Size'
15
+ }
16
+ profile {
17
+ path 'distance'
18
+ label :distance
19
+ name 'Distance Driven'
20
+ }
21
+ output {
22
+ label :co2
23
+ path :default
24
+ name 'Carbon Dioxide'
25
+ }
26
+ }
data/spec/spec.opts ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --format RspecSpinner::Bar
@@ -0,0 +1,244 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+ require 'rspec_spinner'
4
+ require 'flexmock'
5
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
6
+ require 'amee'
7
+ require 'amee-data-abstraction'
8
+
9
+ Spec::Runner.configure do |config|
10
+ config.mock_with :flexmock
11
+ end
12
+
13
+ AMEE::DataAbstraction.connection=FlexMock.new('connection') #Global connection mock, shouldn't receive anything, as we mock the individual amee-ruby calls in the tests
14
+
15
+ Dir.glob(File.dirname(__FILE__) + '/fixtures/*') do |filename|
16
+ require filename
17
+ end
18
+
19
+ include AMEE::DataAbstraction
20
+
21
+ class AMEEMocker
22
+ def initialize(test,options)
23
+ @path=options[:path]
24
+ sel=options[:selections]||[]
25
+ @selections=ActiveSupport::OrderedHash[sel]
26
+ @choices=options[:choices]||[]
27
+ @result=options[:result]
28
+ @params=options[:params]||{}
29
+ @existing=options[:existing]||{}
30
+ @test=test
31
+ @mock_dc=test.flexmock(:path=>"/data/#{path}")
32
+ @mock_id=test.flexmock
33
+ @mock_ivds=[]
34
+ @mock_rvds=[]
35
+ end
36
+
37
+ attr_accessor :path,:selections,:choices,:result,:params,
38
+ :existing,:mock_dc,:mock_id,:mock_ivds,:mock_rvds
39
+
40
+ attr_reader :test
41
+
42
+ def catuid
43
+ path.gsub(/\//,'-').to_sym
44
+ end
45
+
46
+ def select(opts)
47
+ # Like an array of pairs, not a hash, for ordering reasons.
48
+ opts.each do |k,v|
49
+ @selections[k]=v
50
+ end
51
+ end
52
+
53
+ def connection
54
+ AMEE::DataAbstraction.connection
55
+ end
56
+
57
+ def dataitemuid
58
+ "#{catuid}:#{selections.map{|k,v|"#{k}-#{v}"}.join('-')}"
59
+ end
60
+
61
+ def uid
62
+ dataitemuid+"PI"
63
+ end
64
+
65
+ def pipath
66
+ "/profiles/someprofileuid/#{path}/#{uid}"
67
+ end
68
+
69
+ def dipath
70
+ "/data/#{path}/#{dataitemuid}"
71
+ end
72
+
73
+ def drill
74
+ test.flexmock(AMEE::Data::DrillDown).
75
+ should_receive(:get).
76
+ with(connection,
77
+ "/data/#{path}/drill?#{selections.map{|k,v|"#{k}=#{v}"}.join('&')}").
78
+ at_least.once.
79
+ and_return(test.flexmock(:choices=>choices,:selections=>Hash[selections],
80
+ :data_item_uid=>dataitemuid))
81
+ return self
82
+ end
83
+
84
+ def profile_list
85
+ test.flexmock(AMEE::Profile::ProfileList).should_receive(:new).
86
+ with(connection).at_least.once.
87
+ and_return(test.flexmock(:first=>test.flexmock(:uid=>:someprofileuid)))
88
+ return self
89
+ end
90
+
91
+ def timestamp
92
+ test.flexmock(UUIDTools::UUID).should_receive(:timestamp_create).at_least.once.
93
+ and_return(:sometimestamp)
94
+ return self
95
+ end
96
+
97
+ def profile_category
98
+ test.flexmock(AMEE::Profile::Category).should_receive(:get).
99
+ with(connection,"/profiles/someprofileuid/#{path}").at_least.once.
100
+ and_return(catuid)
101
+ return self
102
+ end
103
+
104
+ def itemdef_drills(some_drills)
105
+ mock_id.should_receive(:drill_downs).and_return(some_drills)
106
+ return self
107
+ end
108
+
109
+ def return_value_definition(path,unit=nil,per_unit=nil)
110
+ rvd=test.flexmock :name=>path
111
+ rvd.should_receive(:unit).and_return unit
112
+ rvd.should_receive(:perunit).and_return per_unit
113
+ mock_rvds.push rvd
114
+ return self
115
+ end
116
+
117
+ def return_value_definitions
118
+ test.flexmock(AMEE::Admin::ReturnValueDefinitionList).should_receive(:new).
119
+ with(connection,:itemdefuid).and_return mock_rvds
120
+ return self
121
+ end
122
+
123
+ def item_value_definition_metadata(meta)
124
+ AMEE::Admin::ItemValueDefinition.new(:meta=>meta).meta
125
+ end
126
+
127
+ def item_value_definition(path,compulsories=[],optionals=[],forbiddens=[],choices=[],unit=nil,per_unit=nil,profile=true,drill=false,default=nil,type=nil,wikidoc=nil)
128
+ ivd=test.flexmock :path=>path
129
+ ivd.should_receive(:name).and_return path.to_s.humanize
130
+ ivd.should_receive(:profile?).and_return profile
131
+ ivd.should_receive(:drill?).and_return drill
132
+ ivd.should_receive(:versions).and_return ['2.0']
133
+ ivd.should_receive(:unit).and_return unit
134
+ ivd.should_receive(:perunit).and_return per_unit
135
+ ivd.should_receive(:choices).and_return choices
136
+ ivd.should_receive(:default).and_return default
137
+ ivd.should_receive(:valuetype).and_return type
138
+ ivd.should_receive(:meta).and_return(item_value_definition_metadata(:wikidoc=>wikidoc))#.should_receive(:wikidoc).and_return wikidoc
139
+ compulsories.each do |compulsory|
140
+ ivd.should_receive(:compulsory?).with(compulsory).and_return(true)
141
+ ivd.should_receive(:optional?).with(compulsory).and_return(false)
142
+ end
143
+ optionals.each do |optional|
144
+ ivd.should_receive(:optional?).with(optional).and_return(true)
145
+ ivd.should_receive(:compulsory?).with(optional).and_return(false)
146
+ end
147
+ forbiddens.each do |forbidden|
148
+ ivd.should_receive(:optional?).with(forbidden).and_return(false)
149
+ ivd.should_receive(:compulsory?).with(forbidden).and_return(false)
150
+ end
151
+ mock_ivds.push ivd
152
+ return self
153
+ end
154
+
155
+ def item_value_definitions
156
+ mock_id.should_receive(:item_value_definition_list).at_least.once.and_return(mock_ivds)
157
+ return self
158
+ end
159
+
160
+ def usages(someusages)
161
+ mock_id.should_receive(:usages).and_return(someusages)
162
+ return self
163
+ end
164
+
165
+ def item_definition(name=:itemdef_name)
166
+ mock_id.should_receive(:name).and_return(name)
167
+ mock_id.should_receive(:uid).and_return(:itemdefuid)
168
+ mock_dc.should_receive(:item_definition).at_least.once.and_return(mock_id)
169
+ return self
170
+ end
171
+
172
+ def data_category
173
+ test.flexmock(AMEE::Data::Category).should_receive(:get).
174
+ with(connection,"/data/#{path}").at_least.once.
175
+ and_return(mock_dc)
176
+ return self
177
+ end
178
+
179
+ def create
180
+ test.flexmock(AMEE::Profile::Item).should_receive(:create).
181
+ with(catuid,dataitemuid,
182
+ {:get_item=>false,:name=>:sometimestamp}.merge(params)).
183
+ at_least.once.
184
+ and_return(pipath)
185
+ return self
186
+ end
187
+
188
+ def get(with_pi=false,failing=false,once=false)
189
+ mock_pi=test.flexmock(
190
+ :amounts=>test.flexmock(:find=>{:value=>result}),
191
+ :data_item_uid=>dataitemuid
192
+ )
193
+ mock_di=test.flexmock
194
+ if with_pi
195
+ from_amee=existing.clone
196
+ params.each {|key,val| from_amee.delete key}
197
+ from_amee.each do |k,v|
198
+ if failing
199
+ mock_pi.should_receive(:values).and_return([{:path => k,:value => v }])
200
+ else
201
+ mock_pi.should_receive(:values).and_return([{:path => k,:value => v }]).once
202
+ end
203
+ end
204
+ selections.each do |k,v|
205
+ if failing
206
+ mock_di.should_receive(:value).with(k).and_return(v)
207
+ else
208
+ mock_di.should_receive(:value).with(k).and_return(v).once
209
+ end
210
+ end
211
+ test.flexmock(AMEE::Data::Item).should_receive(:get).
212
+ with(connection,dipath,{}).
213
+ at_least.once.
214
+ and_return(mock_di)
215
+ end
216
+ if once
217
+ test.flexmock(AMEE::Profile::Item).should_receive(:get).
218
+ with(connection,pipath,{}).
219
+ at_least.once.
220
+ and_return(mock_pi)
221
+ else
222
+ test.flexmock(AMEE::Profile::Item).should_receive(:get).
223
+ with(connection,pipath,{}).
224
+ at_least.once.
225
+ and_return(mock_pi)
226
+ end
227
+ return self
228
+ end
229
+
230
+ def delete
231
+ test.flexmock(AMEE::Profile::Item).should_receive(:delete).
232
+ at_least.once.
233
+ with(connection,pipath)
234
+ return self
235
+ end
236
+
237
+ def update
238
+ test.flexmock(AMEE::Profile::Item).should_receive(:update).
239
+ with(connection,pipath,
240
+ {:get_item=>false}.merge(existing).merge(params)).
241
+ at_least.once
242
+ return self
243
+ end
244
+ end