reworked dividend
[smr.git] / gui / test / integration / demo1_user_session_test.rb
blob40709e6f70865bffc68ad7f11b35e3dc1de0f675
2 # This file is part of SMR.
4 # SMR is free software: you can redistribute it and/or modify it under the
5 # terms of the GNU General Public License as published by the Free Software
6 # Foundation, either version 3 of the License, or (at your option) any later
7 # version.
9 # SMR is distributed in the hope that it will be useful, but WITHOUT ANY
10 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License along with
14 # SMR.  If not, see <http://www.gnu.org/licenses/>.
16 require 'test_helper'
17 require 'digest/sha1'
18         
19 module Smr  #:nodoc:
20     ##
21     # typical user session involving interaction with multiple controllers by doing
22     # 'every day work'.
23     #
24     # HINT: regarding path methods, see
25     # http://stackoverflow.com/questions/5345757/in-rails-how-to-see-all-the-path-and-url-methods-added-by-railss-routing#5346350
26     class Demo1UserSessionTest < ActionDispatch::IntegrationTest
27         LOGIN = 'demo1'
28         PASSWORD = 'demo'
29     
30         ##
31         # try to login as demo1 user
32         test "login as demo1" do
33             # see if it takes us to the login page
34             get root_path
35             assert_response :redirect, 'accessing / should redirect to /login'
36             follow_redirect!
37             assert_response :success
38             assert_equal login_path, path
39            
40             smr_login(LOGIN, PASSWORD)
41         end
42     
43         ##
44         # try to list documents, upload one, download it again, delete it
45         test "work with documents" do
46             smr_login(LOGIN, PASSWORD)
47     
48             get documents_path
49             assert_response :success
50             assert_not_nil assigns(:portfolios)
51             assert_not_nil assigns(:document)
52             assert_not_nil docs = assigns(:documents)
53             assert docs.is_a?(UploadedFiles) 
54             assert docs.empty?
55     
56             upload_file = fixture_file_upload('quote.yml', 'text/plain')
57             upload_sha1 = Digest::SHA1.hexdigest(upload_file.read)
58     
59             # upload
60             post documents_path,
61                 {:action=>'create', :document=>{:comment=>'IntegrationTest', :content=>upload_file}, :id_portfolio=>'' },
62                 {:html=>{:multipart=>true}, :referer=>documents_path }
63             assert_response :redirect
64             follow_redirect!
65             assert_not_nil docs = assigns(:documents), 'no document shown after upload'
66             assert docs.is_a?(UploadedFiles) 
67             assert_not docs.empty?
68             assert d = docs.each.first
69             assert d.is_a?(UploadedFile)
70     
71             # download nothing
72             get download_path, {}, {'HTTP_REFERER'=>documents_path}
73             assert_redirected_to documents_path
74     
75             # download what we uploaded
76             get download_path, {:id=>d.id}, {'HTTP_REFERER'=>documents_path}
77             assert_equal @response.content_type, 'text/plain'
78             assert_equal Digest::SHA1.hexdigest(@response.body), upload_sha1
79     
80             # delete what we uploaded
81             get delete_document_path, {:id=>d.id}, {'HTTP_REFERER'=>documents_path}
82             assert_redirected_to documents_path
83         end
84     
85         ##
86         # view a open position
87         test "view open position" do
88             smr_login(LOGIN, PASSWORD)
89     
90             # take second position from asset listing
91             assert_not_nil asset_position_entry = assigns(:open_positions).second
92             assert asset_position_entry.is_a?(AssetPosition)
93             get position_path(:id=>asset_position_entry.id)
94             assert_response :success
95             assert_equal position_path, path
96             assert_not_nil p = assigns(:position)
97             assert p.is_a?(AssetPosition)
98     
99             # position should be open since we took it from open_positions
100             assert_not p.is_closed?
101             assert_not p.is_new?
102             assert p.invested.is_a?(Float)
103             assert (p.market_value.is_a?(Float) and p.market_value>0.0)
104             assert p.profit_loss.is_a?(Float)
105             assert p.dividend.received
106             assert (p.charges.is_a?(Float) and p.charges >= 0.0)
107             assert p.gain.is_a?(Float)
108     
109             # it must have at least one revision since its open but not new
110             assert_not_nil first_revision = p.revisions.first
111             assert first_revision.is_a?(PositionRevision)
112             assert first_revision.Order.is_a?(Order)
113             assert_not_equal first_revision.shares, 0.0
116             get position_path(:id=>30)
117             assert_redirected_to root_path, 'no redirect when using position_controller with cash position'
118         end
119     
120         ##
121         # issue and cancel orders on existing position
122         #
123         test "issue orders on existing position" do
124             smr_login(LOGIN, PASSWORD)
125     
126             get new_position_path
127             assert :success
128     
129             # the form should offer option 3: new order in portfolio OR new order
130             # on existing position
131             assert_not assigns(:position)
132             assert_not assigns(:portfolio)
133             assert open_positions = assigns(:open_positions)
134             assert stocks = assigns(:stocks)
135             assert portfolios = assigns(:portfolios)
136     
137             # issue new order on existing open position
138             marker_order1=Digest::SHA1.hexdigest(Time.now.to_s)
139             post position_index_path(:id_position=>open_positions.first.id),
140                 { :action=>'create',
141                   :order_issued=>Time.now, :order_expire=>Time.now+2.days,
142                   :order=>{ :shares=>100, :limit=>6.66, :provision=>1.11,
143                             :expense=>2.22, :courtage=>0.0,
144                             :comment=>marker_order1}
145                 },
146                 {:html=>{:multipart=>true}, :referer=>position_path(:id=>open_positions.first.id) }
147             assert :success
148     
149             get position_path(:id=>open_positions.first.id)
150             assert :success
151             assert p = assigns(:position)
152             assigns p.is_a?(AssetPosition)
153             assert p.has_pending_orders?
154             neworder1 = p.pending_orders.where(:comment=>marker_order1).first
155             assert neworder1.is_a?(Order), 'issued order not found in pending state, got: %s' % neworder1.inspect
156             
157             # issue and execute new order in one step
158             marker_order2=Digest::SHA1.hexdigest(Time.now.to_s)
159             post position_index_path(:id_position=>open_positions.first.id),
160                 { :action=>'create',
161                   :execute_now=>1, :execute_quote=>7.76, :execute_time=>Time.now+2.hours,
162                   :order_issued=>Time.now, :order_expire=>Time.now+2.days,
163                   :order=>{ :shares=>200, :limit=>7.77, :provision=>0.00,
164                             :expense=>0.001, :courtage=>3.33,
165                             :comment=>marker_order2}
166                 },
167                 {:html=>{:multipart=>true}, :referer=>position_path }
168             assert :success
169     
170             get position_path(:id=>open_positions.first.id)
171             assert :success
172             assert p_after_execute = assigns(:position)
173             assigns p_after_execute.is_a?(AssetPosition)
174     
175             assert p_after_execute.revisions.any? {|r| r.Order.comment == marker_order2},
176                 'executed new order did not create new revision'
177     
178             # check whether executing changed number of shares, invested, etc... in
179             # position ... and.... well... it should be correctly calculated
180             assert_equal p.shares + 200, p_after_execute.shares,
181                 'wrong number of shares in position after order execute'
182             assert_equal p.invested + 200*7.76, p_after_execute.invested,
183                 'wrong invested amount in position after order execute'
184             assert_equal p.charges + 0.001 + 3.33, p_after_execute.charges,
185                 'wrong charges in position after order execute'
186     
187             # cancel issued neworder1
188             post cancel_order_path,
189                 { :action=>'cancel_order', :id_order=>neworder1.id},
190                 {:html=>{:multipart=>true}, :referer=>position_path(:id=>p.id) }
191             assert_redirected_to position_path(:id=>p.id)
192             follow_redirect!
193             assert p_after_cancel = assigns(:position)
194             assigns p_after_cancel.is_a?(AssetPosition)
195             assert_nil p_after_cancel.pending_orders.where(:comment=>marker_order1).first,
196                 'failed to cancel pending order'
197         end 
198     
199         ##
200         # utilize a cash position: view, make booking
201         test "work with cash position" do
202             smr_login(LOGIN, PASSWORD)
204             get cashposition_path(:id=>15)
205             assert_redirected_to root_path, 'no redirect when using cashposition_controller with regular position'
207             get cashposition_path(:id=>30)
208             assert_response :success
209             assert_equal cashposition_path(:id=>30), path
211             assert_not_nil cp = assigns(:position)
212             assert cp.is_a?(Smr::AssetPosition)
213             assert cp.is_cash_position?
214             assert_equal -4656, cp.invested, 'wrong balance of cash account'
216             # make booking: one deposit, one withdrawal, re-test balance
217             booking_data = { :id_cashposition=>30, :amount=>100, :date=>'2015-03-25', :comment=>'booking deposit test' }
218             post(cashposition_index_path(:id=>30),
219                 {:action=>'create', :booking=>booking_data},
220                 {:referer=>cashposition_path(:id=>30) }
221             )
222             follow_redirect!
223             assert_equal cashposition_path(:id=>30), path
224             assert_not_nil cp = assigns(:position)
225             assert_equal -4556, cp.invested, 'wrong balance after booking deposit'
227             booking_data = { :id_cashposition=>30, :amount=>-1000, :date=>'2015-03-26', :comment=>'booking withdrawal test' }
228             post(cashposition_index_path(:id=>30),
229                 {:action=>'create', :booking=>booking_data},
230                 {:referer=>cashposition_path(:id=>30) }
231             )
232             follow_redirect!
233             assert_equal cashposition_path(:id=>30), path
234             assert_not_nil cp = assigns(:position)
235             assert_equal -5556, cp.invested, 'wrong balance after booking withdrawal'
236         end
238         ##
239         # view cashflows from dividends and orders
240         test "view cashflow" do
241             smr_login(LOGIN, PASSWORD)
242     
243             get cashflow_index_path
244             assert_response :success
245             assert_equal cashflow_index_path, path
246             assert_not_nil cflog = assigns(:log)
247             assert cflog.is_a?(CashflowLog)
248     
249             cflog.each do |i|
250                 assert i.is_a?(CashflowLogItem)
251             end
252         end
253     
254         ##
255         # view and add FigureData
256         test "work with figure data" do
257             smr_login(LOGIN, PASSWORD)
258     
259             get figures_path
260             assert_response :success
261             assert_equal figures_path, path
262             assert assigns(:securities).is_a?(Array)
263             assert assigns(:selected_security).is_a?(Stock)
264             assert assigns(:have_data).is_a?(FalseClass)
265     
266             # select a security that has figure data
267             get figures_path, {:id_stock=>25, :show=>'this'}
268             assert_response :success
269             assert assigns(:have_data).is_a?(TrueClass)
270             assert assigns(:datatable).render  # Raises if no data
271     
272             # add new FigureData
273             # - no fixtures on BASF AG, therefore nothing should be shown at first
274             #   and then only FigureData we added from here
275             figure_data = {
276                 :id=>0,             # new
277                 :id_stock=>15,      # BASF AG
278                 :id_figure_var=>4,  # Demo1Var1
279                 :period=>'year', :time=>1.days.ago.strftime('%Y-%m-%d'),
280                 :analyst=>'integration test', :value=>1.23, :is_expected=>1,
281                 :is_audited=>1, :comment=>'made by demo1 integration test'
282             }
283     
284             get new_figure_path, :id_stock=>figure_data[:id_stock], :show=>'this'
285             assert_response :success
286             assert assigns(:figuredata).is_a?(FigureData)
287             assert assigns(:have_data).is_a?(FalseClass)
288             post(figures_path, 
289                 {:action=>'create', :figure_data=>figure_data},
290                 {:referer=>figures_path}
291             )
292             follow_redirect!
293             assert_equal figures_path, path
294             assert assigns(:selected_security).is_a?(Stock)
295             assert_equal assigns(:selected_security).id, figure_data[:id_stock]
296             assert assigns(:have_data).is_a?(TrueClass)
297     
298             # try again, but store FigureData on a FigureVar that belongs to
299             # another user
300             # note: thats something the Gui does not allow to do
301             figure_data[:id_figure_var] = 1  # FirstVar, belongs :id_user=1 (admin)
302             figure_data[:id_stock] = 6       # CocaCola Inc.
303             get new_figure_path, :id_stock=>figure_data[:id_stock], :show=>'this'
304             assert_response :success
305             assert assigns(:have_data).is_a?(FalseClass)
306             post(figures_path, 
307                 {:action=>'create', :figure_data=>figure_data},
308                 {:referer=>figures_path}
309             )
310             follow_redirect!
311             assert assigns(:have_data).is_a?(FalseClass)
312         end
313     
314         ##
315         # use the personal blog
316         test "read and blog articles" do
317             smr_login(LOGIN, PASSWORD)
318     
319             get blog_path
320             assert_response :success
321             assert_equal blog_path, path
322             assert_not_nil blog = assigns(:blogroll)
323             assert blog.is_a?(Blog)
324             assert blog.empty?
325     
326             # blog new article
327             get new_blog_path
328             assert_response :success
329             assert_equal new_blog_path, path
330             assert_not_nil article = assigns(:article)
331             assert article.is_a?(Comment)
332             post blog_path,
333                 {:action=>'create', :comment=>{:title=>'IntegrationTest Title', :comment=>'IntegrationTest Text'} },
334                 {:referer=>blog_path }
335             follow_redirect!
336             assert_equal blog_path, path
337             assert_not_nil blog = assigns(:blogroll)
338             assert blog.is_a?(Blog)
339             assert_not blog.empty?
340             item = blog.each.first
341             assert item.is_a?(BlogItem)
342             assert_equal 'Comment', item.type
343             assert_equal 'IntegrationTest Title', item.title
344             assert_equal 'IntegrationTest Text', item.body
345         end
347         ##
348         # use quote records
349         test "work with quoterecords" do
350             smr_login(LOGIN, PASSWORD)
351     
352             get quoterecords_path
353             assert_response :success
355             # get quoterecords on E.On AG (there should not be any) for 2007-08-07
356             post set_session_params_path,
357                 {:smr_browse_date=>{:day=>7, :month=>8, :year=>2007}},
358                 {:referer=>quoterecords_path}
359             follow_redirect!
360             get quoterecords_path, { :id_stock=>25, :show=>'this' }
361             assert_response :success
362             assert assigns(:selected_security).is_a?(Stock)
363             assert_equal 25, assigns(:selected_security).id
365             assert_not_nil quote = assigns(:intraday_quotes).first
366             assert quote.is_a?(Quote)
368             # post a new quoterecord from :intraday_quotes observations
369             marker_qr=Digest::SHA1.hexdigest(Time.now.to_s)
370             post quoterecords_path,
371                 {:action=>'create',
372                   :quoterecord => {
373                     :id=>'', :id_stock=>quote.id_stock, :id_quote=>quote.id,
374                     :column=>'upward', :comment=>marker_qr,
375                     :is_pivotal_point=>0, :is_uphit=>0, :is_downhit=>0, :is_signal=>0
376                   },
377                   :commit=>'record this one'
378                 },
379                 {:referer=>quoterecords_path}
380             assert_response :success
381             assert_equal quoterecords_path, path
383             # now we should see that one listed in previous records
384             assert_not_nil qrs = assigns(:quoterecords)
385             assert qrs.is_a?(Smr::Quoterecords)
386             qr = qrs.first
387             assert_equal qr.comment, marker_qr
388             assert_equal qr.column, 'upward'
390             # edit that record
391             get quoterecord_path(:id=>qr.id)
392             assert_response :success
393             assert_not_nil qr_edit = assigns(:quoterecord)
394             assert_equal qr_edit.comment, qr.comment
395             marker_qr_edit=Digest::SHA1.hexdigest(marker_qr + Time.now.to_s)
396             post quoterecords_path,
397                 {:action=>'create',
398                   :quoterecord => {
399                     :id=>qr_edit.id, :column=>'downward', :comment=>marker_qr_edit,
400                     :is_pivotal_point=>0, :is_uphit=>0, :is_downhit=>0, :is_signal=>0
401                   },
402                   :commit=>'record this one'
403                 },
404                 {:referer=>quoterecords_path}
405             assert_response :success
406             assert_not_nil qrs_edited = assigns(:quoterecords)
407             assert_equal qrs_edited.first.comment, marker_qr_edit
408         end
410         ##
411         # record rules on quoterecords
412         test "work with quoterecord rules" do
413             smr_login(LOGIN, PASSWORD)
414     
415             get quoterecord_rules_path
416             assert_response :success
417             assert assigns(:rules).empty?
419             # make new rule
420             marker_rule1=Digest::SHA1.hexdigest('obey!' + Time.now.to_s)
421             get new_quoterecord_rule_path
422             assert_response :success
423             post quoterecord_rules_path,
424                 {   :action=>'create',
425                     :quoterecord_rule=>{:id=>'', :order=>1, :name=>'rule1', :rule=>marker_rule1},
426                     :related_columns=>['secondary_rally', 'downward'],
427                     :commit=>'Save Rule'
428                 },
429                 {:referer=>new_quoterecord_rule_path}
430             follow_redirect!
431             assert_response :success
432             rules = assigns(:rules)
433             assert_not rules.empty?, 'we should have a rule by now'
434             assert_equal rules.first.name, 'rule1'
435             assert_equal rules.first.rule, marker_rule1
436             assert rules.first.get_related_columns.include?('downward'), 'column not related to new rule'
438             # edit our rule
439             marker_edited=Digest::SHA1.hexdigest('I said obey!' + Time.now.to_s)
440             get new_quoterecord_rule_path, :id=>rules.first.id
441             assert_not_nil edit_rule = assigns(:rule)
442             assert_equal edit_rule.rule, marker_rule1
443             post quoterecord_rules_path,
444                 {   :action=>'create',
445                     :quoterecord_rule=>{:id=>edit_rule.id, :order=>1, :name=>edit_rule.name, :rule=>marker_edited},
446                     :related_columns=>['secondary_reaction', 'upward'],
447                     :commit=>'Save Rule'
448                 },
449                 {:referer=>new_quoterecord_rule_path}
450             follow_redirect!
451             assert_response :success
452             assert_not_nil edited_rule = assigns(:rules).first
453             assert_equal edited_rule.name, 'rule1'
454             assert_equal edited_rule.rule, marker_edited
455             assert edited_rule.get_related_columns.include?('upward'), 'edited column relation not present'
457         end
458     end
460 end # module