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

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

Add event handler which removes bed object from bed ticket if bed is removed.

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