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

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

Add page to release all expired allocations.

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