source: main/waeup.kofa/trunk/src/waeup/kofa/hostels/tests.py @ 13439

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

Add BedProcessor?.

  • Property svn:keywords set to Id
File size: 28.0 KB
Line 
1## $Id: tests.py 13432 2015-11-10 13:06:25Z 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##
18"""
19Tests for hostels and their UI components.
20"""
21import os
22import shutil
23import tempfile
24import grok
25import pytz
26from datetime import datetime, timedelta
27from zope.event import notify
28from zope.interface.verify import verifyClass, verifyObject
29from zope.component.hooks import setSite, clearSite
30from zope.testbrowser.testing import Browser
31from zope.security.interfaces import Unauthorized
32from zope.catalog.interfaces import ICatalog
33from zope.component import queryUtility
34from waeup.kofa.app import University
35from waeup.kofa.hostels.interfaces import (
36    IHostelsContainer, IHostel, IBed)
37from waeup.kofa.hostels.vocabularies import NOT_OCCUPIED
38from waeup.kofa.hostels.container import HostelsContainer
39from waeup.kofa.hostels.hostel import Hostel, Bed
40from waeup.kofa.hostels.batching import HostelProcessor, BedProcessor
41from waeup.kofa.hostels.export import BedExporter, HostelExporter
42from waeup.kofa.testing import (FunctionalLayer, FunctionalTestCase)
43from waeup.kofa.students.student import Student
44from waeup.kofa.students.accommodation import BedTicket
45from waeup.kofa.university.department import Department
46
47HOSTEL_SAMPLE_DATA = open(
48    os.path.join(os.path.dirname(__file__), 'sample_hostel_data.csv'),
49    'rb').read()
50
51HOSTEL_HEADER_FIELDS = HOSTEL_SAMPLE_DATA.split(
52    '\n')[0].split(',')
53
54BED_SAMPLE_DATA = open(
55    os.path.join(os.path.dirname(__file__), 'sample_bed_data.csv'),
56    'rb').read()
57
58BED_HEADER_FIELDS = BED_SAMPLE_DATA.split(
59    '\n')[0].split(',')
60
61class HostelsContainerTestCase(FunctionalTestCase):
62
63    layer = FunctionalLayer
64
65    def test_interfaces(self):
66        # Make sure the correct interfaces are implemented.
67        self.assertTrue(
68            verifyClass(
69                IHostelsContainer, HostelsContainer)
70            )
71        self.assertTrue(
72            verifyObject(
73                IHostelsContainer, HostelsContainer())
74            )
75        self.assertTrue(
76            verifyClass(
77                IHostel, Hostel)
78            )
79        self.assertTrue(
80            verifyObject(
81                IHostel, Hostel())
82            )
83        self.assertTrue(
84            verifyClass(
85                IBed, Bed)
86            )
87        bed = Bed()
88        bed.bed_id = u'a_b_c_d'
89        bed.bed_type = u'a_b_c'
90        self.assertTrue(
91            verifyObject(
92                IBed, bed)
93            )
94        return
95
96    def test_base(self):
97        # We cannot call the fundamental methods of a base in that case
98        container = HostelsContainer()
99        hostel = Hostel()
100        # We cannot add arbitrary objects
101        department = Department()
102        self.assertRaises(
103            TypeError, container.addHostel, department)
104        self.assertRaises(
105            TypeError, hostel.addBed, department)
106        # Application is expired if startdate or enddate are not set
107        # or current datetime is outside application period.
108        self.assertTrue(container.expired)
109        delta = timedelta(days=10)
110        container.startdate = datetime.now(pytz.utc) - delta
111        self.assertTrue(container.expired)
112        container.enddate = datetime.now(pytz.utc) + delta
113        self.assertFalse(container.expired)
114
115class HostelsFullSetup(FunctionalTestCase):
116
117    def setUp(self):
118        super(HostelsFullSetup, self).setUp()
119
120        # Setup a sample site for each test
121        app = University()
122        self.dc_root = tempfile.mkdtemp()
123        app['datacenter'].setStoragePath(self.dc_root)
124
125        # Prepopulate the ZODB...
126        self.getRootFolder()['app'] = app
127        # we add the site immediately after creation to the
128        # ZODB. Catalogs and other local utilities are not setup
129        # before that step.
130        self.app = self.getRootFolder()['app']
131        # Set site here. Some of the following setup code might need
132        # to access grok.getSite() and should get our new app then
133        setSite(app)
134
135        # Add student with subobjects
136        student = Student()
137        student.firstname = u'Anna'
138        student.lastname = u'Tester'
139        student.reg_number = u'123'
140        student.matric_number = u'234'
141        student.sex = u'f'
142        self.app['students'].addStudent(student)
143        self.student_id = student.student_id
144        self.student = self.app['students'][self.student_id]
145        self.student['studycourse'].current_session = 2004
146        self.student['studycourse'].entry_session = 2004
147        # The students_catalog must be informed that the
148        # session attribute has changed
149        notify(grok.ObjectModifiedEvent(self.student))
150
151        # Set accommodation_session
152        self.app['hostels'].accommodation_session = 2004
153
154        # Create a hostel
155        hostel = Hostel()
156        hostel.hostel_id = u'hall-x'
157        self.app['hostels'][hostel.hostel_id] = hostel
158
159        # Create a bed
160        bed = Bed()
161        bed.bed_id = u'hall_block_room_bed'
162        bed.bed_number = 1
163        bed.bed_type = u'a_b_c'
164        self.app['hostels'][hostel.hostel_id][bed.bed_id] = bed
165
166        self.container_path = 'http://localhost/app/hostels'
167        self.student_path = 'http://localhost/app/students/%s' % self.student_id
168        self.manage_container_path = self.container_path + '/@@manage'
169        self.add_hostel_path = self.container_path + '/addhostel'
170
171        # Put the prepopulated site into test ZODB and prepare test
172        # browser
173        self.browser = Browser()
174        self.browser.handleErrors = False
175
176        self.logfile = os.path.join(
177            self.app['datacenter'].storage, 'logs', 'hostels.log')
178
179    def tearDown(self):
180        super(HostelsFullSetup, self).tearDown()
181        clearSite()
182        shutil.rmtree(self.dc_root)
183
184class HostelsContainerTests(HostelsFullSetup):
185
186    layer = FunctionalLayer
187
188    def test_release_expired_allocations(self):
189        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
190        cat = queryUtility(ICatalog, name='beds_catalog')
191        bedticket = BedTicket()
192        bedticket.booking_session = 2004
193        bedticket.bed_coordinates = u'anything'
194        self.student['accommodation'].addBedTicket(bedticket)
195        self.app[
196            'hostels']['hall-x']['hall_block_room_bed'].owner = self.student_id
197        notify(grok.ObjectModifiedEvent(
198            self.app['hostels']['hall-x']['hall_block_room_bed']))
199        results = cat.searchResults(owner=(self.student_id, self.student_id))
200        self.assertEqual(len(results), 1)
201        self.browser.open(self.container_path + '/releaseexpired')
202        self.assertTrue('No bed released' in self.browser.contents)
203        delta = timedelta(days=10)
204        bedticket.booking_date = datetime.utcnow() - delta
205        self.browser.open(self.container_path + '/releaseexpired')
206        self.assertTrue(
207            'Successfully released beds: hall_block_room_bed (K1000000)'
208            in self.browser.contents)
209        results = cat.searchResults(owner=(self.student_id, self.student_id))
210        self.assertEqual(len(results), 0)
211        self.assertMatches(bedticket.display_coordinates,
212            '-- booking expired (2015-10-14 08:35:38 UTC) --')
213        self.assertEqual(
214            self.app['hostels']['hall-x']['hall_block_room_bed'].owner,
215            NOT_OCCUPIED)
216        # Releasing is logged.
217        logcontent = open(self.logfile).read()
218        self.assertTrue(
219            'hostels.browser.ReleaseExpiredAllocationsPage - hostels - '
220            'released: hall_block_room_bed (K1000000)'
221            in logcontent)
222        return
223
224class BedCatalogTests(HostelsFullSetup):
225
226    layer = FunctionalLayer
227
228    def test_get_catalog(self):
229        # We can get a beds catalog if we wish
230        cat = queryUtility(ICatalog, name='beds_catalog')
231        assert cat is not None
232
233    def test_search_by_type(self):
234        # We can find a certain bed
235        cat = queryUtility(ICatalog, name='beds_catalog')
236        results = cat.searchResults(bed_type=(u'a_b_c', u'a_b_c'))
237        results = [x for x in results] # Turn results generator into list
238        assert len(results) == 1
239        assert results[0] is self.app['hostels']['hall-x']['hall_block_room_bed']
240
241    def test_search_by_owner(self):
242        # We can find a certain bed
243        myobj = self.app['hostels']['hall-x']['hall_block_room_bed']
244        myobj.owner = u'abc'
245        notify(grok.ObjectModifiedEvent(myobj))
246        cat = queryUtility(ICatalog, name='beds_catalog')
247        results = cat.searchResults(owner=(u'abc', u'abc'))
248        results = [x for x in results] # Turn results generator into list
249        assert len(results) == 1
250        assert results[0] is self.app['hostels']['hall-x']['hall_block_room_bed']
251
252class HostelsUITests(HostelsFullSetup):
253
254    layer = FunctionalLayer
255
256    def test_anonymous_access(self):
257        # Anonymous users can't access hostels containers
258        self.assertRaises(
259            Unauthorized, self.browser.open, self.manage_container_path)
260        return
261
262    def test_add_search_edit_delete_manage_hostels(self):
263        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
264        self.browser.open(self.container_path)
265        self.browser.getLink("Manage accommodation").click()
266        self.assertEqual(self.browser.headers['Status'], '200 Ok')
267        self.assertEqual(self.browser.url, self.manage_container_path)
268        self.browser.getControl("Add hostel").click()
269        self.assertEqual(self.browser.headers['Status'], '200 Ok')
270        self.assertEqual(self.browser.url, self.add_hostel_path)
271        self.browser.getControl("Create hostel").click()
272        self.assertEqual(self.browser.headers['Status'], '200 Ok')
273        self.assertTrue('Hostel created' in self.browser.contents)
274        self.browser.open(self.container_path + '/addhostel')
275        self.browser.getControl("Create hostel").click()
276        self.assertTrue('The hostel already exists' in self.browser.contents)
277        hall = self.app['hostels']['hall-1']
278        hall.blocks_for_female = ['A','B']
279        self.browser.open(self.container_path + '/hall-1')
280        expected = '...<ul id="form.blocks_for_female" ><li>Block A</li>...'
281        self.assertMatches(expected,self.browser.contents)
282        self.browser.open(self.container_path + '/hall-1/manage')
283        self.browser.getControl(name="form.rooms_per_floor").value = '1'
284        self.browser.getControl("Save").click()
285        self.assertTrue('Form has been saved' in self.browser.contents)
286        # Since the testbrowser does not support Javascrip the
287        # save action cleared the settings above and we have to set them
288        # again.
289        self.assertTrue(len(hall.blocks_for_female) == 0)
290        hall.blocks_for_female = ['A','B']
291        hall.beds_for_fresh = ['A']
292        hall.beds_for_returning = ['B']
293        hall.beds_for_final = ['C']
294        hall.beds_for_all = ['D','E']
295        self.browser.getControl("Update all beds").click()
296        expected = '...0 empty beds removed, 10 beds added, 0 occupied beds modified ()...'
297        self.assertMatches(expected,self.browser.contents)
298        cat = queryUtility(ICatalog, name='beds_catalog')
299        results = cat.searchResults(
300            bed_type=('regular_female_all', 'regular_female_all'))
301        results = [(x.bed_id, x.bed_type) for x in results]
302        self.assertEqual(results,
303            [(u'hall-1_A_101_D', u'regular_female_all'),
304             (u'hall-1_A_101_E', u'regular_female_all'),
305             (u'hall-1_B_101_D', u'regular_female_all'),
306             (u'hall-1_B_101_E', u'regular_female_all')])
307        # Reserve beds.
308        self.browser.getControl("Switch reservation", index=0).click()
309        self.assertTrue('No item selected' in self.browser.contents)
310        ctrl = self.browser.getControl(name='val_id')
311        ctrl.getControl(value='hall-1_A_101_A').selected = True
312        ctrl.getControl(value='hall-1_A_101_B').selected = True
313        ctrl.getControl(value='hall-1_A_101_C').selected = True
314        ctrl.getControl(value='hall-1_A_101_D').selected = True
315        self.browser.getControl("Switch reservation", index=0).click()
316        self.assertTrue('Successfully switched beds: hall-1_A_101_A (reserved)'
317            in self.browser.contents)
318        self.assertEqual(self.app['hostels']['hall-1'][
319            'hall-1_A_101_D'].bed_type, 'regular_female_reserved')
320        # The catalog has been updated.
321        results = cat.searchResults(
322            bed_type=('regular_female_all', 'regular_female_all'))
323        results = [(x.bed_id, x.bed_type) for x in results]
324        self.assertEqual(results,
325            [(u'hall-1_A_101_E', u'regular_female_all'),
326             (u'hall-1_B_101_D', u'regular_female_all'),
327             (u'hall-1_B_101_E', u'regular_female_all')])
328        results = cat.searchResults(
329            bed_type=('regular_female_reserved', 'regular_female_reserved'))
330        results = [(x.bed_id, x.bed_type) for x in results]
331        self.assertEqual(results,
332            [(u'hall-1_A_101_A', u'regular_female_reserved'),
333             (u'hall-1_A_101_B', u'regular_female_reserved'),
334             (u'hall-1_A_101_C', u'regular_female_reserved'),
335             (u'hall-1_A_101_D', u'regular_female_reserved')])
336        # Change hostel configuration with one bed booked.
337        hall['hall-1_A_101_E'].owner = u'anyid'
338        notify(grok.ObjectModifiedEvent(hall['hall-1_A_101_E']))
339        hall.beds_for_fresh = ['A', 'E']
340        hall.beds_for_all = ['D']
341        self.browser.getControl("Update all beds").click()
342        expected = '...9 empty beds removed, 9 beds added, 1 occupied beds modified...'
343        self.assertMatches(expected,self.browser.contents)
344        # Updating beds (including booked beds!) does update catalog.
345        results = cat.searchResults(
346            bed_type=('regular_female_all', 'regular_female_all'))
347        results = [(x.bed_id, x.bed_type) for x in results]
348        # The reservation of hall-1_A_101_D has been cancelled.
349        self.assertEqual(results,
350            [(u'hall-1_A_101_D', u'regular_female_all'),
351             (u'hall-1_B_101_D', u'regular_female_all')])
352        # Release bed which has previously been booked.
353        bedticket = BedTicket()
354        bedticket.booking_session = 2004
355        bedticket.bed_coordinates = u'anything'
356        self.student['accommodation'].addBedTicket(bedticket)
357        self.app['hostels']['hall-1']['hall-1_A_101_D'].owner = self.student_id
358        notify(grok.ObjectModifiedEvent(self.app['hostels']['hall-1']['hall-1_A_101_D']))
359        self.browser.open(self.container_path + '/hall-1/manage')
360        ctrl = self.browser.getControl(name='val_id')
361        self.browser.getControl("Release selected beds", index=0).click()
362        self.assertMatches("...No item selected...", self.browser.contents)
363        ctrl = self.browser.getControl(name='val_id')
364        ctrl.getControl(value='hall-1_A_101_D').selected = True
365        self.browser.getControl("Release selected beds", index=0).click()
366        self.assertMatches(
367          '...Successfully released beds: hall-1_A_101_D (%s)...' % self.student_id,
368          self.browser.contents)
369        self.assertMatches(bedticket.bed_coordinates,
370          u' -- booking cancelled on <YYYY-MM-DD hh:mm:ss> UTC --')
371        # The catalog has been updated.
372        results = cat.searchResults(owner=(self.student_id, self.student_id))
373        assert len(results) == 0
374        # If we release a free bed, nothing will happen.
375        ctrl = self.browser.getControl(name='val_id')
376        ctrl.getControl(value='hall-1_A_101_D').selected = True
377        self.browser.getControl("Release selected beds", index=0).click()
378        self.assertMatches(
379          '...No allocated bed selected...', self.browser.contents)
380        # Managers can manually allocate eligible students after cancellation.
381        self.browser.open(self.container_path + '/hall-1/hall-1_A_101_A')
382        # 'not occupied' is not accepted.
383        self.browser.getControl("Save").click()
384        self.assertMatches(
385            "...No valid student id...",
386            self.browser.contents)
387        # Invalid student ids are not accepted.
388        self.browser.getControl(name="form.owner").value = 'nonsense'
389        self.browser.getControl("Save").click()
390        self.assertMatches(
391            "...Either student does not exist or student "
392            "is not in accommodation session...",
393            self.browser.contents)
394        self.browser.getControl(name="form.owner").value = self.student_id
395        self.browser.getControl("Save").click()
396        self.assertMatches("...Form has been saved...", self.browser.contents)
397        # Students can only be allocated once.
398        self.browser.open(self.container_path + '/hall-1/hall-1_A_101_B')
399        self.browser.getControl(name="form.owner").value = self.student_id
400        self.browser.getControl("Save").click()
401        self.assertMatches(
402            "...This student resides in bed hall-1_A_101_A...",
403            self.browser.contents)
404        # If we open the same form again, we will be redirected to hostel
405        # manage page. Beds must be released first before they can be
406        # allocated to other students.
407        self.browser.open(self.container_path + '/hall-1/hall-1_A_101_A')
408        self.assertEqual(self.browser.url,
409            self.container_path + '/hall-1/@@manage#tab2')
410        # Updating the beds again will not affect the allocation and also
411        # the bed numbering remains the same.
412        old_number = self.app['hostels']['hall-1']['hall-1_A_101_A'].bed_number
413        old_owner = self.app['hostels']['hall-1']['hall-1_A_101_A'].owner
414        self.browser.getControl("Update all beds").click()
415        # 8 beds have been removed and re-added, 2 beds remains untouched
416        # because they are occupied.
417        expected = '...8 empty beds removed, 8 beds added, 0 occupied beds modified...'
418        self.assertMatches(expected,self.browser.contents)
419        new_number = self.app['hostels']['hall-1']['hall-1_A_101_A'].bed_number
420        new_owner = self.app['hostels']['hall-1']['hall-1_A_101_A'].owner
421        self.assertEqual(new_number, old_number)
422        self.assertEqual(new_owner, old_owner)
423        # If we change the bed type of an allocated bed, the modification will
424        # be indicated.
425        hall.blocks_for_female = ['B']
426        hall.blocks_for_male = ['A']
427        self.browser.getControl("Update all beds").click()
428        expected = '...8 empty beds removed, 8 beds added, ' + \
429            '2 occupied beds modified (hall-1_A_101_A, hall-1_A_101_E, )...'
430        self.assertMatches(expected,self.browser.contents)
431        new_number = self.app['hostels']['hall-1']['hall-1_A_101_A'].bed_number
432        # Also the number of the bed has changed.
433        self.assertFalse(new_number == old_number)
434        # The number of occupied beds are displayed on container page.
435        self.browser.open(self.container_path)
436        self.assertTrue('2 of 10' in self.browser.contents)
437        # Remove entire hostel.
438        self.browser.open(self.manage_container_path)
439        ctrl = self.browser.getControl(name='val_id')
440        value = ctrl.options[0]
441        ctrl.getControl(value=value).selected = True
442        self.browser.getControl("Remove selected", index=0).click()
443        self.assertTrue('Successfully removed' in self.browser.contents)
444        # Catalog is empty.
445        results = cat.searchResults(
446            bed_type=('regular_female_all', 'regular_female_all'))
447        results = [x for x in results]
448        assert len(results) == 0
449        # Actions are logged.
450        logcontent = open(self.logfile).read()
451        self.assertTrue(
452            'hall-1 - 9 empty beds removed, 9 beds added, 1 occupied '
453            'beds modified (hall-1_A_101_E, )'
454            in logcontent)
455
456    def test_clear_hostels(self):
457        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
458        self.browser.open(self.container_path)
459        self.browser.getLink("Manage accommodation").click()
460        self.browser.getControl("Add hostel").click()
461        self.browser.getControl("Create hostel").click()
462        hall = self.app['hostels']['hall-1']
463        hall.blocks_for_female = ['A','B']
464        hall.rooms_per_floor = 1
465        hall.beds_for_fresh = ['A']
466        hall.beds_for_returning = ['B']
467        hall.beds_for_final = ['C']
468        hall.beds_for_all = ['D','E']
469        self.browser.open(self.container_path + '/hall-1/manage')
470        self.browser.getControl("Update all beds").click()
471        cat = queryUtility(ICatalog, name='beds_catalog')
472        results = cat.searchResults(bed_type=(None, None))
473        self.assertEqual(len(results), 11)
474        self.browser.getControl("Clear hostel").click()
475        self.assertEqual(len(self.app['hostels']['hall-1']), 0)
476        # Only the bed in hall-x remains in the catalog.
477        results = cat.searchResults(bed_type=(None, None))
478        self.assertEqual(len(results), 1)
479        # We can clear all hostels at the same time.
480        self.browser.open(self.manage_container_path)
481        self.browser.getControl("Clear all hostels").click()
482        results = cat.searchResults(bed_type=(None, None))
483        self.assertEqual(len(results), 0)
484        # Both actions have been logged.
485        logcontent = open(self.logfile).read()
486        self.assertTrue('INFO - zope.mgr - hostels.browser.HostelManageFormPage'
487                        ' - hall-1 - cleared' in logcontent)
488        self.assertTrue('zope.mgr - hostels.browser.HostelsContainerManagePage'
489                        ' - hostels - all hostels cleared' in logcontent)
490
491class ExportTests(HostelsFullSetup):
492
493    layer = FunctionalLayer
494
495    def setUp(self):
496        super(ExportTests, self).setUp()
497        self.workdir = tempfile.mkdtemp()
498        self.outfile = os.path.join(self.workdir, 'myoutput.csv')
499        return
500
501    def test_export_hostels(self):
502        exporter = HostelExporter()
503        exporter.export_all(self.app, self.outfile)
504        result = open(self.outfile, 'rb').read()
505        self.assertEqual(
506            result,
507            'beds_for_all,beds_for_final,beds_for_fresh,beds_for_pre,'
508            'beds_for_returning,blocks_for_female,'
509            'blocks_for_male,floors_per_block,hostel_id,hostel_name,maint_fee,'
510            'rooms_per_floor,sort_id,special_handling\r\n[],[],[],[],[],[],[],'
511            '1,hall-x,Hall 1,0.0,2,10,regular\r\n'
512            )
513        return
514
515    def test_export_beds(self):
516        exporter = BedExporter()
517        exporter.export_all(self.app, self.outfile)
518        result = open(self.outfile, 'rb').read()
519        self.assertEqual(
520            result,
521            'bed_id,bed_number,bed_type,owner,hall,block,room,bed,'
522            'special_handling,sex,bt\r\nhall_block_room_bed,1,a_b_c,,'
523            'hall,block,room,bed,a,b,c\r\n'
524            )
525        return
526
527    def tearDown(self):
528        super(ExportTests, self).tearDown()
529        clearSite()
530        shutil.rmtree(os.path.dirname(self.outfile))
531
532class HostelBedProcessorTest(HostelsFullSetup):
533
534    layer = FunctionalLayer
535
536    def test_import(self):
537        self.processor = HostelProcessor()
538        self.workdir = tempfile.mkdtemp()
539        self.csv_file = os.path.join(self.workdir, 'sample_hostel_data.csv')
540        open(self.csv_file, 'wb').write(HOSTEL_SAMPLE_DATA)
541        num, num_warns, fin_file, fail_file = self.processor.doImport(
542            self.csv_file, HOSTEL_HEADER_FIELDS)
543        self.assertEqual(num_warns,0)
544        self.assertEqual(len(self.app['hostels'].keys()), 11) # including hall-x
545        self.assertEqual(self.app['hostels'][
546            'block-a-upper-hostel'].hostel_id,'block-a-upper-hostel')
547        self.assertEqual(self.app['hostels'][
548            'block-a-upper-hostel'].beds_for_final, ['A', 'B'])
549        logcontent = open(self.logfile).read()
550        self.assertTrue(
551            "Hostel Processor - sample_hostel_data - block-a-upper-hostel - "
552            "updated: "
553            "beds_for_pre=['G'], floors_per_block=1, "
554            "special_handling=regular, "
555            "beds_for_final=['A', 'B'], rooms_per_floor=32, "
556            "hostel_id=block-a-upper-hostel, "
557            "sort_id=20, beds_for_returning=['C', 'D'], "
558            "hostel_name=Block A Upper Hostel, beds_for_fresh=['E', 'F'], "
559            "blocks_for_female=['A']"
560            in logcontent)
561        shutil.rmtree(os.path.dirname(fin_file))
562        shutil.rmtree(self.workdir)
563        # The manage page can be opened.
564        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
565        self.browser.open(self.container_path + '/block-a-upper-hostel')
566        self.browser.getLink("Manage").click()
567        self.assertEqual(self.browser.headers['Status'], '200 Ok')
568        return
569
570    def test_import_update_hostel_and_beds(self):
571        self.processor = HostelProcessor()
572        self.workdir = tempfile.mkdtemp()
573        self.csv_file = os.path.join(self.workdir, 'sample_hostel_data.csv')
574        open(self.csv_file, 'wb').write(HOSTEL_SAMPLE_DATA)
575        num, num_warns, fin_file, fail_file = self.processor.doImport(
576            self.csv_file, HOSTEL_HEADER_FIELDS)
577        # We import the same file in update mode
578        num, num_warns, fin_file, fail_file = self.processor.doImport(
579            self.csv_file, HOSTEL_HEADER_FIELDS, 'update')
580        self.assertEqual(num_warns,0)
581        logcontent = open(self.logfile).read()
582        self.assertTrue(
583            "Hostel Processor - sample_hostel_data - block-a-upper-hostel - "
584            "updated: "
585            "beds_for_pre=['G'], floors_per_block=1, "
586            "special_handling=regular, "
587            "beds_for_final=['A', 'B'], rooms_per_floor=32, "
588            "hostel_id=block-a-upper-hostel, "
589            "sort_id=20, beds_for_returning=['C', 'D'], "
590            "hostel_name=Block A Upper Hostel, beds_for_fresh=['E', 'F'], "
591            "blocks_for_female=['A']"
592            in logcontent)
593        # Update the beds of first hostel
594        self.app['hostels']['block-a-upper-hostel'].updateBeds()
595        # Import beds
596        self.processor = BedProcessor()
597        self.csv_file = os.path.join(self.workdir, 'sample_bed_data.csv')
598        open(self.csv_file, 'wb').write(BED_SAMPLE_DATA)
599        num, num_warns, fin_file, fail_file = self.processor.doImport(
600            self.csv_file, BED_HEADER_FIELDS, 'update')
601        self.assertEqual(num_warns,2)
602        fail_file_content = open(fail_file).read()
603        logcontent = open(self.logfile).read()
604        self.assertEqual(
605            'owner,bed_id,hostel_id,reserved,--ERRORS--\r\n'
606            '<IGNORE>,block-a-upper-hostel_A_101_C,block-a-upper-hostel,2,'
607            'reserved: invalid value\r\n'
608            'K999,block-a-upper-hostel_A_101_E,block-a-upper-hostel,0,'
609            'owner: student does not exist\r\n',
610            fail_file_content)
611        self.assertTrue(
612            'system - Bed Processor (update only) - sample_bed_data - '
613            'block-a-upper-hostel_A_101_A - updated: nothing'
614            in logcontent)
615        self.assertTrue(
616            'system - Bed Processor (update only) - sample_bed_data - '
617            'block-a-upper-hostel_A_101_B - updated: reserved'
618            in logcontent)
619        self.assertTrue(
620            'system - Bed Processor (update only) - sample_bed_data - '
621            'block-a-upper-hostel_A_101_D - updated: owner=K1000000'
622            in logcontent)
623        self.assertEqual(
624            self.app['hostels']['block-a-upper-hostel']
625                    ['block-a-upper-hostel_A_101_D'].owner, 'K1000000')
626        self.assertEqual(
627            self.app['hostels']['block-a-upper-hostel']
628                    ['block-a-upper-hostel_A_101_B'].bed_type,
629                    'regular_female_reserved')
630        shutil.rmtree(os.path.dirname(fin_file))
631        shutil.rmtree(self.workdir)
632        return
Note: See TracBrowser for help on using the repository browser.