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

Last change on this file since 7797 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
Line 
1## $Id: tests.py 7718 2012-02-28 19:34:51Z 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 shutil
22import tempfile
23import grok
24from zope.event import notify
25
26from zope.interface.verify import verifyClass, verifyObject
27from zope.component.hooks import setSite, clearSite
28from zope.testbrowser.testing import Browser
29from zope.security.interfaces import Unauthorized
30from zope.catalog.interfaces import ICatalog
31from zope.component import queryUtility
32from waeup.sirp.app import University
33from waeup.sirp.hostels.interfaces import (
34    IHostelsContainer, IHostel, IBed)
35from waeup.sirp.hostels.container import HostelsContainer
36from waeup.sirp.hostels.hostel import Hostel, Bed
37from waeup.sirp.testing import (FunctionalLayer, FunctionalTestCase)
38from waeup.sirp.students.student import Student
39from waeup.sirp.students.accommodation import BedTicket
40from waeup.sirp.university.department import Department
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            )
64        self.assertTrue(
65            verifyClass(
66                IBed, Bed)
67            )
68        self.assertTrue(
69            verifyObject(
70                IBed, Bed())
71            )
72        return
73
74    def test_base(self):
75        # We cannot call the fundamental methods of a base in that case
76        container = HostelsContainer()
77        hostel = Hostel()
78        self.assertRaises(
79            NotImplementedError, container.archive)
80        self.assertRaises(
81            NotImplementedError, container.clear)
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)
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
109        # Add student with subobjects
110        student = Student()
111        student.firstname = u'Anna'
112        student.lastname = u'Tester'
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
121        # The students_catalog must be informed that the
122        # session attribute has changed
123        notify(grok.ObjectModifiedEvent(self.student))
124
125        # Set accommodation_session
126        self.app['configuration'].accommodation_session = 2004
127
128        # Create a hostel
129        hostel = Hostel()
130        hostel.hostel_id = u'hall-x'
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
140        self.container_path = 'http://localhost/app/hostels'
141        self.student_path = 'http://localhost/app/students/%s' % self.student_id
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
155class BedCatalogTests(HostelsFullSetup):
156
157    layer = FunctionalLayer
158
159    def test_get_catalog(self):
160        # We can get a beds catalog if we wish
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')
167        results = cat.searchResults(bed_type=(u'abc', u'abc'))
168        results = [x for x in results] # Turn results generator into list
169        assert len(results) == 1
170        assert results[0] is self.app['hostels']['hall-x']['xyz']
171
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
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
193    def test_add_search_edit_delete_manage_hostels(self):
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)
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)
208        hall = self.app['hostels']['hall-1']
209        hall.blocks_for_female = ['A','B']
210        self.browser.open(self.container_path + '/hall-1')
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)
214        self.browser.open(self.container_path + '/hall-1/manage')
215        self.browser.getControl(name="form.rooms_per_floor").value = '1'
216        self.browser.getControl("Save").click()
217        self.assertTrue('Form has been saved' in self.browser.contents)
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']
223        hall.beds_for_fresh = ['A']
224        hall.beds_for_returning = ['B']
225        hall.beds_for_final = ['C']
226        hall.beds_for_all = ['D','E']
227        self.browser.getControl("Update all beds").click()
228        expected = '...0 empty beds removed, 10 beds added, 0 occupied beds modified ()...'
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
235        # Reserve bed
236        self.browser.getControl("Switch reservation", index=0).click()
237        self.assertTrue('No item selected' in self.browser.contents)
238        ctrl = self.browser.getControl(name='val_id')
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
242        ctrl.getControl(value='hall-1_A_101_D').selected = True
243        self.browser.getControl("Switch reservation", index=0).click()
244        self.assertTrue('Successfully switched beds: hall-1_A_101_A (reserved)'
245            in self.browser.contents)
246        assert self.app['hostels']['hall-1'][
247            'hall-1_A_101_D'].bed_type == 'regular_female_reserved'
248        self.assertTrue('<li>A_101_A</li>' in self.browser.contents)
249        # Change hostel configuration
250        hall.beds_for_all = ['D']
251        self.browser.getControl("Update all beds").click()
252        expected = '...10 empty beds removed, 8 beds added, 0 occupied beds modified...'
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]
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)
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')
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')
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> --')
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)
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)
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,
302            self.container_path + '/hall-1/@@manage?tab2')
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)
326        # Remove entire hostel
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)
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.