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

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

Accommodation session must not be changed if hostels are not empty.

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