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

Last change on this file since 12982 was 12976, checked in by Henrik Bettermann, 10 years ago

Test if the ticket-expire mechanism works, for both applicant and student payments.

  • Property svn:keywords set to Id
File size: 22.7 KB
Line 
1## $Id: tests.py 12976 2015-05-21 17:36:58Z 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 = 'nce_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>14975.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="1497500" />'
98            in self.browser.contents)
99        self.assertTrue(
100            'item_name="School Fee" item_amt="1182500" 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.app['configuration']['2004'].third_semester_fee = 10000.0
111        self.browser.open(self.payments_path)
112        self.browser.open(self.payments_path + '/addop')
113        self.browser.getControl(
114            name="form.p_category").value = ['third_semester']
115        self.browser.getControl("Create ticket").click()
116        ctrl = self.browser.getControl(name='val_id')
117        value = ctrl.options[1]
118        self.browser.getLink(value).click()
119        self.browser.getLink("CollegePAY", index=0).click()
120        self.assertTrue(
121            '<input type="hidden" name="amount" value="791300" />'
122            in self.browser.contents)
123        self.assertTrue(
124            'item_name="NCE Third Semester Fee" item_amt="476300" bank_id="117" acct_num="1013780934"'
125            in self.browser.contents)
126        self.assertTrue(
127            'item_name="FCEOkene Split" item_amt="140000" bank_id="117" acct_num="1013780934"'
128            in self.browser.contents)
129        self.assertTrue(
130            'item_name="BT Education" item_amt="160000" bank_id="31" acct_num="0026781725"'
131            in self.browser.contents)
132
133        # Maintenance fee payment
134        self.certificate.study_mode = 'nce_ft'
135        self.browser.open(self.payments_path)
136        self.browser.open(self.payments_path + '/addop')
137        self.browser.getControl(
138            name="form.p_category").value = ['hostel_maintenance']
139        self.browser.getControl("Create ticket").click()
140        self.assertMatches('...You have not yet booked accommodation...',
141                           self.browser.contents)
142        # Students have to book bed first
143        self.browser.open(self.acco_path)
144        IWorkflowState(self.student).setState('admitted')
145        self.browser.getLink("Book accommodation").click()
146        self.assertFalse('Activation Code:' in self.browser.contents)
147        self.browser.getControl("Create bed ticket").click()
148        # Bed is randomly selected but, since there is only
149        # one bed for this student, we know that ...
150        self.assertFalse('Hall 1, Block A, Room 101, Bed A'
151                           in self.browser.contents)
152        self.assertTrue('(see payment slip)'
153                           in self.browser.contents)
154        self.assertTrue('ticket created'
155                           in self.browser.contents)
156        self.browser.open(self.payments_path + '/addop')
157        self.browser.getControl(
158            name="form.p_category").value = ['hostel_maintenance']
159        self.browser.getControl("Create ticket").click()
160        self.assertMatches('...ticket created...',
161                           self.browser.contents)
162        ctrl = self.browser.getControl(name='val_id')
163        value = ctrl.options[2]
164        self.browser.getLink(value).click()
165        self.assertMatches('...Amount Authorized...',
166                           self.browser.contents)
167        self.assertTrue(
168            '<span>4150.0</span>' in self.browser.contents)
169        # p_item is not unveiled
170        self.assertFalse('Hall 1, Block A, Room 101, Bed A'
171            in self.browser.contents)
172        self.assertTrue('(visible after successful payment)'
173            in self.browser.contents)
174        self.payment_url = self.browser.url
175        self.assertEqual(self.student['payments'][value].provider_amt, 0.0)
176        self.assertEqual(self.student['payments'][value].gateway_amt, 0.0)
177        self.assertEqual(self.student['payments'][value].thirdparty_amt, 0.0)
178        # Manager can access InterswitchForm
179        self.browser.getLink("CollegePAY", index=0).click()
180        # Split amounts have been set
181        self.assertEqual(self.student['payments'][value].provider_amt, 0.0)
182        self.assertEqual(self.student['payments'][value].gateway_amt, 150.0)
183        self.assertEqual(self.student['payments'][value].thirdparty_amt, 0.0)
184        # The total amount to be processed by Interswitch
185        # has been reduced by the Interswitch fee of 150 Nairas
186        self.assertMatches('...Total Amount Authorized:...',
187                           self.browser.contents)
188        self.assertTrue(
189            '<input type="hidden" name="amount" value="415000" />'
190            in self.browser.contents)
191        self.assertTrue(
192            'item_name="Hostel Maintenance Fee" item_amt="400000" bank_id="117" acct_num="1013780934"'
193            in self.browser.contents)
194        # BT does nor charge a fee for maintenance fee
195        self.assertFalse("BT Education" in self.browser.contents)
196        # p_item is not unveiled
197        self.assertFalse('Hall 1, Block A, Room 101, Bed A'
198            in self.browser.contents)
199        self.assertTrue('(visible after successful payment)'
200            in self.browser.contents)
201        # If the ticket is paid coordinates are shown
202        self.student['payments'][value].p_state = 'paid'
203        self.browser.open(self.payment_url)
204        self.assertTrue('Hall 1, Block A, Room 101, Bed A'
205            in self.browser.contents)
206        self.assertFalse('(visible after successful payment)'
207            in self.browser.contents)
208
209        # Acceptance fee payment
210
211        self.browser.open(self.payments_path)
212        self.browser.open(self.payments_path + '/addop')
213        self.browser.getControl(
214            name="form.p_category").value = ['clearance']
215        self.browser.getControl("Create ticket").click()
216        self.assertMatches('...ticket created...',
217                           self.browser.contents)
218        ctrl = self.browser.getControl(name='val_id')
219        value = ctrl.options[3]
220        self.browser.getLink(value).click()
221        self.assertMatches('...Amount Authorized...',
222                           self.browser.contents)
223        self.assertTrue(
224            '<span>3606.0</span>' in self.browser.contents)
225        self.payment_url = self.browser.url
226        self.assertEqual(self.student['payments'][value].provider_amt, 0.0)
227        self.assertEqual(self.student['payments'][value].gateway_amt, 0.0)
228        self.assertEqual(self.student['payments'][value].thirdparty_amt, 0.0)
229        # Manager can access InterswitchForm
230        self.browser.getLink("CollegePAY", index=0).click()
231        # Split amounts have been set
232        self.assertEqual(self.student['payments'][value].provider_amt, 0.0)
233        self.assertEqual(self.student['payments'][value].gateway_amt, 150.0)
234        self.assertEqual(self.student['payments'][value].thirdparty_amt, 0.0)
235        # The total amount to be processed by Interswitch
236        # has been reduced by the Interswitch fee of 150 Nairas
237        self.assertMatches('...Total Amount Authorized:...',
238                           self.browser.contents)
239        self.assertTrue(
240            '<input type="hidden" name="amount" value="360600" />' in
241            self.browser.contents)
242        self.assertTrue(
243            'item_name="Acceptance Fee" item_amt="345600" bank_id="8" acct_num="2010952698"'
244            in self.browser.contents)
245        # BT does nor charge a fee for maintenance fee
246        self.assertFalse("BT Education" in self.browser.contents)
247
248    def test_interswitch_form_ticket_expired(self):
249        # Manager can access InterswitchForm
250        self.browser.getLink("CollegePAY", index=0).click()
251        self.assertMatches('...<input type="hidden" name="pay_item_id" value="8302" />...',
252                           self.browser.contents)
253        self.assertMatches('...Total Amount Authorized:...',
254                           self.browser.contents)
255        self.assertEqual(self.student.current_mode, 'nce_ft')
256        self.assertMatches(
257            '...<input type="hidden" name="amount" value="4000000" />...',
258            self.browser.contents)
259        delta = timedelta(minutes=61)
260        self.payment.creation_date -= delta
261        self.browser.open(self.payment_url)
262        self.browser.getLink("CollegePAY", index=0).click()
263        self.assertMatches(
264            '...This payment ticket is too old. Please create a new ticket...',
265            self.browser.contents)
266        delta = timedelta(minutes=2)
267        self.payment.creation_date += delta
268        self.browser.open(self.payment_url)
269        self.browser.getLink("CollegePAY", index=0).click()
270        self.assertMatches('...Total Amount Authorized:...',
271                           self.browser.contents)
272
273#    @external_test
274#    def test_callback(self):
275
276        # Manager can call callback manually
277#        self.browser.open(self.callback_url(self.payment_url, 'XX', '300'))
278#        self.assertMatches('...Unsuccessful callback: Something went wrong...',
279#                          self.browser.contents)
280#        self.assertMatches('...Failed...',
281#                           self.browser.contents)
282#        self.browser.open(self.payment_url + '/isw_callback')
283#        self.assertMatches('...Unsuccessful callback: Incomplete query string...',
284#                          self.browser.contents)
285#        self.assertMatches('...Failed...',
286#                           self.browser.contents)
287#        self.browser.open(self.callback_url(self.payment_url, '00', '300000'))
288#        self.assertMatches('...Wrong amount...',
289#                          self.browser.contents)
290#        self.browser.open(self.callback_url(self.payment_url, '00', '4000000'))
291#        self.assertMatches('...Valid callback received...',
292#                          self.browser.contents)
293
294    @external_test
295    def test_webservice(self):
296        # First we have open InterswitchPageStudent to set provider_amt
297        # and gateway_amt
298        self.browser.open(self.payment_url + '/goto_interswitch')
299        # Now we can call the webservice
300        self.browser.open(self.payment_url + '/request_webservice')
301        #self.assertMatches('...Unsuccessful callback...',
302        #                  self.browser.contents)
303        self.assertMatches('...Unsuccessful callback...',
304                          self.browser.contents)
305        # The payment is now in state failed ...
306        self.assertMatches('...<span>Failed</span>...',
307                          self.browser.contents)
308        # ... and the catalog has been updated
309        cat = getUtility(ICatalog, name='payments_catalog')
310        results = list(
311            cat.searchResults(p_state=('failed', 'failed')))
312        self.assertEqual(len(results), 1)
313        self.assertEqual(results[0].p_state, 'failed')
314
315        # Let's replace the p_id with a valid p_id of the FCEOkene
316        # live system. This is definitely not an appropriate
317        # solution for testing, but we have no choice since
318        # Interswitch doesn't provide any interface
319        # for testing.
320        payment = self.student['payments'][self.value]
321        payment.p_id = 'p3536651296379'
322        self.browser.open(self.payment_url + '/request_webservice')
323        self.assertMatches('...Callback amount does not match...',
324                          self.browser.contents)
325        # The payment is now in state failed ...
326        self.assertMatches('...<span>Failed</span>...',
327                          self.browser.contents)
328        # Let's replace the amount autorized with the amount of the
329        # live system payment
330        payment.amount_auth = payment.r_amount_approved
331        self.browser.open(self.payment_url + '/request_webservice')
332        self.assertMatches('...Successful payment...',
333                          self.browser.contents)
334        # The payment is now in state paid ...
335        self.assertMatches('...<span>Paid</span>...',
336                          self.browser.contents)
337        # ... and the catalog has been updated
338        cat = getUtility(ICatalog, name='payments_catalog')
339        results = list(
340            cat.searchResults(p_state=('paid', 'paid')))
341        self.assertEqual(len(results), 1)
342        self.assertEqual(results[0].p_state, 'paid')
343        # Approval is logged in students.log ...
344        logfile = os.path.join(
345            self.app['datacenter'].storage, 'logs', 'students.log')
346        logcontent = open(logfile).read()
347        self.assertTrue(
348            'zope.mgr - '
349            'waeup.fceokene.interswitch.browser.CustomInterswitchPaymentRequestWebservicePageStudent - '
350            'K1000000 - successful schoolfee payment: p3536651296379\n'
351            in logcontent)
352        # ... and in payments.log
353        logfile = os.path.join(
354            self.app['datacenter'].storage, 'logs', 'payments.log')
355        logcontent = open(logfile).read()
356        self.assertTrue(
357            '"zope.mgr",K1000000,p3536651296379,schoolfee,'
358            '3150.0,00,1600.0,150.0,1400.0,,,\n'
359            in logcontent)
360
361class InterswitchTestsApplicants(ApplicantsFullSetup):
362    """Tests for the Interswitch payment gateway.
363    """
364
365    layer = FunctionalLayer
366
367    def setUp(self):
368        super(InterswitchTestsApplicants, self).setUp()
369        configuration = SessionConfiguration()
370        configuration.academic_session = datetime.now().year - 2
371        self.app['configuration'].addSessionConfiguration(configuration)
372        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
373        self.browser.open(self.manage_path)
374        #IWorkflowState(self.student).setState('started')
375        super(InterswitchTestsApplicants, self).fill_correct_values()
376        self.applicantscontainer.application_fee = 1000.0
377        self.browser.getControl(name="form.nationality").value = ['NG']
378        self.browser.getControl(name="transition").value = ['start']
379        self.browser.getControl("Save").click()
380
381    def test_interswitch_form(self):
382        self.browser.getControl("Add online").click()
383        self.assertMatches('...ticket created...',
384                           self.browser.contents)
385        self.assertMatches(
386            '...<span>1000.0</span>...',
387            self.browser.contents)
388        self.payment_url = self.browser.url
389        self.browser.open(self.manage_path)
390        ctrl = self.browser.getControl(name='val_id')
391        self.value = ctrl.options[0]
392        # Manager can access InterswitchForm
393        self.browser.open(self.payment_url)
394        self.browser.getLink("CollegePAY", index=0).click()
395        self.assertMatches('...Total Amount Authorized:...',
396                           self.browser.contents)
397        self.assertTrue(
398            '<input type="hidden" name="amount" value="100000" />'
399            in self.browser.contents)
400        self.assertTrue(
401            '<item_detail item_id="1" item_name="application"'
402            ' item_amt="35000" bank_id="117" acct_num="1013780934" />'
403            in self.browser.contents)
404        delta = timedelta(minutes=61)
405        self.applicant[self.value].creation_date -= delta
406        self.browser.open(self.payment_url)
407        self.browser.getLink("CollegePAY", index=0).click()
408        self.assertMatches(
409            '...This payment ticket is too old. Please create a new ticket...',
410            self.browser.contents)
411
412    @external_test
413    def test_webservice(self):
414        self.browser.getControl("Add online").click()
415        self.assertMatches('...ticket created...',
416                           self.browser.contents)
417        self.assertMatches(
418            '...<span>1000.0</span>...',
419            self.browser.contents)
420        self.payment_url = self.browser.url
421        self.browser.open(self.manage_path)
422        ctrl = self.browser.getControl(name='val_id')
423        self.value = ctrl.options[0]
424        # First we have open InterswitchPageStudent to set provider_amt
425        # and gateway_amt
426        self.browser.open(self.payment_url + '/goto_interswitch')
427        # Now we can call the webservice
428        self.browser.open(self.payment_url + '/request_webservice')
429        self.assertMatches('...Unsuccessful callback...',
430                          self.browser.contents)
431        # The payment is now in state failed ...
432        self.assertMatches('...<span>Failed</span>...',
433                          self.browser.contents)
434        # ... and the catalog has been updated
435        cat = getUtility(ICatalog, name='payments_catalog')
436        results = list(
437            cat.searchResults(p_state=('failed', 'failed')))
438        self.assertEqual(len(results), 1)
439        self.assertEqual(results[0].p_state, 'failed')
440
441        # Let's replace the p_id with a valid p_id of the Uniben
442        # live system. This is definitely not an appropriate
443        # solution for testing, but we have no choice since
444        # Interswitch doesn't provide any interface
445        # for testing.
446        payment = self.applicant[self.value]
447        payment.p_id = 'p3536651296379'
448        self.browser.open(self.payment_url + '/request_webservice')
449        self.assertMatches('...Callback amount does not match...',
450                          self.browser.contents)
451        # The payment is now in state failed ...
452        self.assertMatches('...<span>Failed</span>...',
453                          self.browser.contents)
454        # Let's replace the amount autorized with the amount of the
455        # live system payment
456        payment.amount_auth = payment.r_amount_approved
457        self.browser.open(self.payment_url + '/request_webservice')
458        self.assertMatches('...Successful payment...',
459                          self.browser.contents)
460        # The payment is now in state paid ...
461        self.assertMatches('...<span>Paid</span>...',
462                          self.browser.contents)
463        # ... and the catalog has been updated
464        cat = getUtility(ICatalog, name='payments_catalog')
465        results = list(
466            cat.searchResults(p_state=('paid', 'paid')))
467        self.assertEqual(len(results), 1)
468        self.assertEqual(results[0].p_state, 'paid')
469        # Approval is logged in students.log ...
470        logfile = os.path.join(
471            self.app['datacenter'].storage, 'logs', 'applicants.log')
472        logcontent = open(logfile).read()
473        self.assertTrue(
474            'zope.mgr - '
475            'waeup.fceokene.interswitch.browser.CustomInterswitchPaymentRequestWebservicePageApplicant - '
476            '%s - successful payment: p3536651296379\n'
477            % self.applicant.applicant_id in logcontent)
478        # ... and in payments.log
479        logfile = os.path.join(
480            self.app['datacenter'].storage, 'logs', 'payments.log')
481        logcontent = open(logfile).read()
482        self.assertTrue(
483            '"zope.mgr",%s,p3536651296379,application,'
484            '3150.0,00,500.0,150.0,0.0,,,\n' % self.applicant.applicant_id
485            in logcontent)
Note: See TracBrowser for help on using the repository browser.