source: main/kofacustom.nigeria/trunk/src/kofacustom/nigeria/students/tests/test_browser.py @ 13007

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

Fix test.

  • Property svn:keywords set to Id
File size: 16.4 KB
Line 
1## $Id: test_browser.py 12985 2015-05-22 08:15:48Z 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
19import shutil
20import tempfile
21from datetime import datetime, timedelta
22from StringIO import StringIO
23from hurry.workflow.interfaces import IWorkflowState, IWorkflowInfo
24from zope.component.hooks import setSite, clearSite
25from zope.component import getUtility, createObject
26from zope.interface import verify
27from waeup.kofa.app import University
28from waeup.kofa.students.tests.test_browser import (
29    StudentsFullSetup, SAMPLE_IMAGE)
30from waeup.kofa.testing import FunctionalTestCase
31from waeup.kofa.interfaces import (
32    IExtFileStore, IFileStoreNameChooser)
33from waeup.kofa.schoolgrades import ResultEntry
34from waeup.kofa.students.batching import StudentProcessor
35from waeup.kofa.students.interfaces import IStudentsUtils
36from kofacustom.nigeria.students.batching import NigeriaStudentProcessor
37from kofacustom.nigeria.testing import FunctionalLayer
38from kofacustom.nigeria.utils.utils import NigeriaKofaUtils
39from kofacustom.nigeria.students.interfaces import (
40    INigeriaStudentStudyCourse, INigeriaStudent,
41    INigeriaStudentStudyLevel, INigeriaCourseTicket)
42
43
44STUDENT_SAMPLE_DATA = open(
45    os.path.join(os.path.dirname(__file__), 'sample_student_data.csv'),
46    'rb').read()
47
48STUDENT_HEADER_FIELDS = STUDENT_SAMPLE_DATA.split(
49    '\n')[0].split(',')
50
51class StudentProcessorTest(FunctionalTestCase):
52    """Perform some batching tests.
53    """
54
55    layer = FunctionalLayer
56
57    def setUp(self):
58        super(StudentProcessorTest, self).setUp()
59        # Setup a sample site for each test
60        app = University()
61        self.dc_root = tempfile.mkdtemp()
62        app['datacenter'].setStoragePath(self.dc_root)
63
64        # Prepopulate the ZODB...
65        self.getRootFolder()['app'] = app
66        # we add the site immediately after creation to the
67        # ZODB. Catalogs and other local utilities are not setup
68        # before that step.
69        self.app = self.getRootFolder()['app']
70        # Set site here. Some of the following setup code might need
71        # to access grok.getSite() and should get our new app then
72        setSite(app)
73
74        self.processor_base = StudentProcessor()
75        self.processor = NigeriaStudentProcessor()
76        self.workdir = tempfile.mkdtemp()
77        self.csv_file = os.path.join(self.workdir, 'sample_student_data.csv')
78        open(self.csv_file, 'wb').write(STUDENT_SAMPLE_DATA)
79
80    def tearDown(self):
81        super(StudentProcessorTest, self).tearDown()
82        shutil.rmtree(self.workdir)
83        shutil.rmtree(self.dc_root)
84        clearSite()
85        return
86
87    def test_import(self):
88        num, num_warns, fin_file, fail_file = self.processor.doImport(
89            self.csv_file, STUDENT_HEADER_FIELDS)
90        #print open(fail_file).read()
91        self.assertEqual(num_warns,0)
92        assert len(self.app['students'].keys()) == 3
93        # Also fst_sit_results have been properly imported (tested only here!)
94        self.assertEqual(
95            self.app['students']['K1000000'].fst_sit_results[0].__dict__,
96            {'grade': 'A1', 'subject': 'visual_art'})
97        self.assertEqual(
98            self.app['students']['K1000000'].fst_sit_results[1].__dict__,
99            {'grade': 'C6', 'subject': 'applied_electricity'})
100        shutil.rmtree(os.path.dirname(fin_file))
101
102
103class StudentUITests(StudentsFullSetup):
104    """Tests for customized student class views and pages
105    """
106
107    layer = FunctionalLayer
108
109    def setUp(self):
110        super(StudentUITests, self).setUp()
111
112    def test_classes(self):
113        # Let's see if objects created in the customized
114        # portal really implement the customized interfaces
115        verify.verifyObject(INigeriaStudent, self.student)
116        verify.verifyObject(
117            INigeriaStudentStudyCourse, self.student['studycourse'])
118        studylevel = createObject(u'waeup.StudentStudyLevel')
119        verify.verifyObject(INigeriaStudentStudyLevel, studylevel)
120        ticket = createObject(u'waeup.CourseTicket')
121        verify.verifyObject(INigeriaCourseTicket, ticket)
122        IWorkflowState(self.student).setState('returning')
123        # Let's see if next_session_allowed works as expected
124        # A, ug_ft, 100
125        self.assertTrue(self.student['studycourse'].next_session_allowed)
126        # Zero, ug_ft, 100
127        self.student['studycourse'].current_verdict = '0' # Zero!
128        self.assertTrue(self.student['studycourse'].next_session_allowed)
129        # Zero, ug_ft, 200
130        self.student['studycourse'].current_level = 200
131        self.assertFalse(self.student['studycourse'].next_session_allowed)
132        # Zero, de_ft, 200
133        self.student['studycourse'].certificate.study_mode = 'de_ft'
134        self.assertTrue(self.student['studycourse'].next_session_allowed)
135        # Zero, ph_ft, 300
136        self.student['studycourse'].certificate.study_mode = 'ph_ft'
137        self.student['studycourse'].current_level = 300
138        self.assertTrue(self.student['studycourse'].next_session_allowed)
139        # Zero, ph_ft, 400
140        self.student['studycourse'].current_level = 400
141        self.assertFalse(self.student['studycourse'].next_session_allowed)
142
143        # Now we convert the certificate into a postgraduate certificate
144        IWorkflowState(self.student).setState('school fee paid')
145        self.certificate.study_mode = 'pg_ft'
146        # ... and voila next session registration is allowed
147        self.assertTrue(self.student['studycourse'].next_session_allowed)
148
149    def test_manage_access(self):
150        self.student.nationality = u'DE'
151        # Managers can access the pages of students
152        # and can perform actions
153        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
154        # The student created in the base package is an ug student
155        self.browser.open(self.student_path)
156        self.browser.getLink("Clearance Data").click()
157        self.assertEqual(self.browser.headers['Status'], '200 Ok')
158        self.assertEqual(self.browser.url, self.clearance_path)
159        self.browser.getLink("Manage").click()
160        self.assertEqual(self.browser.headers['Status'], '200 Ok')
161        self.assertEqual(self.browser.url, self.manage_clearance_path)
162        self.browser.getControl(name="form.date_of_birth").value = '09/10/1961'
163        self.browser.getControl("Save").click()
164        self.assertMatches('...Form has been saved...',
165                           self.browser.contents)
166        self.assertMatches('...First Sitting Record...',
167                           self.browser.contents)
168        # Managers can open clearance slip of ug students
169        self.browser.open(self.student_path + '/clearance_slip.pdf')
170        self.assertEqual(self.browser.headers['Status'], '200 Ok')
171        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
172        # There is no pg field in the clearance form
173        self.assertFalse('Second Higher Education Record'
174            in self.browser.contents)
175        # Now we change the study mode ...
176        self.certificate.study_mode = 'pg_ft'
177        self.browser.open(self.clearance_path)
178        # ... and additional pg clearance fields appear
179        self.assertMatches('...Second Higher Education Record...',
180                           self.browser.contents)
181        # But also fields from the ug form are displayed
182        self.assertMatches('...First Sitting Record...',
183                           self.browser.contents)
184        # Managers can open clearance slip of pg students
185        self.browser.open(self.student_path + '/clearance_slip.pdf')
186        self.assertEqual(self.browser.headers['Status'], '200 Ok')
187        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
188        # Managers can edit personal data. No fields are required.
189        self.browser.open(self.manage_personal_path)
190        self.browser.getControl("Save").click()
191        self.assertMatches('...Form has been saved...',
192                           self.browser.contents)
193
194    def test_logging(self):
195        self.student.nationality = u'DE'
196        valid_subj = NigeriaKofaUtils().EXAM_SUBJECTS_DICT.keys()[0]
197        valid_grade = NigeriaKofaUtils().EXAM_GRADES[0][0]
198        result_entry = ResultEntry(valid_subj, valid_grade)
199        self.student.fst_sit_results = [result_entry,]
200        # Managers can access the pages of students
201        # and can perform actions
202        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
203        # The student created in the base package is an ug student
204        self.browser.open(self.student_path)
205        self.browser.getLink("Clearance Data").click()
206        self.browser.getLink("Manage").click()
207        self.browser.getControl("Save").click()
208        logfile = os.path.join(
209            self.app['datacenter'].storage, 'logs', 'students.log')
210        logcontent = open(logfile).read()
211        self.assertFalse('saved: fst_sit_results' in logcontent)
212
213    def test_student_access(self):
214        # Students can edit clearance data
215        IWorkflowState(self.student).setState('cleared')
216        self.browser.open(self.login_path)
217        self.browser.getControl(name="form.login").value = self.student_id
218        self.browser.getControl(name="form.password").value = 'spwd'
219        self.browser.getControl("Login").click()
220        # Even in state admitted students can't change the portait if
221        # application slip exists.
222        IWorkflowState(self.student).setState('admitted')
223        self.browser.open(self.student_path)
224        self.assertTrue('Change portrait' in self.browser.contents)
225        file_store = getUtility(IExtFileStore)
226        applicant_slip = 'My application slip'
227        file_id = IFileStoreNameChooser(self.student).chooseName(
228            attr="application_slip.pdf")
229        file_store.createFile(file_id, StringIO(applicant_slip))
230        self.browser.open(self.student_path)
231        self.assertFalse('Change portrait' in self.browser.contents)
232        self.browser.open(self.student_path + '/change_portrait')
233        self.assertTrue('The requested form is locked' in self.browser.contents)
234
235        # Student can view and edit clearance data if clearance has started ...
236        IWorkflowInfo(self.student).fireTransition('start_clearance')
237        self.student.officer_comment = u'Fill properly'
238        self.browser.getLink("Clearance Data").click()
239        self.assertTrue("Officer's Comment" in self.browser.contents)
240        # Students can't edit officer's comment
241        self.browser.getLink("Edit").click()
242        self.assertFalse("Officer's Comment" in self.browser.contents)
243        self.assertTrue('Save' in self.browser.contents)
244        # ... and request clearance if nationality field has been filled.
245        self.browser.getControl("Save and request clearance").click()
246        self.assertMatches('...Required input is missing...',
247                           self.browser.contents)
248        self.student.nationality = u'DE'
249        self.browser.open(self.edit_clearance_path)
250        self.browser.getControl("Save and request clearance").click()
251        self.assertMatches('...Clearance has been requested...',
252                           self.browser.contents)
253
254        # Students can edit personal data. Some fields are required.
255        self.browser.open(self.personal_path)
256        self.assertTrue('Updated' in self.browser.contents)
257        self.browser.getLink("Edit").click()
258        self.assertEqual(self.browser.headers['Status'], '200 Ok')
259        self.assertEqual(self.browser.url, self.edit_personal_path)
260        self.browser.getControl("Save").click()
261        self.assertMatches('...Required input is missing...',
262                           self.browser.contents)
263        self.browser.getControl(name="form.perm_address").value = 'My address!'
264        self.browser.getControl("Save").click()
265        self.assertMatches('...Required input is missing...',
266                           self.browser.contents)
267        # Ok, let's give up and fill the rest.
268        self.browser.getControl(name="form.next_kin_name").value = 'My Mutti'
269        self.browser.getControl(name="form.next_kin_relation").value = 'mother'
270        self.browser.getControl(name="form.next_kin_address").value = 'sweet home'
271        self.browser.getControl(name="form.next_kin_phone.country").value = ['+234']
272        self.browser.getControl(name="form.next_kin_phone.ext").value = '45678'
273        self.browser.getControl("Save").click()
274        self.assertMatches('...Form has been saved...',
275                           self.browser.contents)
276
277    def test_manage_upload_file(self):
278        # Managers can upload a file via the StudentClearanceManageFormPage
279        # The image is stored even if form has errors
280        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
281        self.browser.open(self.manage_clearance_path)
282        # Managers can add and delete a file
283        self.browser.open(self.manage_clearance_path)
284        image = open(SAMPLE_IMAGE, 'rb')
285        ctrl = self.browser.getControl(name='birthcertificateupload')
286        file_ctrl = ctrl.mech_control
287        file_ctrl.add_file(image, filename='my_acceptance_letter.jpg')
288        self.browser.getControl(
289            name='upload_acceptanceletterupload').click()
290        # Uups, we used the wrong 'Browse' field
291        self.assertFalse(
292            '<a target="image" href="acc_let">'
293            in self.browser.contents)
294        ctrl = self.browser.getControl(name='acceptanceletterupload')
295        file_ctrl = ctrl.mech_control
296        image.seek(0)
297        file_ctrl.add_file(image, filename='my_acceptance_letter.jpg')
298        self.browser.getControl(
299            name='upload_acceptanceletterupload').click()
300        self.assertTrue(
301            'http://localhost/app/students/K1000000/acc_let'
302            in self.browser.contents)
303        self.browser.getControl(
304            name='delete_acceptanceletterupload').click()
305        self.assertTrue(
306            'acc_let deleted'
307            in self.browser.contents)
308
309    def test_student_expired_personal_data(self):
310        # Login
311        IWorkflowState(self.student).setState('school fee paid')
312        delta = timedelta(days=180)
313        self.student.personal_updated = datetime.utcnow() - delta
314        self.browser.open(self.login_path)
315        self.browser.getControl(name="form.login").value = self.student_id
316        self.browser.getControl(name="form.password").value = 'spwd'
317        self.browser.getControl("Login").click()
318        self.assertEqual(self.browser.url, self.student_path)
319        self.assertTrue(
320            'You logged in' in self.browser.contents)
321        # Students don't see personal_updated field in edit form
322        self.browser.open(self.edit_personal_path)
323        self.assertFalse('Updated' in self.browser.contents)
324        self.browser.open(self.personal_path)
325        self.assertTrue('Updated' in self.browser.contents)
326        self.browser.getLink("Logout").click()
327        delta = timedelta(days=181)
328        self.student.personal_updated = datetime.utcnow() - delta
329        self.browser.open(self.login_path)
330        self.browser.getControl(name="form.login").value = self.student_id
331        self.browser.getControl(name="form.password").value = 'spwd'
332        self.browser.getControl("Login").click()
333        self.assertEqual(self.browser.url, self.edit_personal_path)
334        self.assertTrue(
335            'Your personal data record is outdated.' in self.browser.contents)
336
337    def test_lga_nationality(self):
338        self.student.nationality = u'DE'
339        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
340        self.browser.open(self.manage_clearance_path)
341        self.browser.getControl(name="form.lga").value = ['abia_aba_north']
342        self.browser.getControl("Save").click()
343        self.assertTrue(
344            'Nationalty and LGA are contradictory.' in self.browser.contents)
345        self.browser.getControl(name="form.nationality").value = ['NG']
346        self.browser.getControl("Save").click()
347        self.assertTrue(
348            'Form has been saved' in self.browser.contents)
Note: See TracBrowser for help on using the repository browser.