source: main/waeup.fceokene/trunk/src/waeup/fceokene/interswitch/tests.py @ 13557

Last change on this file since 13557 was 13459, checked in by Henrik Bettermann, 9 years ago

Adjust to changes in base package.

  • Property svn:keywords set to Id
File size: 22.7 KB
Line 
1## $Id: tests.py 13459 2015-11-16 09:08:11Z henrik $
2##
3## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18import os
19from datetime import datetime, timedelta, date
20from zope.component import getUtility
21from zope.catalog.interfaces import ICatalog
22from hurry.workflow.interfaces import IWorkflowState
23from waeup.kofa.students.tests.test_browser import StudentsFullSetup
24from waeup.kofa.applicants.tests.test_browser import ApplicantsFullSetup
25from waeup.kofa.configuration import SessionConfiguration
26from waeup.fceokene.testing import FunctionalLayer
27
28# Also run tests that send requests to external servers?
29#   If you enable this, please make sure the external services
30#   do exist really and are not bothered by being spammed by a test programme.
31EXTERNAL_TESTS = False
32
33def external_test(func):
34    if not EXTERNAL_TESTS:
35        myself = __file__
36        if myself.endswith('.pyc'):
37            myself = myself[:-2]
38        print "WARNING: external tests are skipped!"
39        print "WARNING: edit %s to enable them." % myself
40        return
41    return func
42
43
44class InterswitchTestsStudents(StudentsFullSetup):
45    """Tests for the Interswitch payment gateway.
46    """
47
48    layer = FunctionalLayer
49
50    def setUp(self):
51        super(InterswitchTestsStudents, self).setUp()
52        self.certificate.study_mode = 'pd_ft'
53        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
54        self.browser.open(self.payments_path)
55        IWorkflowState(self.student).setState('cleared')
56        self.browser.open(self.payments_path + '/addop')
57        self.browser.getControl(name="form.p_category").value = ['schoolfee']
58        self.browser.getControl("Create ticket").click()
59        self.assertMatches('...ticket created...',
60                           self.browser.contents)
61        ctrl = self.browser.getControl(name='val_id')
62        self.value = ctrl.options[0]
63        self.browser.getLink(self.value).click()
64        self.assertMatches('...Amount Authorized...',
65                           self.browser.contents)
66        self.assertTrue(
67            '<span>70450.0</span>' in self.browser.contents)
68        self.payment_url = self.browser.url
69        self.payment = self.student['payments'][self.value]
70
71
72#    def callback_url(self, payment_url, resp, apprAmt):
73#        return payment_url + (
74#            '/isw_callback?echo=' +
75#            '&resp=%s' +
76#            '&desc=Something went wrong' +
77#            '&txnRef=p1331792385335' +
78#            '&payRef=' + '&retRef=' +
79#            '&cardNum=0' +
80#            '&apprAmt=%s' +
81#            '&url=http://xyz') % (resp, apprAmt)
82
83    def test_interswitch_form(self):
84
85        self.assertEqual(self.student['payments'][self.value].provider_amt, 0.0)
86        self.assertEqual(self.student['payments'][self.value].gateway_amt, 0.0)
87        self.assertEqual(self.student['payments'][self.value].thirdparty_amt, 0.0)
88        # Manager can access InterswitchForm for the created school fee ticket
89        self.browser.getLink("CollegePAY", index=0).click()
90        # Split amounts have been set
91        self.assertEqual(self.student['payments'][self.value].provider_amt, 1600.0)
92        self.assertEqual(self.student['payments'][self.value].gateway_amt, 150.0)
93        self.assertEqual(self.student['payments'][self.value].thirdparty_amt, 1400.0)
94        self.assertMatches('...Total Amount Authorized:...',
95                           self.browser.contents)
96        self.assertTrue(
97            '<input type="hidden" name="amount" value="7045000" />'
98            in self.browser.contents)
99        self.assertTrue(
100            'item_name="School Fee" item_amt="6730000" bank_id="117" acct_num="1013780934"'
101            in self.browser.contents)
102        self.assertTrue(
103            'item_name="FCEOkene Split" item_amt="140000" bank_id="117" acct_num="1013780934"'
104            in self.browser.contents)
105        self.assertTrue(
106            'item_name="BT Education" item_amt="160000" bank_id="31" acct_num="0026781725"'
107            in self.browser.contents)
108
109        # Third semester payment
110        self.certificate.study_mode = 'nce_ft'
111        self.app['configuration']['2004'].third_semester_fee = 10000.0
112        self.browser.open(self.payments_path)
113        self.browser.open(self.payments_path + '/addop')
114        self.browser.getControl(
115            name="form.p_category").value = ['third_semester']
116        self.browser.getControl("Create ticket").click()
117        ctrl = self.browser.getControl(name='val_id')
118        value = ctrl.options[1]
119        self.browser.getLink(value).click()
120        self.browser.getLink("CollegePAY", index=0).click()
121        self.assertTrue(
122            '<input type="hidden" name="amount" value="791300" />'
123            in self.browser.contents)
124        self.assertTrue(
125            'item_name="NCE Third Semester Fee" item_amt="476300" bank_id="117" acct_num="1013780934"'
126            in self.browser.contents)
127        self.assertTrue(
128            'item_name="FCEOkene Split" item_amt="140000" bank_id="117" acct_num="1013780934"'
129            in self.browser.contents)
130        self.assertTrue(
131            'item_name="BT Education" item_amt="160000" bank_id="31" acct_num="0026781725"'
132            in self.browser.contents)
133
134        # Maintenance fee payment
135        self.certificate.study_mode = 'nce_ft'
136        self.browser.open(self.payments_path)
137        self.browser.open(self.payments_path + '/addop')
138        self.browser.getControl(
139            name="form.p_category").value = ['hostel_maintenance']
140        self.browser.getControl("Create ticket").click()
141        self.assertMatches('...You have not yet booked accommodation...',
142                           self.browser.contents)
143        # Students have to book bed first
144        self.browser.open(self.acco_path)
145        IWorkflowState(self.student).setState('admitted')
146        self.browser.getControl("Book accommodation").click()
147        self.assertFalse('Activation Code:' in self.browser.contents)
148        self.browser.getControl("Create bed ticket").click()
149        # Bed is randomly selected but, since there is only
150        # one bed for this student, we know that ...
151        self.assertFalse('Hall 1, Block A, Room 101, Bed A'
152                           in self.browser.contents)
153        self.assertTrue('(see payment slip)'
154                           in self.browser.contents)
155        self.assertTrue('ticket created'
156                           in self.browser.contents)
157        self.browser.open(self.payments_path + '/addop')
158        self.browser.getControl(
159            name="form.p_category").value = ['hostel_maintenance']
160        self.browser.getControl("Create ticket").click()
161        self.assertMatches('...ticket created...',
162                           self.browser.contents)
163        ctrl = self.browser.getControl(name='val_id')
164        value = ctrl.options[2]
165        self.browser.getLink(value).click()
166        self.assertMatches('...Amount Authorized...',
167                           self.browser.contents)
168        self.assertTrue(
169            '<span>4150.0</span>' in self.browser.contents)
170        # p_item is not unveiled
171        self.assertFalse('Hall 1, Block A, Room 101, Bed A'
172            in self.browser.contents)
173        self.assertTrue('(visible after successful payment)'
174            in self.browser.contents)
175        self.payment_url = self.browser.url
176        self.assertEqual(self.student['payments'][value].provider_amt, 0.0)
177        self.assertEqual(self.student['payments'][value].gateway_amt, 0.0)
178        self.assertEqual(self.student['payments'][value].thirdparty_amt, 0.0)
179        # Manager can access InterswitchForm
180        self.browser.getLink("CollegePAY", index=0).click()
181        # Split amounts have been set
182        self.assertEqual(self.student['payments'][value].provider_amt, 0.0)
183        self.assertEqual(self.student['payments'][value].gateway_amt, 150.0)
184        self.assertEqual(self.student['payments'][value].thirdparty_amt, 0.0)
185        # The total amount to be processed by Interswitch
186        # has been reduced by the Interswitch fee of 150 Nairas
187        self.assertMatches('...Total Amount Authorized:...',
188                           self.browser.contents)
189        self.assertTrue(
190            '<input type="hidden" name="amount" value="415000" />'
191            in self.browser.contents)
192        self.assertTrue(
193            'item_name="Hostel Maintenance Fee" item_amt="400000" bank_id="117" acct_num="1013780934"'
194            in self.browser.contents)
195        # BT does nor charge a fee for maintenance fee
196        self.assertFalse("BT Education" in self.browser.contents)
197        # p_item is not unveiled
198        self.assertFalse('Hall 1, Block A, Room 101, Bed A'
199            in self.browser.contents)
200        self.assertTrue('(visible after successful payment)'
201            in self.browser.contents)
202        # If the ticket is paid coordinates are shown
203        self.student['payments'][value].p_state = 'paid'
204        self.browser.open(self.payment_url)
205        self.assertTrue('Hall 1, Block A, Room 101, Bed A'
206            in self.browser.contents)
207        self.assertFalse('(visible after successful payment)'
208            in self.browser.contents)
209
210        # Acceptance fee payment
211
212        self.browser.open(self.payments_path)
213        self.browser.open(self.payments_path + '/addop')
214        self.browser.getControl(
215            name="form.p_category").value = ['clearance']
216        self.browser.getControl("Create ticket").click()
217        self.assertMatches('...ticket created...',
218                           self.browser.contents)
219        ctrl = self.browser.getControl(name='val_id')
220        value = ctrl.options[3]
221        self.browser.getLink(value).click()
222        self.assertMatches('...Amount Authorized...',
223                           self.browser.contents)
224        self.assertTrue(
225            '<span>3606.0</span>' in self.browser.contents)
226        self.payment_url = self.browser.url
227        self.assertEqual(self.student['payments'][value].provider_amt, 0.0)
228        self.assertEqual(self.student['payments'][value].gateway_amt, 0.0)
229        self.assertEqual(self.student['payments'][value].thirdparty_amt, 0.0)
230        # Manager can access InterswitchForm
231        self.browser.getLink("CollegePAY", index=0).click()
232        # Split amounts have been set
233        self.assertEqual(self.student['payments'][value].provider_amt, 0.0)
234        self.assertEqual(self.student['payments'][value].gateway_amt, 150.0)
235        self.assertEqual(self.student['payments'][value].thirdparty_amt, 0.0)
236        # The total amount to be processed by Interswitch
237        # has been reduced by the Interswitch fee of 150 Nairas
238        self.assertMatches('...Total Amount Authorized:...',
239                           self.browser.contents)
240        self.assertTrue(
241            '<input type="hidden" name="amount" value="360600" />' in
242            self.browser.contents)
243        self.assertTrue(
244            'item_name="Acceptance Fee" item_amt="345600" bank_id="8" acct_num="2010952698"'
245            in self.browser.contents)
246        # BT does nor charge a fee for maintenance fee
247        self.assertFalse("BT Education" in self.browser.contents)
248
249    def test_interswitch_form_ticket_expired(self):
250        # Manager can access InterswitchForm
251        self.browser.getLink("CollegePAY", index=0).click()
252        self.assertMatches('...<input type="hidden" name="pay_item_id" value="8302" />...',
253                           self.browser.contents)
254        self.assertMatches('...Total Amount Authorized:...',
255                           self.browser.contents)
256        self.assertEqual(self.student.current_mode, 'pd_ft')
257        self.assertMatches(
258            '...<input type="hidden" name="amount" value="4000000" />...',
259            self.browser.contents)
260        delta = timedelta(days=8)
261        self.payment.creation_date -= delta
262        self.browser.open(self.payment_url)
263        self.browser.getLink("CollegePAY", index=0).click()
264        self.assertMatches(
265            '...This payment ticket is too old. Please create a new ticket...',
266            self.browser.contents)
267        delta = timedelta(days=2)
268        self.payment.creation_date += delta
269        self.browser.open(self.payment_url)
270        self.browser.getLink("CollegePAY", index=0).click()
271        self.assertMatches('...Total Amount Authorized:...',
272                           self.browser.contents)
273
274#    @external_test
275#    def test_callback(self):
276
277        # Manager can call callback manually
278#        self.browser.open(self.callback_url(self.payment_url, 'XX', '300'))
279#        self.assertMatches('...Unsuccessful callback: Something went wrong...',
280#                          self.browser.contents)
281#        self.assertMatches('...Failed...',
282#                           self.browser.contents)
283#        self.browser.open(self.payment_url + '/isw_callback')
284#        self.assertMatches('...Unsuccessful callback: Incomplete query string...',
285#                          self.browser.contents)
286#        self.assertMatches('...Failed...',
287#                           self.browser.contents)
288#        self.browser.open(self.callback_url(self.payment_url, '00', '300000'))
289#        self.assertMatches('...Wrong amount...',
290#                          self.browser.contents)
291#        self.browser.open(self.callback_url(self.payment_url, '00', '4000000'))
292#        self.assertMatches('...Valid callback received...',
293#                          self.browser.contents)
294
295    @external_test
296    def test_webservice(self):
297        # First we have open InterswitchPageStudent to set provider_amt
298        # and gateway_amt
299        self.browser.open(self.payment_url + '/goto_interswitch')
300        # Now we can call the webservice
301        self.browser.open(self.payment_url + '/request_webservice')
302        #self.assertMatches('...Unsuccessful callback...',
303        #                  self.browser.contents)
304        self.assertMatches('...Unsuccessful callback...',
305                          self.browser.contents)
306        # The payment is now in state failed ...
307        self.assertMatches('...<span>Failed</span>...',
308                          self.browser.contents)
309        # ... and the catalog has been updated
310        cat = getUtility(ICatalog, name='payments_catalog')
311        results = list(
312            cat.searchResults(p_state=('failed', 'failed')))
313        self.assertEqual(len(results), 1)
314        self.assertEqual(results[0].p_state, 'failed')
315
316        # Let's replace the p_id with a valid p_id of the FCEOkene
317        # live system. This is definitely not an appropriate
318        # solution for testing, but we have no choice since
319        # Interswitch doesn't provide any interface
320        # for testing.
321        payment = self.student['payments'][self.value]
322        payment.p_id = 'p3536651296379'
323        self.browser.open(self.payment_url + '/request_webservice')
324        self.assertMatches('...Callback amount does not match...',
325                          self.browser.contents)
326        # The payment is now in state failed ...
327        self.assertMatches('...<span>Failed</span>...',
328                          self.browser.contents)
329        # Let's replace the amount autorized with the amount of the
330        # live system payment
331        payment.amount_auth = payment.r_amount_approved
332        self.browser.open(self.payment_url + '/request_webservice')
333        self.assertMatches('...Successful payment...',
334                          self.browser.contents)
335        # The payment is now in state paid ...
336        self.assertMatches('...<span>Paid</span>...',
337                          self.browser.contents)
338        # ... and the catalog has been updated
339        cat = getUtility(ICatalog, name='payments_catalog')
340        results = list(
341            cat.searchResults(p_state=('paid', 'paid')))
342        self.assertEqual(len(results), 1)
343        self.assertEqual(results[0].p_state, 'paid')
344        # Approval is logged in students.log ...
345        logfile = os.path.join(
346            self.app['datacenter'].storage, 'logs', 'students.log')
347        logcontent = open(logfile).read()
348        self.assertTrue(
349            'zope.mgr - '
350            'waeup.fceokene.interswitch.browser.CustomInterswitchPaymentRequestWebservicePageStudent - '
351            'K1000000 - successful schoolfee payment: p3536651296379\n'
352            in logcontent)
353        # ... and in payments.log
354        logfile = os.path.join(
355            self.app['datacenter'].storage, 'logs', 'payments.log')
356        logcontent = open(logfile).read()
357        self.assertTrue(
358            '"zope.mgr",K1000000,p3536651296379,schoolfee,'
359            '3150.0,00,1600.0,150.0,1400.0,,,\n'
360            in logcontent)
361
362class InterswitchTestsApplicants(ApplicantsFullSetup):
363    """Tests for the Interswitch payment gateway.
364    """
365
366    layer = FunctionalLayer
367
368    def setUp(self):
369        super(InterswitchTestsApplicants, self).setUp()
370        configuration = SessionConfiguration()
371        configuration.academic_session = datetime.now().year - 2
372        self.app['configuration'].addSessionConfiguration(configuration)
373        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
374        self.browser.open(self.manage_path)
375        #IWorkflowState(self.student).setState('started')
376        super(InterswitchTestsApplicants, self).fill_correct_values()
377        self.applicantscontainer.application_fee = 1000.0
378        self.browser.getControl(name="form.nationality").value = ['NG']
379        self.browser.getControl(name="transition").value = ['start']
380        self.browser.getControl("Save").click()
381
382    def test_interswitch_form(self):
383        self.browser.getControl("Add online").click()
384        self.assertMatches('...ticket created...',
385                           self.browser.contents)
386        self.assertMatches(
387            '...<span>1000.0</span>...',
388            self.browser.contents)
389        self.payment_url = self.browser.url
390        self.browser.open(self.manage_path)
391        ctrl = self.browser.getControl(name='val_id')
392        self.value = ctrl.options[0]
393        # Manager can access InterswitchForm
394        self.browser.open(self.payment_url)
395        self.browser.getLink("CollegePAY", index=0).click()
396        self.assertMatches('...Total Amount Authorized:...',
397                           self.browser.contents)
398        self.assertTrue(
399            '<input type="hidden" name="amount" value="100000" />'
400            in self.browser.contents)
401        self.assertTrue(
402            '<item_detail item_id="1" item_name="application"'
403            ' item_amt="35000" bank_id="117" acct_num="1013780934" />'
404            in self.browser.contents)
405        delta = timedelta(days=8)
406        self.applicant[self.value].creation_date -= delta
407        self.browser.open(self.payment_url)
408        self.browser.getLink("CollegePAY", index=0).click()
409        self.assertMatches(
410            '...This payment ticket is too old. Please create a new ticket...',
411            self.browser.contents)
412
413    @external_test
414    def test_webservice(self):
415        self.browser.getControl("Add online").click()
416        self.assertMatches('...ticket created...',
417                           self.browser.contents)
418        self.assertMatches(
419            '...<span>1000.0</span>...',
420            self.browser.contents)
421        self.payment_url = self.browser.url
422        self.browser.open(self.manage_path)
423        ctrl = self.browser.getControl(name='val_id')
424        self.value = ctrl.options[0]
425        # First we have open InterswitchPageStudent to set provider_amt
426        # and gateway_amt
427        self.browser.open(self.payment_url + '/goto_interswitch')
428        # Now we can call the webservice
429        self.browser.open(self.payment_url + '/request_webservice')
430        self.assertMatches('...Unsuccessful callback...',
431                          self.browser.contents)
432        # The payment is now in state failed ...
433        self.assertMatches('...<span>Failed</span>...',
434                          self.browser.contents)
435        # ... and the catalog has been updated
436        cat = getUtility(ICatalog, name='payments_catalog')
437        results = list(
438            cat.searchResults(p_state=('failed', 'failed')))
439        self.assertEqual(len(results), 1)
440        self.assertEqual(results[0].p_state, 'failed')
441
442        # Let's replace the p_id with a valid p_id of the Uniben
443        # live system. This is definitely not an appropriate
444        # solution for testing, but we have no choice since
445        # Interswitch doesn't provide any interface
446        # for testing.
447        payment = self.applicant[self.value]
448        payment.p_id = 'p3536651296379'
449        self.browser.open(self.payment_url + '/request_webservice')
450        self.assertMatches('...Callback amount does not match...',
451                          self.browser.contents)
452        # The payment is now in state failed ...
453        self.assertMatches('...<span>Failed</span>...',
454                          self.browser.contents)
455        # Let's replace the amount autorized with the amount of the
456        # live system payment
457        payment.amount_auth = payment.r_amount_approved
458        self.browser.open(self.payment_url + '/request_webservice')
459        self.assertMatches('...Successful payment...',
460                          self.browser.contents)
461        # The payment is now in state paid ...
462        self.assertMatches('...<span>Paid</span>...',
463                          self.browser.contents)
464        # ... and the catalog has been updated
465        cat = getUtility(ICatalog, name='payments_catalog')
466        results = list(
467            cat.searchResults(p_state=('paid', 'paid')))
468        self.assertEqual(len(results), 1)
469        self.assertEqual(results[0].p_state, 'paid')
470        # Approval is logged in students.log ...
471        logfile = os.path.join(
472            self.app['datacenter'].storage, 'logs', 'applicants.log')
473        logcontent = open(logfile).read()
474        self.assertTrue(
475            'zope.mgr - '
476            'waeup.fceokene.interswitch.browser.CustomInterswitchPaymentRequestWebservicePageApplicant - '
477            '%s - successful payment: p3536651296379\n'
478            % self.applicant.applicant_id in logcontent)
479        # ... and in payments.log
480        logfile = os.path.join(
481            self.app['datacenter'].storage, 'logs', 'payments.log')
482        logcontent = open(logfile).read()
483        self.assertTrue(
484            '"zope.mgr",%s,p3536651296379,application,'
485            '3150.0,00,500.0,150.0,0.0,,,\n' % self.applicant.applicant_id
486            in logcontent)
Note: See TracBrowser for help on using the repository browser.