ooor 1.3.0 → 1.3.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.
- data/spec/ooor_spec.rb +356 -0
- metadata +3 -2
data/spec/ooor_spec.rb
ADDED
@@ -0,0 +1,356 @@
|
|
1
|
+
require "lib/ooor.rb"
|
2
|
+
|
3
|
+
#RSpec executable specification; see http://rspec.info/ for more information.
|
4
|
+
#Run the file with the rspec command from the rspec gem
|
5
|
+
describe Ooor do
|
6
|
+
before(:all) do
|
7
|
+
@url = 'http://localhost:8069/xmlrpc'
|
8
|
+
@db_password = 'admin'
|
9
|
+
@username = 'admin'
|
10
|
+
@password = 'admin'
|
11
|
+
@database = 'ooor_test'
|
12
|
+
@ooor = Ooor.new(:url => @url, :username => @username, :admin => @password)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should keep quiet if no database is mentioned" do
|
16
|
+
@ooor.loaded_models.should be_empty
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should be able to list databases" do
|
20
|
+
@ooor.list.should be_kind_of(Array)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should be able to create a new database with demo data" do
|
24
|
+
unless @ooor.list.index(@database)
|
25
|
+
@ooor.create(@db_password, @database)
|
26
|
+
end
|
27
|
+
@ooor.list.index(@database).should_not be_nil
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
describe "Configure existing database" do
|
32
|
+
before(:all) do
|
33
|
+
@ooor = Ooor.new(:url => @url, :username => @username, :admin => @password, :database => @database)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should be able to load a profile" do
|
37
|
+
manufacturing_module_id = IrModuleModule.search([['name','=', 'profile_manufacturing']])[0]
|
38
|
+
unless IrModuleModule.find(manufacturing_module_id).state == "installed"
|
39
|
+
w = @ooor.old_wizard_step('base_setup.base_setup')
|
40
|
+
w.company(:profile => manufacturing_module_id)
|
41
|
+
w.update(:name => 'Akretion.com', :state_id => false)
|
42
|
+
w.finish
|
43
|
+
@ooor.load_models
|
44
|
+
@ooor.loaded_models.should_not be_empty
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should be able to configure the database" do
|
49
|
+
chart_module_id = IrModuleModule.search([['category_id', '=', 'Account Charts'], ['name','=', 'l10n_fr']])[0]
|
50
|
+
unless IrModuleModule.find(chart_module_id).state == "installed"
|
51
|
+
w2 = @ooor.const_get('account.config.wizard').create(:charts => chart_module_id)
|
52
|
+
w2.action_create
|
53
|
+
w3 = @ooor.const_get('wizard.multi.charts.accounts').create
|
54
|
+
w3.action_create
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
describe "Do operations on configured database" do
|
61
|
+
before(:all) do
|
62
|
+
@ooor = Ooor.new(:url => @url, :username => @username, :admin => @password, :database => @database,
|
63
|
+
:models => ['res.user', 'res.partner', 'product.product', 'sale.order', 'account.invoice', 'product.category', 'stock.move', 'ir.ui.menu'])
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "Finders operations" do
|
67
|
+
|
68
|
+
it "should be able to find data by id" do
|
69
|
+
p = ProductProduct.find(1)
|
70
|
+
p.should_not be_nil
|
71
|
+
l = ProductProduct.find([1,2])
|
72
|
+
l.size.should == 2
|
73
|
+
a = AccountInvoice.find(1)
|
74
|
+
a.should_not be_nil
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should load required models on the fly" do
|
78
|
+
SaleOrder.find(1).shop_id.should be_kind_of(SaleShop)
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should be able to specify the fields to read" do
|
82
|
+
p = ProductProduct.find(1, :fields=>["state", "id"])
|
83
|
+
p.should_not be_nil
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should be able to find using ir.model.data absolute ids" do
|
87
|
+
p = ProductProduct.find('product_product_pc1')
|
88
|
+
p.should_not be_nil
|
89
|
+
p = ProductProduct.find('product.product_product_pc1')#module scoping is optionnal
|
90
|
+
p.should_not be_nil
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should be able to use OpenERP domains" do
|
94
|
+
partners = ResPartner.find(:all, :domain=>[['supplier', '=', 1],['active','=',1]], :fields=>["id", "name"])
|
95
|
+
partners.should_not be_empty
|
96
|
+
products = ProductProduct.find(:all, :domain=>[['categ_id','=',1],'|',['name', '=', 'PC1'],['name','=','PC2']])
|
97
|
+
products.should be_kind_of(Array)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should mimic ActiveResource scoping" do
|
101
|
+
partners = ResPartner.find(:all, :params => {:supplier => true})
|
102
|
+
partners.should_not be_empty
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should support OpenERP context in finders" do
|
106
|
+
p = ProductProduct.find(1, :context => {:my_key => 'value'})
|
107
|
+
p.should_not be_nil
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should support OpenERP search method" do
|
111
|
+
partners = ResPartner.search([['name', 'ilike', 'a']], 0, 2)
|
112
|
+
partners.should_not be_empty
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should cast dates properly from OpenERP to Ruby" do
|
116
|
+
o = SaleOrder.find(1)
|
117
|
+
o.date_order.should be_kind_of(Date)
|
118
|
+
m = StockMove.find(1)
|
119
|
+
m.date.should be_kind_of(Time)
|
120
|
+
end
|
121
|
+
|
122
|
+
it "should be able to call any Class method" do
|
123
|
+
ResPartner.name_search('ax', [], 'ilike', {}).should_not be_nil
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
describe "Relations reading" do
|
129
|
+
it "should read many2one relations" do
|
130
|
+
o = SaleOrder.find(1)
|
131
|
+
o.partner_id.should be_kind_of(ResPartner)
|
132
|
+
p = ProductProduct.find(1) #inherited via product template
|
133
|
+
p.categ_id.should be_kind_of(ProductCategory)
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should read one2many relations" do
|
137
|
+
o = SaleOrder.find(1)
|
138
|
+
o.order_line.each do |line|
|
139
|
+
line.should be_kind_of(SaleOrderLine)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
it "should read many2many relations" do
|
144
|
+
SaleOrder.find(1).order_line[1].invoice_ids.should be_kind_of(Array)
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should read polymorphic references" do
|
148
|
+
IrUiMenu.find(:first, :domain => [['name', '=', 'Partners'], ['parent_id', '!=', false]]).action.should be_kind_of(IrActionsAct_window)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
describe "Basic creations" do
|
153
|
+
it "should be able to create a product" do
|
154
|
+
p = ProductProduct.create(:name => "testProduct1", :categ_id => 1)
|
155
|
+
ProductProduct.find(p.id).categ_id.id.should == 1
|
156
|
+
p = ProductProduct.new(:name => "testProduct1")
|
157
|
+
p.categ_id = 1
|
158
|
+
p.save
|
159
|
+
p.categ_id.id.should == 1
|
160
|
+
end
|
161
|
+
|
162
|
+
it "should be able to create an order" do
|
163
|
+
o = SaleOrder.create(:partner_id => ResPartner.search([['name', 'ilike', 'Agrolait']])[0],
|
164
|
+
:partner_order_id => 1, :partner_invoice_id => 1, :partner_shipping_id => 1, :pricelist_id => 1)
|
165
|
+
o.id.should be_kind_of(Integer)
|
166
|
+
end
|
167
|
+
|
168
|
+
it "should be able to to create an invoice" do
|
169
|
+
i = AccountInvoice.new(:origin => 'ooor_test')
|
170
|
+
partner_id = ResPartner.search([['name', 'ilike', 'Agrolait']])[0]
|
171
|
+
i.on_change('onchange_partner_id', :partner_id, partner_id, 'out_invoice', partner_id, false, false)
|
172
|
+
i.save
|
173
|
+
i.id.should be_kind_of(Integer)
|
174
|
+
end
|
175
|
+
|
176
|
+
it "should be able to call on_change" do
|
177
|
+
o = SaleOrder.new
|
178
|
+
partner_id = ResPartner.search([['name', 'ilike', 'Agrolait']])[0]
|
179
|
+
o.on_change('onchange_partner_id', :partner_id, partner_id, partner_id)
|
180
|
+
o.save
|
181
|
+
line = SaleOrderLine.new(:order_id => o.id)
|
182
|
+
product_id = 1
|
183
|
+
pricelist_id = 1
|
184
|
+
product_uom_qty = 1
|
185
|
+
line.on_change('product_id_change', :product_id, product_id, pricelist_id, product_id, product_uom_qty, false, 1, false, false, o.partner_id.id, 'en_US', true, false, false, false)
|
186
|
+
line.save
|
187
|
+
SaleOrder.find(o.id).order_line.size.should == 1
|
188
|
+
end
|
189
|
+
|
190
|
+
it "should use default fields on creation" do
|
191
|
+
p = ProductProduct.new
|
192
|
+
p.sale_delay.should be_kind_of(Integer)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
describe "Basic updates" do
|
197
|
+
it "should cast properly from Ruby to OpenERP" do
|
198
|
+
o = SaleOrder.find(1).copy()
|
199
|
+
o.date_order = 2.days.ago
|
200
|
+
o.save
|
201
|
+
end
|
202
|
+
|
203
|
+
it "should be able to reload resource" do
|
204
|
+
s = SaleOrder.find(1)
|
205
|
+
s.reload.should be_kind_of(SaleOrder)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
describe "Relations assignations" do
|
210
|
+
it "should be able to do product.taxes_id = [1,2]" do
|
211
|
+
p = ProductProduct.find(1)
|
212
|
+
p.taxes_id = [1, 2]
|
213
|
+
p.save
|
214
|
+
p.taxes_id[0].id.should == 1
|
215
|
+
p.taxes_id[1].id.should == 2
|
216
|
+
end
|
217
|
+
|
218
|
+
it "should be able to create one2many relations on the fly" do
|
219
|
+
so = SaleOrder.new
|
220
|
+
partner_id = ResPartner.search([['name', 'ilike', 'Agrolait']])[0]
|
221
|
+
so.on_change('onchange_partner_id', :partner_id, partner_id, partner_id) #auto-complete the address and other data based on the partner
|
222
|
+
so.order_line = [SaleOrderLine.new(:name => 'sl1', :product_id => 1, :price_unit => 21, :product_uom => 1), SaleOrderLine.new(:name => 'sl2', :product_id => 1, :price_unit => 21, :product_uom => 1)] #create one order line
|
223
|
+
so.save
|
224
|
+
so.amount_total.should == 42.0
|
225
|
+
end
|
226
|
+
|
227
|
+
it "should be able to assign a polymorphic relation" do
|
228
|
+
#TODO implement!
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
describe "Old wizard management" do
|
233
|
+
it "should be possible to pay an invoice in one step" do
|
234
|
+
inv = AccountInvoice.find(1).copy() #creates a draft invoice
|
235
|
+
inv.state.should == "draft"
|
236
|
+
inv.wkf_action('invoice_open')
|
237
|
+
inv.state.should == "open"
|
238
|
+
wizard = inv.old_wizard_step('account.invoice.pay') #tip: you can inspect the wizard fields, arch and datas
|
239
|
+
inv = wizard.reconcile({:journal_id => 6, :name =>"from_rails"}) #if you want to pay all; will give you a reloaded invoice
|
240
|
+
inv.state.should == "paid"
|
241
|
+
end
|
242
|
+
|
243
|
+
it "should be possible to pay an invoice using an intermediary wizard step" do
|
244
|
+
inv = AccountInvoice.find(1).copy() #creates a draft invoice
|
245
|
+
inv.wkf_action('invoice_open')
|
246
|
+
wizard = inv.old_wizard_step('account.invoice.pay')
|
247
|
+
wizard.writeoff_check({"amount" => inv.amount_total - 1, "journal_id" => AccountJournal.search([['code', 'ilike', 'CHK']])[0], "name" =>'from_rails'}) #use the button name as the wizard method
|
248
|
+
inv = wizard.reconcile({:name => 'from_ooor', :writeoff_acc_id => 13, :writeoff_journal_id => AccountJournal.search([['code', 'ilike', 'EXJ']])[0], :journal_id => AccountJournal.search([['code', 'ilike', 'CHK']])[0]})
|
249
|
+
inv.state.should == "paid"
|
250
|
+
end
|
251
|
+
|
252
|
+
it "should be possible to call resource actions and workflow actions" do
|
253
|
+
s = SaleOrder.find(1).copy()
|
254
|
+
s.wkf_action('order_confirm')
|
255
|
+
s.wkf_action('manual_invoice')
|
256
|
+
i = s.invoice_ids[0]
|
257
|
+
i.journal_id.update_posted = true
|
258
|
+
i.journal_id.save
|
259
|
+
i.wkf_action('invoice_open')
|
260
|
+
i.wkf_action('invoice_cancel')
|
261
|
+
i.action_cancel_draft
|
262
|
+
s.reload.state.should == "invoice_except"
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
describe "New style wizards" do
|
267
|
+
#already tested, see database configuration test
|
268
|
+
end
|
269
|
+
|
270
|
+
describe "Delete resources" do
|
271
|
+
it "should be able to call unlink" do
|
272
|
+
ids = ProductProduct.search([['name', 'ilike', 'testProduct']])
|
273
|
+
ProductProduct.unlink(ids)
|
274
|
+
end
|
275
|
+
|
276
|
+
it "should be able to destroy loaded business objects" do
|
277
|
+
orders = SaleOrder.find(:all, :domain => [['origin', 'ilike', 'ooor_test']])
|
278
|
+
orders.each {|order| order.destroy}
|
279
|
+
|
280
|
+
invoices = AccountInvoice.find(:all, :domain => [['origin', 'ilike', 'ooor_test']])
|
281
|
+
invoices.each {|inv| inv.destroy}
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
end
|
286
|
+
|
287
|
+
|
288
|
+
describe "Offer Web Client core features" do
|
289
|
+
before(:all) do
|
290
|
+
@ooor = Ooor.new(:url => @url, :username => @username, :admin => @password, :database => @database,
|
291
|
+
:models => ['res.user', 'res.partner', 'product.product', 'sale.order', 'account.invoice', 'product.category', 'stock.move', 'ir.ui.menu'])
|
292
|
+
end
|
293
|
+
|
294
|
+
it "should find the default user action" do
|
295
|
+
@ooor.get_init_menu(1)
|
296
|
+
end
|
297
|
+
|
298
|
+
it "should be able to find the sub-menus of a menu" do
|
299
|
+
menu = IrUiMenu.find(:first, :domain => [['name', '=', 'Partners'], ['parent_id', '!=', false]])
|
300
|
+
menu.child_id.each do |sub_menu|
|
301
|
+
sub_menu.should be_kind_of(IrUiMenu)
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
it "should retrieve the action of a menu" do
|
306
|
+
IrUiMenu.find(:first, :domain => [['name', '=', 'Partners'], ['parent_id', '!=', false]]).action.should be_kind_of(IrActionsAct_window)
|
307
|
+
end
|
308
|
+
|
309
|
+
it "should be able to open a list view of a menu action" do
|
310
|
+
@ooor.menu_class.find(:first, :domain => [['name', '=', 'Partners'], ['parent_id', '!=', false]]).action.open('tree')
|
311
|
+
end
|
312
|
+
|
313
|
+
it "should be able to open a form view of a menu action" do
|
314
|
+
@ooor.menu_class.find(:first, :domain => [['name', '=', 'Partners'], ['parent_id', '!=', false]]).action.open('form', [1])
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
|
319
|
+
describe "UML features" do
|
320
|
+
before(:all) do
|
321
|
+
@ooor = Ooor.new(:url => @url, :username => @username, :admin => @password, :database => @database,
|
322
|
+
:models => ['res.user', 'res.partner', 'product.product', 'sale.order', 'account.invoice', 'product.category', 'stock.move', 'ir.ui.menu'])
|
323
|
+
end
|
324
|
+
|
325
|
+
it "should be able to draw the UML of any class" do
|
326
|
+
SaleOrder.print_uml.should be_true
|
327
|
+
end
|
328
|
+
|
329
|
+
it "should be able to draw the UML of several classes" do
|
330
|
+
UML.print_uml([SaleOrder, SaleShop]).should be_true
|
331
|
+
end
|
332
|
+
|
333
|
+
it "should accept rendering options" do
|
334
|
+
SaleOrder.print_uml(:all, :detailed).should be_true
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
|
339
|
+
describe "Multi-instance and class name scoping" do
|
340
|
+
before(:all) do
|
341
|
+
@ooor1 = Ooor.new(:url => @url, :username => @username, :admin => @password, :database => @database, :scope_prefix => 'OE1', :models => ['product.product'])
|
342
|
+
@ooor2 = Ooor.new(:url => @url, :username => @username, :admin => @password, :database => @database, :scope_prefix => 'OE2', :models => ['product.product'])
|
343
|
+
end
|
344
|
+
|
345
|
+
it "should still be possible to find a ressource using an absolute id" do
|
346
|
+
OE1::ProductProduct.find('product_product_pc1').should be_kind_of(OE1::ProductProduct)
|
347
|
+
end
|
348
|
+
|
349
|
+
it "should be able to read in one instance and write in an other" do
|
350
|
+
p1 = OE1::ProductProduct.find(1)
|
351
|
+
p2 = OE2::ProductProduct.create(:name => p1.name, :categ_id => p1.categ_id.id)
|
352
|
+
p2.should be_kind_of(OE2::ProductProduct)
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 1
|
7
7
|
- 3
|
8
|
-
-
|
9
|
-
version: 1.3.
|
8
|
+
- 1
|
9
|
+
version: 1.3.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Raphael Valyi - www.akretion.com
|
@@ -52,6 +52,7 @@ files:
|
|
52
52
|
- lib/app/ui/client_base.rb
|
53
53
|
- lib/app/ui/form_model.rb
|
54
54
|
- lib/app/ui/menu.rb
|
55
|
+
- spec/ooor_spec.rb
|
55
56
|
has_rdoc: true
|
56
57
|
homepage: http://github.com/rvalyi/ooor
|
57
58
|
licenses: []
|