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

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

We need an itemTag for the list of reserved beds.

Change tests accordingly.

  • Property svn:keywords set to Id
File size: 14.7 KB
RevLine 
[7195]1## $Id: tests.py 7802 2012-03-08 14:26: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"""
[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'
[7802]248        self.assertTrue('<div>A_101_A</div>' in self.browser.contents)
249
[6985]250        # Change hostel configuration
251        hall.beds_for_all = ['D']
252        self.browser.getControl("Update all beds").click()
[6988]253        expected = '...10 empty beds removed, 8 beds added, 0 occupied beds modified...'
[6985]254        self.assertMatches(expected,self.browser.contents)
255        results = cat.searchResults(
256            bed_type=('regular_female_all', 'regular_female_all'))
257        results = [x for x in results]
[6988]258        assert len(results) == 1
259        # Unreserve bed
260        ctrl = self.browser.getControl(name='val_id')
261        ctrl.getControl(value='hall-1_A_101_A').selected = True
262        ctrl.getControl(value='hall-1_A_101_B').selected = True
263        ctrl.getControl(value='hall-1_A_101_C').selected = True
264        ctrl.getControl(value='hall-1_A_101_D').selected = True
265        self.browser.getControl("Switch reservation", index=0).click()
266        assert self.app['hostels']['hall-1'][
267            'hall-1_A_101_D'].bed_type == 'regular_female_all'
268        self.assertFalse(expected in self.browser.contents)
[7045]269        # Release bed which has previously been booked
270        bedticket = BedTicket()
271        bedticket.ticket_id = u'2004'
272        bedticket.bed_coordinates = u'anything'
273        self.student['accommodation'].addBedTicket(bedticket)
274        self.app['hostels']['hall-1']['hall-1_A_101_D'].owner = self.student_id
275        self.browser.open(self.container_path + '/hall-1/manage')
276        ctrl = self.browser.getControl(name='val_id')
[7068]277        self.browser.getControl("Release selected beds", index=0).click()
278        self.assertMatches("...No item selected...", self.browser.contents)
279        ctrl = self.browser.getControl(name='val_id')
[7045]280        ctrl.getControl(value='hall-1_A_101_D').selected = True
281        self.browser.getControl("Release selected beds", index=0).click()
282        self.assertMatches(
283          '...Successfully released beds: hall-1_A_101_D (%s)...' % self.student_id,
284          self.browser.contents)
285        self.assertMatches(bedticket.bed_coordinates,
286          u' -- booking cancelled on <YYYY-MM-DD hh:mm:ss> --')
[7070]287        # If we release a free be, nothing will happen
288        ctrl = self.browser.getControl(name='val_id')
289        ctrl.getControl(value='hall-1_A_101_D').selected = True
290        self.browser.getControl("Release selected beds", index=0).click()
291        self.assertMatches(
292          '...No allocated bed selected...', self.browser.contents)
[7068]293        # Managers can manually allocate studenst after cancellation
294        self.browser.open(self.container_path + '/hall-1/hall-1_A_101_A')
295        self.browser.getControl(name="form.owner").value = [self.student_id]
296        self.browser.getControl("Save").click()
297        self.assertMatches("...Form has been saved...", self.browser.contents)
[7070]298        # If we open the same form again, we will be redirected to hostel
299        # manage page. Beds must be released first before they can be
300        # allocated to other students.
301        self.browser.open(self.container_path + '/hall-1/hall-1_A_101_A')
302        self.assertEqual(self.browser.url,
[7484]303            self.container_path + '/hall-1/@@manage?tab2')
[7070]304        # Updating the beds again will not affect the allocation and also
305        # the bed numbering remains the same
306        old_number = self.app['hostels']['hall-1']['hall-1_A_101_A'].bed_number
307        old_owner = self.app['hostels']['hall-1']['hall-1_A_101_A'].owner
308        self.browser.getControl("Update all beds").click()
309        # 7 beds have been removed and re-added, 1 bed remains untouched
310        expected = '...7 empty beds removed, 7 beds added, 0 occupied beds modified...'
311        self.assertMatches(expected,self.browser.contents)
312        new_number = self.app['hostels']['hall-1']['hall-1_A_101_A'].bed_number
313        new_owner = self.app['hostels']['hall-1']['hall-1_A_101_A'].owner
314        self.assertEqual(new_number, old_number)
315        self.assertEqual(new_owner, old_owner)
316        # If we change the bed type of an allocated bed, the modification will
317        # be indicated
318        hall.blocks_for_female = ['B']
319        hall.blocks_for_male = ['A']
320        self.browser.getControl("Update all beds").click()
321        expected = '...7 empty beds removed, 7 beds added, ' + \
322            '1 occupied beds modified (hall-1_A_101_A )...'
323        self.assertMatches(expected,self.browser.contents)
324        new_number = self.app['hostels']['hall-1']['hall-1_A_101_A'].bed_number
325        # Also the number of the bed has changed.
326        self.assertFalse(new_number == old_number)
[6985]327        # Remove entire hostel
[6962]328        self.browser.open(self.manage_container_path)
329        ctrl = self.browser.getControl(name='val_id')
330        value = ctrl.options[0]
331        ctrl.getControl(value=value).selected = True
332        self.browser.getControl("Remove selected", index=0).click()
333        self.assertTrue('Successfully removed' in self.browser.contents)
[6985]334        # Catalog is empty
335        results = cat.searchResults(
336            bed_type=('regular_female_all', 'regular_female_all'))
337        results = [x for x in results]
338        assert len(results) == 0
Note: See TracBrowser for help on using the repository browser.