source: main/waeup.sirp/trunk/src/waeup/sirp/hostels/tests.py @ 7720

Last change on this file since 7720 was 7718, checked in by Henrik Bettermann, 13 years ago

Internationalize hostels package.

Remove exception catcher in switchReservations and corresponding test.

When testing the hostel configuration manually I found out that the beds_reserved list attribute of halls
only changed during the lifetime of a running instance. After restarting the portal all changes were gone.
Also "hostel._p_changed = True" didn't help. The only solution was to reassign the attribute to ensure persistance.

Unfortunately, the current tests don't catch such a malfunction. This has to be improved.

  • Property svn:keywords set to Id
File size: 14.7 KB
RevLine 
[7195]1## $Id: tests.py 7718 2012-02-28 19:34:51Z 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"""
[6961]21import shutil
22import tempfile
[7003]23import grok
24from zope.event import notify
25
[6951]26from zope.interface.verify import verifyClass, verifyObject
[6961]27from zope.component.hooks import setSite, clearSite
28from zope.testbrowser.testing import Browser
29from zope.security.interfaces import Unauthorized
[6972]30from zope.catalog.interfaces import ICatalog
31from zope.component import queryUtility
[6961]32from waeup.sirp.app import University
[6951]33from waeup.sirp.hostels.interfaces import (
[6963]34    IHostelsContainer, IHostel, IBed)
[6951]35from waeup.sirp.hostels.container import HostelsContainer
[6963]36from waeup.sirp.hostels.hostel import Hostel, Bed
[6951]37from waeup.sirp.testing import (FunctionalLayer, FunctionalTestCase)
[7045]38from waeup.sirp.students.student import Student
39from waeup.sirp.students.accommodation import BedTicket
[7077]40from waeup.sirp.university.department import Department
[6951]41
42class HostelsContainerTestCase(FunctionalTestCase):
43
44    layer = FunctionalLayer
45
46    def test_interfaces(self):
47        # Make sure the correct interfaces are implemented.
48        self.assertTrue(
49            verifyClass(
50                IHostelsContainer, HostelsContainer)
51            )
52        self.assertTrue(
53            verifyObject(
54                IHostelsContainer, HostelsContainer())
55            )
56        self.assertTrue(
57            verifyClass(
58                IHostel, Hostel)
59            )
60        self.assertTrue(
61            verifyObject(
62                IHostel, Hostel())
63            )
[6963]64        self.assertTrue(
65            verifyClass(
66                IBed, Bed)
67            )
68        self.assertTrue(
69            verifyObject(
70                IBed, Bed())
71            )
[6951]72        return
73
74    def test_base(self):
75        # We cannot call the fundamental methods of a base in that case
76        container = HostelsContainer()
[7077]77        hostel = Hostel()
[6951]78        self.assertRaises(
79            NotImplementedError, container.archive)
80        self.assertRaises(
81            NotImplementedError, container.clear)
[7077]82        # We cannot add arbitrary objects
83        department = Department()
84        self.assertRaises(
85            TypeError, container.addHostel, department)
86        self.assertRaises(
87            TypeError, hostel.addBed, department)
[6961]88
89class HostelsFullSetup(FunctionalTestCase):
90
91    def setUp(self):
92        super(HostelsFullSetup, self).setUp()
93
94        # Setup a sample site for each test
95        app = University()
96        self.dc_root = tempfile.mkdtemp()
97        app['datacenter'].setStoragePath(self.dc_root)
98
99        # Prepopulate the ZODB...
100        self.getRootFolder()['app'] = app
101        # we add the site immediately after creation to the
102        # ZODB. Catalogs and other local utilities are not setup
103        # before that step.
104        self.app = self.getRootFolder()['app']
105        # Set site here. Some of the following setup code might need
106        # to access grok.getSite() and should get our new app then
107        setSite(app)
108
[7045]109        # Add student with subobjects
110        student = Student()
[7357]111        student.firstname = u'Anna'
112        student.lastname = u'Tester'
[7045]113        student.reg_number = u'123'
114        student.matric_number = u'234'
115        student.sex = u'f'
116        self.app['students'].addStudent(student)
117        self.student_id = student.student_id
118        self.student = self.app['students'][self.student_id]
119        self.student['studycourse'].current_session = 2004
120        self.student['studycourse'].entry_session = 2004
[7068]121        # The students_catalog must be informed that the
122        # session attribute has changed
123        notify(grok.ObjectModifiedEvent(self.student))
[7045]124
125        # Set accommodation_session
126        self.app['configuration'].accommodation_session = 2004
127
[6972]128        # Create a hostel
129        hostel = Hostel()
[6973]130        hostel.hostel_id = u'hall-x'
[6972]131        self.app['hostels'][hostel.hostel_id] = hostel
132
133        # Create a bed
134        bed = Bed()
135        bed.bed_id = u'xyz'
136        bed.bed_number = 1
137        bed.bed_type = u'abc'
138        self.app['hostels'][hostel.hostel_id][bed.bed_id] = bed
139
[6961]140        self.container_path = 'http://localhost/app/hostels'
[7068]141        self.student_path = 'http://localhost/app/students/%s' % self.student_id
[6961]142        self.manage_container_path = self.container_path + '/@@manage'
143        self.add_hostel_path = self.container_path + '/addhostel'
144
145        # Put the prepopulated site into test ZODB and prepare test
146        # browser
147        self.browser = Browser()
148        self.browser.handleErrors = False
149
150    def tearDown(self):
151        super(HostelsFullSetup, self).tearDown()
152        clearSite()
153        shutil.rmtree(self.dc_root)
154
[6972]155class BedCatalogTests(HostelsFullSetup):
156
157    layer = FunctionalLayer
158
159    def test_get_catalog(self):
[7045]160        # We can get a beds catalog if we wish
[6972]161        cat = queryUtility(ICatalog, name='beds_catalog')
162        assert cat is not None
163
164    def test_search_by_type(self):
165        # We can find a certain bed
166        cat = queryUtility(ICatalog, name='beds_catalog')
[7003]167        results = cat.searchResults(bed_type=(u'abc', u'abc'))
[6972]168        results = [x for x in results] # Turn results generator into list
169        assert len(results) == 1
[6973]170        assert results[0] is self.app['hostels']['hall-x']['xyz']
[6972]171
[7003]172    def test_search_by_owner(self):
173        # We can find a certain bed
174        myobj = self.app['hostels']['hall-x']['xyz']
175        myobj.owner = u'abc'
176        notify(grok.ObjectModifiedEvent(myobj))
177        cat = queryUtility(ICatalog, name='beds_catalog')
178        results = cat.searchResults(owner=(u'abc', u'abc'))
179        results = [x for x in results] # Turn results generator into list
180        assert len(results) == 1
181        assert results[0] is self.app['hostels']['hall-x']['xyz']
182
[6961]183class HostelsUITests(HostelsFullSetup):
184
185    layer = FunctionalLayer
186
187    def test_anonymous_access(self):
188        # Anonymous users can't access hostels containers
189        self.assertRaises(
190            Unauthorized, self.browser.open, self.manage_container_path)
191        return
192
[6985]193    def test_add_search_edit_delete_manage_hostels(self):
[6961]194        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
195        self.browser.open(self.container_path)
196        self.browser.getLink("Manage accommodation").click()
197        self.assertEqual(self.browser.headers['Status'], '200 Ok')
198        self.assertEqual(self.browser.url, self.manage_container_path)
199        self.browser.getControl("Add hostel").click()
200        self.assertEqual(self.browser.headers['Status'], '200 Ok')
201        self.assertEqual(self.browser.url, self.add_hostel_path)
202        self.browser.getControl("Create hostel").click()
203        self.assertEqual(self.browser.headers['Status'], '200 Ok')
204        self.assertTrue('Hostel created' in self.browser.contents)
[6988]205        self.browser.open(self.container_path + '/addhostel')
206        self.browser.getControl("Create hostel").click()
207        self.assertTrue('The hostel already exists' in self.browser.contents)
[6973]208        hall = self.app['hostels']['hall-1']
[6961]209        hall.blocks_for_female = ['A','B']
[6973]210        self.browser.open(self.container_path + '/hall-1')
[6961]211        expected = '''...<ul id="form.blocks_for_female" ><li>Block A</li>
212<li>Block B</li></ul>...'''
213        self.assertMatches(expected,self.browser.contents)
[6973]214        self.browser.open(self.container_path + '/hall-1/manage')
[6985]215        self.browser.getControl(name="form.rooms_per_floor").value = '1'
[6962]216        self.browser.getControl("Save").click()
217        self.assertTrue('Form has been saved' in self.browser.contents)
[6985]218        # Since the testbrowser does not support Javascrip the
219        # save action cleared the settings above and we have to set them
220        # again
221        self.assertTrue(len(hall.blocks_for_female) == 0)
222        hall.blocks_for_female = ['A','B']
[6988]223        hall.beds_for_fresh = ['A']
224        hall.beds_for_returning = ['B']
225        hall.beds_for_final = ['C']
[6985]226        hall.beds_for_all = ['D','E']
227        self.browser.getControl("Update all beds").click()
[6988]228        expected = '...0 empty beds removed, 10 beds added, 0 occupied beds modified ()...'
[6985]229        self.assertMatches(expected,self.browser.contents)
230        cat = queryUtility(ICatalog, name='beds_catalog')
231        results = cat.searchResults(
232            bed_type=('regular_female_all', 'regular_female_all'))
233        results = [x for x in results]
234        assert len(results) == 4
[6988]235        # Reserve bed
236        self.browser.getControl("Switch reservation", index=0).click()
237        self.assertTrue('No item selected' in self.browser.contents)
[6985]238        ctrl = self.browser.getControl(name='val_id')
[6988]239        ctrl.getControl(value='hall-1_A_101_A').selected = True
240        ctrl.getControl(value='hall-1_A_101_B').selected = True
241        ctrl.getControl(value='hall-1_A_101_C').selected = True
[6985]242        ctrl.getControl(value='hall-1_A_101_D').selected = True
243        self.browser.getControl("Switch reservation", index=0).click()
[6988]244        self.assertTrue('Successfully switched beds: hall-1_A_101_A (reserved)'
[6985]245            in self.browser.contents)
[6988]246        assert self.app['hostels']['hall-1'][
[6985]247            'hall-1_A_101_D'].bed_type == 'regular_female_reserved'
[7718]248        self.assertTrue('<li>A_101_A</li>' in self.browser.contents)
[6985]249        # Change hostel configuration
250        hall.beds_for_all = ['D']
251        self.browser.getControl("Update all beds").click()
[6988]252        expected = '...10 empty beds removed, 8 beds added, 0 occupied beds modified...'
[6985]253        self.assertMatches(expected,self.browser.contents)
254        results = cat.searchResults(
255            bed_type=('regular_female_all', 'regular_female_all'))
256        results = [x for x in results]
[6988]257        assert len(results) == 1
258        # Unreserve bed
259        ctrl = self.browser.getControl(name='val_id')
260        ctrl.getControl(value='hall-1_A_101_A').selected = True
261        ctrl.getControl(value='hall-1_A_101_B').selected = True
262        ctrl.getControl(value='hall-1_A_101_C').selected = True
263        ctrl.getControl(value='hall-1_A_101_D').selected = True
264        self.browser.getControl("Switch reservation", index=0).click()
265        assert self.app['hostels']['hall-1'][
266            'hall-1_A_101_D'].bed_type == 'regular_female_all'
267        self.assertFalse(expected in self.browser.contents)
[7045]268        # Release bed which has previously been booked
269        bedticket = BedTicket()
270        bedticket.ticket_id = u'2004'
271        bedticket.bed_coordinates = u'anything'
272        self.student['accommodation'].addBedTicket(bedticket)
273        self.app['hostels']['hall-1']['hall-1_A_101_D'].owner = self.student_id
274        self.browser.open(self.container_path + '/hall-1/manage')
275        ctrl = self.browser.getControl(name='val_id')
[7068]276        self.browser.getControl("Release selected beds", index=0).click()
277        self.assertMatches("...No item selected...", self.browser.contents)
278        ctrl = self.browser.getControl(name='val_id')
[7045]279        ctrl.getControl(value='hall-1_A_101_D').selected = True
280        self.browser.getControl("Release selected beds", index=0).click()
281        self.assertMatches(
282          '...Successfully released beds: hall-1_A_101_D (%s)...' % self.student_id,
283          self.browser.contents)
284        self.assertMatches(bedticket.bed_coordinates,
285          u' -- booking cancelled on <YYYY-MM-DD hh:mm:ss> --')
[7070]286        # If we release a free be, nothing will happen
287        ctrl = self.browser.getControl(name='val_id')
288        ctrl.getControl(value='hall-1_A_101_D').selected = True
289        self.browser.getControl("Release selected beds", index=0).click()
290        self.assertMatches(
291          '...No allocated bed selected...', self.browser.contents)
[7068]292        # Managers can manually allocate studenst after cancellation
293        self.browser.open(self.container_path + '/hall-1/hall-1_A_101_A')
294        self.browser.getControl(name="form.owner").value = [self.student_id]
295        self.browser.getControl("Save").click()
296        self.assertMatches("...Form has been saved...", self.browser.contents)
[7070]297        # If we open the same form again, we will be redirected to hostel
298        # manage page. Beds must be released first before they can be
299        # allocated to other students.
300        self.browser.open(self.container_path + '/hall-1/hall-1_A_101_A')
301        self.assertEqual(self.browser.url,
[7484]302            self.container_path + '/hall-1/@@manage?tab2')
[7070]303        # Updating the beds again will not affect the allocation and also
304        # the bed numbering remains the same
305        old_number = self.app['hostels']['hall-1']['hall-1_A_101_A'].bed_number
306        old_owner = self.app['hostels']['hall-1']['hall-1_A_101_A'].owner
307        self.browser.getControl("Update all beds").click()
308        # 7 beds have been removed and re-added, 1 bed remains untouched
309        expected = '...7 empty beds removed, 7 beds added, 0 occupied beds modified...'
310        self.assertMatches(expected,self.browser.contents)
311        new_number = self.app['hostels']['hall-1']['hall-1_A_101_A'].bed_number
312        new_owner = self.app['hostels']['hall-1']['hall-1_A_101_A'].owner
313        self.assertEqual(new_number, old_number)
314        self.assertEqual(new_owner, old_owner)
315        # If we change the bed type of an allocated bed, the modification will
316        # be indicated
317        hall.blocks_for_female = ['B']
318        hall.blocks_for_male = ['A']
319        self.browser.getControl("Update all beds").click()
320        expected = '...7 empty beds removed, 7 beds added, ' + \
321            '1 occupied beds modified (hall-1_A_101_A )...'
322        self.assertMatches(expected,self.browser.contents)
323        new_number = self.app['hostels']['hall-1']['hall-1_A_101_A'].bed_number
324        # Also the number of the bed has changed.
325        self.assertFalse(new_number == old_number)
[6985]326        # Remove entire hostel
[6962]327        self.browser.open(self.manage_container_path)
328        ctrl = self.browser.getControl(name='val_id')
329        value = ctrl.options[0]
330        ctrl.getControl(value=value).selected = True
331        self.browser.getControl("Remove selected", index=0).click()
332        self.assertTrue('Successfully removed' in self.browser.contents)
[6985]333        # Catalog is empty
334        results = cat.searchResults(
335            bed_type=('regular_female_all', 'regular_female_all'))
336        results = [x for x in results]
337        assert len(results) == 0
Note: See TracBrowser for help on using the repository browser.