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

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

Remove beds_reserved attribute from hostels. Hostels do no longer
contain information about reserved bed spaces.

Use default values for list attributes. Otherwise the hostel manage page cannot be opened after import of hostels.

  • Property svn:keywords set to Id
File size: 26.2 KB
RevLine 
[7195]1## $Id: tests.py 13346 2015-10-26 08:57:30Z 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')
[13176]313        # The catalog has been updated.
[9448]314        results = cat.searchResults(
315            bed_type=('regular_female_all', 'regular_female_all'))
316        results = [(x.bed_id, x.bed_type) for x in results]
317        self.assertEqual(results,
318            [(u'hall-1_A_101_E', u'regular_female_all'),
319             (u'hall-1_B_101_D', u'regular_female_all'),
320             (u'hall-1_B_101_E', u'regular_female_all')])
321        results = cat.searchResults(
322            bed_type=('regular_female_reserved', 'regular_female_reserved'))
323        results = [(x.bed_id, x.bed_type) for x in results]
324        self.assertEqual(results,
325            [(u'hall-1_A_101_A', u'regular_female_reserved'),
326             (u'hall-1_A_101_B', u'regular_female_reserved'),
327             (u'hall-1_A_101_C', u'regular_female_reserved'),
328             (u'hall-1_A_101_D', u'regular_female_reserved')])
[13176]329        # Change hostel configuration with one bed booked.
[9448]330        hall['hall-1_A_101_E'].owner = u'anyid'
331        notify(grok.ObjectModifiedEvent(hall['hall-1_A_101_E']))
332        hall.beds_for_fresh = ['A', 'E']
[6985]333        hall.beds_for_all = ['D']
334        self.browser.getControl("Update all beds").click()
[9448]335        expected = '...9 empty beds removed, 9 beds added, 1 occupied beds modified...'
[6985]336        self.assertMatches(expected,self.browser.contents)
[13176]337        # Updating beds (including booked beds!) does update catalog.
[6985]338        results = cat.searchResults(
339            bed_type=('regular_female_all', 'regular_female_all'))
[9448]340        results = [(x.bed_id, x.bed_type) for x in results]
[13346]341        # The reservation of hall-1_A_101_D has been cancelled.
[9448]342        self.assertEqual(results,
[13346]343            [(u'hall-1_A_101_D', u'regular_female_all'),
344             (u'hall-1_B_101_D', u'regular_female_all')])
[13176]345        # Release bed which has previously been booked.
[7045]346        bedticket = BedTicket()
[9423]347        bedticket.booking_session = 2004
[7045]348        bedticket.bed_coordinates = u'anything'
349        self.student['accommodation'].addBedTicket(bedticket)
350        self.app['hostels']['hall-1']['hall-1_A_101_D'].owner = self.student_id
[13315]351        notify(grok.ObjectModifiedEvent(self.app['hostels']['hall-1']['hall-1_A_101_D']))
[7045]352        self.browser.open(self.container_path + '/hall-1/manage')
353        ctrl = self.browser.getControl(name='val_id')
[7068]354        self.browser.getControl("Release selected beds", index=0).click()
355        self.assertMatches("...No item selected...", self.browser.contents)
356        ctrl = self.browser.getControl(name='val_id')
[7045]357        ctrl.getControl(value='hall-1_A_101_D').selected = True
358        self.browser.getControl("Release selected beds", index=0).click()
359        self.assertMatches(
360          '...Successfully released beds: hall-1_A_101_D (%s)...' % self.student_id,
361          self.browser.contents)
362        self.assertMatches(bedticket.bed_coordinates,
[8234]363          u' -- booking cancelled on <YYYY-MM-DD hh:mm:ss> UTC --')
[13316]364        # The catalog has been updated.
[13315]365        results = cat.searchResults(owner=(self.student_id, self.student_id))
366        assert len(results) == 0
367        # If we release a free bed, nothing will happen.
[7070]368        ctrl = self.browser.getControl(name='val_id')
369        ctrl.getControl(value='hall-1_A_101_D').selected = True
370        self.browser.getControl("Release selected beds", index=0).click()
371        self.assertMatches(
372          '...No allocated bed selected...', self.browser.contents)
[13176]373        # Managers can manually allocate eligible students after cancellation.
[7068]374        self.browser.open(self.container_path + '/hall-1/hall-1_A_101_A')
[13176]375        # 'not occupied' is not accepted.
[9416]376        self.browser.getControl("Save").click()
377        self.assertMatches(
378            "...No valid student id...",
379            self.browser.contents)
[13176]380        # Invalid student ids are not accepted.
[9414]381        self.browser.getControl(name="form.owner").value = 'nonsense'
[7068]382        self.browser.getControl("Save").click()
[9414]383        self.assertMatches(
[9416]384            "...Either student does not exist or student "
385            "is not in accommodation session...",
[9414]386            self.browser.contents)
387        self.browser.getControl(name="form.owner").value = self.student_id
388        self.browser.getControl("Save").click()
[7068]389        self.assertMatches("...Form has been saved...", self.browser.contents)
[13176]390        # Students can only be allocated once.
[9414]391        self.browser.open(self.container_path + '/hall-1/hall-1_A_101_B')
392        self.browser.getControl(name="form.owner").value = self.student_id
393        self.browser.getControl("Save").click()
394        self.assertMatches(
395            "...This student resides in bed hall-1_A_101_A...",
396            self.browser.contents)
[7070]397        # If we open the same form again, we will be redirected to hostel
398        # manage page. Beds must be released first before they can be
399        # allocated to other students.
400        self.browser.open(self.container_path + '/hall-1/hall-1_A_101_A')
401        self.assertEqual(self.browser.url,
[11254]402            self.container_path + '/hall-1/@@manage#tab2')
[7070]403        # Updating the beds again will not affect the allocation and also
[13176]404        # the bed numbering remains the same.
[7070]405        old_number = self.app['hostels']['hall-1']['hall-1_A_101_A'].bed_number
406        old_owner = self.app['hostels']['hall-1']['hall-1_A_101_A'].owner
407        self.browser.getControl("Update all beds").click()
[9448]408        # 8 beds have been removed and re-added, 2 beds remains untouched
[13176]409        # because they are occupied.
[9448]410        expected = '...8 empty beds removed, 8 beds added, 0 occupied beds modified...'
[7070]411        self.assertMatches(expected,self.browser.contents)
412        new_number = self.app['hostels']['hall-1']['hall-1_A_101_A'].bed_number
413        new_owner = self.app['hostels']['hall-1']['hall-1_A_101_A'].owner
414        self.assertEqual(new_number, old_number)
415        self.assertEqual(new_owner, old_owner)
416        # If we change the bed type of an allocated bed, the modification will
[13176]417        # be indicated.
[7070]418        hall.blocks_for_female = ['B']
419        hall.blocks_for_male = ['A']
420        self.browser.getControl("Update all beds").click()
[9448]421        expected = '...8 empty beds removed, 8 beds added, ' + \
422            '2 occupied beds modified (hall-1_A_101_A, hall-1_A_101_E, )...'
[7070]423        self.assertMatches(expected,self.browser.contents)
424        new_number = self.app['hostels']['hall-1']['hall-1_A_101_A'].bed_number
425        # Also the number of the bed has changed.
426        self.assertFalse(new_number == old_number)
[9414]427        # The number of occupied beds are displayed on container page.
[9196]428        self.browser.open(self.container_path)
[9448]429        self.assertTrue('2 of 10' in self.browser.contents)
[13176]430        # Remove entire hostel.
[6962]431        self.browser.open(self.manage_container_path)
432        ctrl = self.browser.getControl(name='val_id')
433        value = ctrl.options[0]
434        ctrl.getControl(value=value).selected = True
435        self.browser.getControl("Remove selected", index=0).click()
436        self.assertTrue('Successfully removed' in self.browser.contents)
[13176]437        # Catalog is empty.
[6985]438        results = cat.searchResults(
439            bed_type=('regular_female_all', 'regular_female_all'))
440        results = [x for x in results]
441        assert len(results) == 0
[12894]442        # Actions are logged.
443        logcontent = open(self.logfile).read()
444        self.assertTrue(
445            'hall-1 - 9 empty beds removed, 9 beds added, 1 occupied '
446            'beds modified (hall-1_A_101_E, )'
447            in logcontent)
[9197]448
449    def test_clear_hostels(self):
450        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
451        self.browser.open(self.container_path)
452        self.browser.getLink("Manage accommodation").click()
453        self.browser.getControl("Add hostel").click()
454        self.browser.getControl("Create hostel").click()
455        hall = self.app['hostels']['hall-1']
456        hall.blocks_for_female = ['A','B']
457        hall.rooms_per_floor = 1
458        hall.beds_for_fresh = ['A']
459        hall.beds_for_returning = ['B']
460        hall.beds_for_final = ['C']
461        hall.beds_for_all = ['D','E']
462        self.browser.open(self.container_path + '/hall-1/manage')
463        self.browser.getControl("Update all beds").click()
464        cat = queryUtility(ICatalog, name='beds_catalog')
465        results = cat.searchResults(bed_type=(None, None))
466        self.assertEqual(len(results), 11)
467        self.browser.getControl("Clear hostel").click()
468        self.assertEqual(len(self.app['hostels']['hall-1']), 0)
469        # Only the bed in hall-x remains in the catalog.
470        results = cat.searchResults(bed_type=(None, None))
471        self.assertEqual(len(results), 1)
472        # We can clear all hostels at the same time.
473        self.browser.open(self.manage_container_path)
474        self.browser.getControl("Clear all hostels").click()
475        results = cat.searchResults(bed_type=(None, None))
476        self.assertEqual(len(results), 0)
477        # Both actions have been logged.
[9202]478        logcontent = open(self.logfile).read()
[9197]479        self.assertTrue('INFO - zope.mgr - hostels.browser.HostelManageFormPage'
480                        ' - hall-1 - cleared' in logcontent)
481        self.assertTrue('zope.mgr - hostels.browser.HostelsContainerManagePage'
482                        ' - hostels - all hostels cleared' in logcontent)
[9200]483
484class ExportTests(HostelsFullSetup):
485
486    layer = FunctionalLayer
487
488    def setUp(self):
489        super(ExportTests, self).setUp()
490        self.workdir = tempfile.mkdtemp()
491        self.outfile = os.path.join(self.workdir, 'myoutput.csv')
492        return
493
494    def test_export_hostels(self):
495        exporter = HostelExporter()
496        exporter.export_all(self.app, self.outfile)
497        result = open(self.outfile, 'rb').read()
498        self.assertEqual(
499            result,
500            'beds_for_all,beds_for_final,beds_for_fresh,beds_for_pre,'
[13346]501            'beds_for_returning,blocks_for_female,'
[10680]502            'blocks_for_male,floors_per_block,hostel_id,hostel_name,maint_fee,'
[13346]503            'rooms_per_floor,sort_id,special_handling\r\n[],[],[],[],[],[],[],'
504            '1,hall-x,Hall 1,0.0,2,10,regular\r\n'
[9200]505            )
506        return
507
508    def test_export_beds(self):
509        exporter = BedExporter()
510        exporter.export_all(self.app, self.outfile)
511        result = open(self.outfile, 'rb').read()
512        self.assertEqual(
513            result,
514            'bed_id,bed_number,bed_type,owner,hall,block,room,bed,'
515            'special_handling,sex,bt\r\nhall_block_room_bed,1,a_b_c,,'
516            'hall,block,room,bed,a,b,c\r\n'
517            )
[9202]518        return
519
[9283]520    def tearDown(self):
521        super(ExportTests, self).tearDown()
522        clearSite()
523        shutil.rmtree(os.path.dirname(self.outfile))
524
[9202]525class HostelProcessorTest(HostelsFullSetup):
526
527    layer = FunctionalLayer
528
529    def test_import(self):
530        self.processor = HostelProcessor()
531        self.workdir = tempfile.mkdtemp()
[9283]532        self.csv_file = os.path.join(self.workdir, 'sample_hostel_data.csv')
[9202]533        open(self.csv_file, 'wb').write(HOSTEL_SAMPLE_DATA)
534        num, num_warns, fin_file, fail_file = self.processor.doImport(
535            self.csv_file, HOSTEL_HEADER_FIELDS)
536        self.assertEqual(num_warns,0)
537        self.assertEqual(len(self.app['hostels'].keys()), 11) # including hall-x
538        self.assertEqual(self.app['hostels'][
539            'block-a-upper-hostel'].hostel_id,'block-a-upper-hostel')
540        self.assertEqual(self.app['hostels'][
541            'block-a-upper-hostel'].beds_for_final, ['A', 'B'])
542        logcontent = open(self.logfile).read()
543        self.assertTrue(
[9706]544            "Hostel Processor - sample_hostel_data - block-a-upper-hostel - "
545            "updated: "
546            "beds_for_pre=['G'], floors_per_block=1, "
[13346]547            "special_handling=regular, "
[9202]548            "beds_for_final=['A', 'B'], rooms_per_floor=32, "
[12981]549            "hostel_id=block-a-upper-hostel, "
[9202]550            "sort_id=20, beds_for_returning=['C', 'D'], "
551            "hostel_name=Block A Upper Hostel, beds_for_fresh=['E', 'F'], "
[12981]552            "blocks_for_female=['A']"
[9202]553            in logcontent)
554        shutil.rmtree(os.path.dirname(fin_file))
[9283]555        shutil.rmtree(self.workdir)
[13346]556        # The manage page can be opened.
557        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
558        self.browser.open(self.container_path + '/block-a-upper-hostel')
559        self.browser.getLink("Manage").click()
560        self.assertEqual(self.browser.headers['Status'], '200 Ok')
[10683]561        return
562
563    def test_import_update(self):
564        self.processor = HostelProcessor()
565        self.workdir = tempfile.mkdtemp()
566        self.csv_file = os.path.join(self.workdir, 'sample_hostel_data.csv')
567        open(self.csv_file, 'wb').write(HOSTEL_SAMPLE_DATA)
568        self.csv_file = os.path.join(self.workdir, 'sample_hostel_data.csv')
569        open(self.csv_file, 'wb').write(HOSTEL_SAMPLE_DATA)
570        num, num_warns, fin_file, fail_file = self.processor.doImport(
571            self.csv_file, HOSTEL_HEADER_FIELDS)
572        # We import the same file in update mode
573        num, num_warns, fin_file, fail_file = self.processor.doImport(
574            self.csv_file, HOSTEL_HEADER_FIELDS, 'update')
575        self.assertEqual(num_warns,0)
576        logcontent = open(self.logfile).read()
577        self.assertTrue(
578            "Hostel Processor - sample_hostel_data - block-a-upper-hostel - "
579            "updated: "
580            "beds_for_pre=['G'], floors_per_block=1, "
[13346]581            "special_handling=regular, "
[10683]582            "beds_for_final=['A', 'B'], rooms_per_floor=32, "
[12981]583            "hostel_id=block-a-upper-hostel, "
[10683]584            "sort_id=20, beds_for_returning=['C', 'D'], "
585            "hostel_name=Block A Upper Hostel, beds_for_fresh=['E', 'F'], "
[12981]586            "blocks_for_female=['A']"
[10683]587            in logcontent)
588        shutil.rmtree(os.path.dirname(fin_file))
589        shutil.rmtree(self.workdir)
[9200]590        return
Note: See TracBrowser for help on using the repository browser.